From 9c050e95ec8a03d92d0d83f5a941d7fedf78b410 Mon Sep 17 00:00:00 2001 From: Naseer Ahmed Date: Wed, 16 Nov 2011 13:41:37 -0800 Subject: [PATCH] gralloc: Refactor, ion support - Add ION support - Refactor the design Change-Id: I5b067b0aca1235ee8c01c256e025f416bb56f560 --- Android.mk | 8 +- libgralloc-qsd8k/gpu.h | 84 --- libgralloc-qsd8k/gralloc.cpp | 231 ------- libgralloc-qsd8k/tests/Android.mk | 55 -- libgralloc-qsd8k/tests/pmemalloc_test.cpp | 601 ------------------ {libgralloc-qsd8k => libgralloc}/Android.mk | 70 +- .../MODULE_LICENSE_APACHE2 | 0 {libgralloc-qsd8k => libgralloc}/NOTICE | 0 libgralloc/alloc_controller.cpp | 158 +++++ libgralloc/alloc_controller.h | 87 +++ libgralloc/ashmemalloc.cpp | 140 ++++ libgralloc/ashmemalloc.h | 56 ++ .../framebuffer.cpp | 87 ++- {libgralloc-qsd8k => libgralloc}/gpu.cpp | 265 ++------ libgralloc/gpu.h | 81 +++ {libgralloc-qsd8k => libgralloc}/gr.h | 1 + libgralloc/gralloc.cpp | 113 ++++ .../gralloc_priv.h | 14 +- libgralloc/ionalloc.cpp | 249 ++++++++ libgralloc/ionalloc.h | 71 +++ {libgralloc-qsd8k => libgralloc}/mapper.cpp | 194 +++--- libgralloc/memalloc.h | 85 +++ .../pmem_bestfit_alloc.cpp | 6 +- .../pmem_bestfit_alloc.h | 5 +- .../pmemalloc.cpp | 13 +- {libgralloc-qsd8k => libgralloc}/pmemalloc.h | 0 26 files changed, 1316 insertions(+), 1358 deletions(-) delete mode 100755 libgralloc-qsd8k/gpu.h delete mode 100755 libgralloc-qsd8k/gralloc.cpp delete mode 100644 libgralloc-qsd8k/tests/Android.mk delete mode 100644 libgralloc-qsd8k/tests/pmemalloc_test.cpp rename {libgralloc-qsd8k => libgralloc}/Android.mk (51%) rename {libgralloc-qsd8k => libgralloc}/MODULE_LICENSE_APACHE2 (100%) rename {libgralloc-qsd8k => libgralloc}/NOTICE (100%) create mode 100644 libgralloc/alloc_controller.cpp create mode 100644 libgralloc/alloc_controller.h create mode 100644 libgralloc/ashmemalloc.cpp create mode 100644 libgralloc/ashmemalloc.h rename {libgralloc-qsd8k => libgralloc}/framebuffer.cpp (95%) rename {libgralloc-qsd8k => libgralloc}/gpu.cpp (55%) mode change 100755 => 100644 create mode 100644 libgralloc/gpu.h rename {libgralloc-qsd8k => libgralloc}/gr.h (97%) create mode 100644 libgralloc/gralloc.cpp rename {libgralloc-qsd8k => libgralloc}/gralloc_priv.h (96%) mode change 100755 => 100644 create mode 100644 libgralloc/ionalloc.cpp create mode 100644 libgralloc/ionalloc.h rename {libgralloc-qsd8k => libgralloc}/mapper.cpp (69%) mode change 100755 => 100644 create mode 100644 libgralloc/memalloc.h rename libgralloc-qsd8k/allocator.cpp => libgralloc/pmem_bestfit_alloc.cpp (98%) rename libgralloc-qsd8k/allocator.h => libgralloc/pmem_bestfit_alloc.h (97%) rename {libgralloc-qsd8k => libgralloc}/pmemalloc.cpp (96%) mode change 100755 => 100644 rename {libgralloc-qsd8k => libgralloc}/pmemalloc.h (100%) mode change 100755 => 100644 diff --git a/Android.mk b/Android.mk index 0360739..838af1e 100644 --- a/Android.mk +++ b/Android.mk @@ -1 +1,7 @@ -# Empty Android.mk +# Build only new gralloc + +ifeq ($(TARGET_USES_ION),true) + display-hals := libgralloc + include $(call all-named-subdir-makefiles,$(display-hals)) +endif + diff --git a/libgralloc-qsd8k/gpu.h b/libgralloc-qsd8k/gpu.h deleted file mode 100755 index 3ef57d3..0000000 --- a/libgralloc-qsd8k/gpu.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef GRALLOC_QSD8K_GPU_H_ -#define GRALLOC_QSD8K_GPU_H_ - -#include -#include -#include -#include - -#include -#include - -#include "gralloc_priv.h" -#include "pmemalloc.h" - - -class gpu_context_t : public alloc_device_t { - public: - - class Deps { - public: - - virtual ~Deps(); - - // ashmem - virtual int ashmem_create_region(const char *name, size_t size) = 0; - - // POSIX - virtual int close(int fd) = 0; - - // Framebuffer (locally defined) - virtual int mapFrameBufferLocked(struct private_module_t* module) = 0; - virtual int terminateBuffer(gralloc_module_t const* module, - private_handle_t* hnd) = 0; - }; - - gpu_context_t(Deps& deps, PmemAllocator& pmemAllocator, - PmemAllocator& pmemAdspAllocator, const private_module_t* module); - - int gralloc_alloc_framebuffer_locked(size_t size, int usage, - buffer_handle_t* pHandle); - int gralloc_alloc_framebuffer(size_t size, int usage, - buffer_handle_t* pHandle); - int gralloc_alloc_buffer(size_t size, int usage, buffer_handle_t* pHandle, int bufferType, int format, - int width, int height); - int free_impl(private_handle_t const* hnd); - int alloc_impl(int w, int h, int format, int usage, - buffer_handle_t* pHandle, int* pStride, int bufferSize = 0); - - static int gralloc_alloc(alloc_device_t* dev, int w, int h, int format, - int usage, buffer_handle_t* pHandle, int* pStride); - static int gralloc_free(alloc_device_t* dev, buffer_handle_t handle); - static int gralloc_alloc_size(alloc_device_t* dev, int w, int h, int format, - int usage, buffer_handle_t* pHandle, int* pStride, int bufferSize); - static int gralloc_close(struct hw_device_t *dev); - int get_composition_type() const { return compositionType; } - - private: - - Deps& deps; - PmemAllocator& pmemAllocator; - PmemAllocator& pmemAdspAllocator; - int compositionType; - int alloc_ashmem_buffer(size_t size, unsigned int postfix, void** pBase, - int* pOffset, int* pFd); - void getGrallocInformationFromFormat(int inputFormat, int *colorFormat, int *bufferType); -}; - -#endif // GRALLOC_QSD8K_GPU_H diff --git a/libgralloc-qsd8k/gralloc.cpp b/libgralloc-qsd8k/gralloc.cpp deleted file mode 100755 index bfade0a..0000000 --- a/libgralloc-qsd8k/gralloc.cpp +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include - -#include -#include -#include -#include - -#include - -#include "allocator.h" -#include "gr.h" -#include "gpu.h" - -/*****************************************************************************/ - -static int gralloc_alloc_buffer(alloc_device_t* dev, - size_t size, int usage, buffer_handle_t* pHandle); - -/*****************************************************************************/ - -int fb_device_open(const hw_module_t* module, const char* name, - hw_device_t** device); - -static int gralloc_device_open(const hw_module_t* module, const char* name, - hw_device_t** device); - -extern int gralloc_lock(gralloc_module_t const* module, - buffer_handle_t handle, int usage, - int l, int t, int w, int h, - void** vaddr); - -extern int gralloc_unlock(gralloc_module_t const* module, - buffer_handle_t handle); - -extern int gralloc_register_buffer(gralloc_module_t const* module, - buffer_handle_t handle); - -extern int gralloc_unregister_buffer(gralloc_module_t const* module, - buffer_handle_t handle); - -extern int gralloc_perform(struct gralloc_module_t const* module, - int operation, ... ); - -/*****************************************************************************/ - -/* On-device dependency implementation */ -class PmemAllocatorDepsDeviceImpl : public PmemUserspaceAllocator::Deps, - public PmemKernelAllocator::Deps { - - const private_module_t* module; - - virtual size_t getPmemTotalSize(int fd, size_t* size) { - int err = 0; -#ifndef TARGET_MSM7x27 - pmem_region region; - err = ioctl(fd, PMEM_GET_TOTAL_SIZE, ®ion); - if (err == 0) { - *size = region.len; - } -#else -#ifdef USE_ASHMEM - if(module != NULL) - *size = module->info.xres * module->info.yres * 2 * 2; - else - return -ENOMEM; -#else - *size = 23<<20; //23MB for 7x27 -#endif -#endif - return err; - } - - virtual int connectPmem(int fd, int master_fd) { - return ioctl(fd, PMEM_CONNECT, master_fd); - } - - virtual int mapPmem(int fd, int offset, size_t size) { - struct pmem_region sub = { offset, size }; - return ioctl(fd, PMEM_MAP, &sub); - } - - virtual int unmapPmem(int fd, int offset, size_t size) { - struct pmem_region sub = { offset, size }; - return ioctl(fd, PMEM_UNMAP, &sub); - } - - virtual int alignPmem(int fd, size_t size, int align) { - struct pmem_allocation allocation; - allocation.size = size; - allocation.align = align; - return ioctl(fd, PMEM_ALLOCATE_ALIGNED, &allocation); - } - - virtual int cleanPmem(int fd, unsigned long base, int offset, size_t size) { - struct pmem_addr pmem_addr; - pmem_addr.vaddr = base; - pmem_addr.offset = offset; - pmem_addr.length = size; - return ioctl(fd, PMEM_CLEAN_INV_CACHES, &pmem_addr); - } - - virtual int getErrno() { - return errno; - } - - virtual void* mmap(void* start, size_t length, int prot, int flags, int fd, - off_t offset) { - return ::mmap(start, length, prot, flags, fd, offset); - } - - virtual int munmap(void* start, size_t length) { - return ::munmap(start, length); - } - - virtual int open(const char* pathname, int flags, int mode) { - return ::open(pathname, flags, mode); - } - - virtual int close(int fd) { - return ::close(fd); - } - -public: - void setModule(const private_module_t* m) { - module = m; - } - -}; - -class GpuContextDepsDeviceImpl : public gpu_context_t::Deps { - - public: - - virtual int ashmem_create_region(const char *name, size_t size) { - return ::ashmem_create_region(name, size); - } - - virtual int mapFrameBufferLocked(struct private_module_t* module) { - return ::mapFrameBufferLocked(module); - } - - virtual int terminateBuffer(gralloc_module_t const* module, - private_handle_t* hnd) { - return ::terminateBuffer(module, hnd); - } - - virtual int close(int fd) { - return ::close(fd); - } -}; - -static PmemAllocatorDepsDeviceImpl pmemAllocatorDeviceDepsImpl; -static GpuContextDepsDeviceImpl gpuContextDeviceDepsImpl; - -/*****************************************************************************/ - -static SimpleBestFitAllocator pmemAllocMgr; -static PmemUserspaceAllocator pmemAllocator(pmemAllocatorDeviceDepsImpl, pmemAllocMgr, - "/dev/pmem"); - -static PmemKernelAllocator pmemAdspAllocator(pmemAllocatorDeviceDepsImpl); - -/*****************************************************************************/ - -static struct hw_module_methods_t gralloc_module_methods = { - open: gralloc_device_open -}; - -struct private_module_t HAL_MODULE_INFO_SYM = { - base: { - common: { - tag: HARDWARE_MODULE_TAG, - version_major: 1, - version_minor: 0, - id: GRALLOC_HARDWARE_MODULE_ID, - name: "Graphics Memory Allocator Module", - author: "The Android Open Source Project", - methods: &gralloc_module_methods - }, - registerBuffer: gralloc_register_buffer, - unregisterBuffer: gralloc_unregister_buffer, - lock: gralloc_lock, - unlock: gralloc_unlock, - perform: gralloc_perform, - }, - framebuffer: 0, - fbFormat: 0, - flags: 0, - numBuffers: 0, - bufferMask: 0, - lock: PTHREAD_MUTEX_INITIALIZER, - currentBuffer: 0, -}; - -/*****************************************************************************/ - -int gralloc_device_open(const hw_module_t* module, const char* name, - hw_device_t** device) -{ - int status = -EINVAL; - if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) { - const private_module_t* m = reinterpret_cast( - module); - pmemAllocatorDeviceDepsImpl.setModule(m); - gpu_context_t *dev; - dev = new gpu_context_t(gpuContextDeviceDepsImpl, pmemAllocator, - pmemAdspAllocator, m); - *device = &dev->common; - status = 0; - } else { - status = fb_device_open(module, name, device); - } - return status; -} diff --git a/libgralloc-qsd8k/tests/Android.mk b/libgralloc-qsd8k/tests/Android.mk deleted file mode 100644 index b9a7459..0000000 --- a/libgralloc-qsd8k/tests/Android.mk +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright (C) 2008 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -LOCAL_PATH := $(call my-dir) - -# you can use EXTRA_CFLAGS to indicate additional CFLAGS to use -# in the build. The variables will be cleaned on exit -# -# - -libgralloc_test_includes:= \ - bionic/libstdc++/include \ - external/astl/include \ - external/gtest/include \ - $(LOCAL_PATH)/.. - -libgralloc_test_static_libs := \ - libgralloc_qsd8k_host \ - libgtest_main_host \ - libgtest_host \ - libastl_host \ - liblog - -define host-test - $(foreach file,$(1), \ - $(eval include $(CLEAR_VARS)) \ - $(eval LOCAL_CPP_EXTENSION := .cpp) \ - $(eval LOCAL_SRC_FILES := $(file)) \ - $(eval LOCAL_C_INCLUDES := $(libgralloc_test_includes)) \ - $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \ - $(eval LOCAL_CFLAGS += $(EXTRA_CFLAGS)) \ - $(eval LOCAL_LDLIBS += $(EXTRA_LDLIBS)) \ - $(eval LOCAL_STATIC_LIBRARIES := $(libgralloc_test_static_libs)) \ - $(eval LOCAL_MODULE_TAGS := eng tests) \ - $(eval include $(BUILD_HOST_EXECUTABLE)) \ - ) \ - $(eval EXTRA_CFLAGS :=) \ - $(eval EXTRA_LDLIBS :=) -endef - -TEST_SRC_FILES := \ - pmemalloc_test.cpp - -$(call host-test, $(TEST_SRC_FILES)) diff --git a/libgralloc-qsd8k/tests/pmemalloc_test.cpp b/libgralloc-qsd8k/tests/pmemalloc_test.cpp deleted file mode 100644 index 94e86bf..0000000 --- a/libgralloc-qsd8k/tests/pmemalloc_test.cpp +++ /dev/null @@ -1,601 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include -#include -#include -#include - -#include "pmemalloc.h" - -class DepsStub : public PmemUserspaceAllocator::Deps, public PmemKernelAllocator::Deps { - - public: - - virtual size_t getPmemTotalSize(int fd, size_t* size) { - return 0; - } - - virtual int connectPmem(int fd, int master_fd) { - return 0; - } - - virtual int mapPmem(int fd, int offset, size_t size) { - return 0; - } - - virtual int unmapPmem(int fd, int offset, size_t size) { - return 0; - } - - virtual int getErrno() { - return 0; - } - - virtual void* mmap(void* start, size_t length, int prot, int flags, int fd, - off_t offset) { - return 0; - } - - virtual int munmap(void* start, size_t length) { - return 0; - } - - virtual int open(const char* pathname, int flags, int mode) { - return 0; - } - - virtual int close(int fd) { - return 0; - } -}; - -/******************************************************************************/ - -class AllocatorStub : public PmemUserspaceAllocator::Deps::Allocator { - virtual ssize_t setSize(size_t size) { - return 0; - } - - virtual size_t size() const { - return 0; - } - - virtual ssize_t allocate(size_t size, uint32_t flags = 0) { - return 0; - } - - virtual ssize_t deallocate(size_t offset) { - return 0; - } -}; - -/******************************************************************************/ - -static const char* fakePmemDev = "/foo/bar"; - -/******************************************************************************/ - -struct Deps_InitPmemAreaLockedWithSuccessfulCompletion : public DepsStub { - - virtual int open(const char* pathname, int flags, int mode) { - EXPECT_EQ(fakePmemDev, pathname); - EXPECT_EQ(O_RDWR, flags); - EXPECT_EQ(0, mode); - return 1234; - } - - virtual size_t getPmemTotalSize(int fd, size_t* size) { - EXPECT_EQ(1234, fd); - *size = 16 << 20; - return 0; - } - - virtual void* mmap(void* start, size_t length, int prot, int flags, int fd, - off_t offset) { - EXPECT_EQ(1234, fd); - return (void*)0x87654321; - } - -}; - -struct Allocator_InitPmemAreaLockedWithSuccessfulCompletion : public AllocatorStub { - - virtual ssize_t setSize(size_t size) { - EXPECT_EQ(size_t(16 << 20), size); - return 0; - } -}; - -TEST(test_pmem_userspace_allocator, testInitPmemAreaLockedWithSuccessfulCompletion) { - Deps_InitPmemAreaLockedWithSuccessfulCompletion depsMock; - Allocator_InitPmemAreaLockedWithSuccessfulCompletion allocMock; - PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev); - - int result = pma.init_pmem_area_locked(); - ASSERT_EQ(0, result); -} - -/******************************************************************************/ - -struct Deps_InitPmemAreaLockedWithEnomemOnMmap : public DepsStub { - - virtual int open(const char* pathname, int flags, int mode) { - EXPECT_EQ(fakePmemDev, pathname); - EXPECT_EQ(O_RDWR, flags); - EXPECT_EQ(0, mode); - return 1234; - } - - virtual size_t getPmemTotalSize(int fd, size_t* size) { - EXPECT_EQ(1234, fd); - *size = 16 << 20; - return 0; - } - - virtual int getErrno() { - return ENOMEM; - } - - virtual void* mmap(void* start, size_t length, int prot, int flags, int fd, - off_t offset) { - return (void*)MAP_FAILED; - } - -}; - -struct Allocator_InitPmemAreaLockedWithEnomemOnMmap : public AllocatorStub { - - virtual ssize_t setSize(size_t size) { - EXPECT_EQ(size_t(16 << 20), size); - return 0; - } -}; - -TEST(test_pmem_userspace_allocator, testInitPmemAreaLockedWthEnomemOnMmap) { - Deps_InitPmemAreaLockedWithEnomemOnMmap depsMock; - Allocator_InitPmemAreaLockedWithEnomemOnMmap allocMock; - PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev); - - int result = pma.init_pmem_area_locked(); - ASSERT_EQ(-ENOMEM, result); -} - -/******************************************************************************/ - -struct Deps_InitPmemAreaLockedWithEaccesOnGetPmemTotalSize : public DepsStub { - - virtual int open(const char* pathname, int flags, int mode) { - EXPECT_EQ(fakePmemDev, pathname); - EXPECT_EQ(O_RDWR, flags); - EXPECT_EQ(0, mode); - return 1234; - } - - virtual size_t getPmemTotalSize(int fd, size_t* size) { - EXPECT_EQ(1234, fd); - return -EACCES; - } -}; - -TEST(test_pmem_userspace_allocator, testInitPmemAreaLockedWthEaccesOnGetPmemTotalSize) { - Deps_InitPmemAreaLockedWithEaccesOnGetPmemTotalSize depsMock; - AllocatorStub allocStub; - PmemUserspaceAllocator pma(depsMock, allocStub, fakePmemDev); - - int result = pma.init_pmem_area_locked(); - ASSERT_EQ(-EACCES, result); -} - -/******************************************************************************/ - -struct Deps_InitPmemAreaLockedWithEaccesOnOpen : public DepsStub { - - virtual int getErrno() { - return EACCES; - } - - virtual int open(const char* pathname, int flags, int mode) { - EXPECT_EQ(fakePmemDev, pathname); - EXPECT_EQ(O_RDWR, flags); - EXPECT_EQ(0, mode); - return -1; - } -}; - -TEST(test_pmem_userspace_allocator, testInitPmemAreaLockedWithEaccesOnOpenMaster) { - Deps_InitPmemAreaLockedWithEaccesOnOpen depsMock; - AllocatorStub allocStub; - PmemUserspaceAllocator pma(depsMock, allocStub, fakePmemDev); - - int result = pma.init_pmem_area_locked(); - ASSERT_EQ(-EACCES, result); -} - -/******************************************************************************/ - -typedef Deps_InitPmemAreaLockedWithSuccessfulCompletion Deps_InitPmemAreaWithSuccessfulInitialCompletion; - -TEST(test_pmem_userspace_allocator, testInitPmemAreaWithSuccessfulInitialCompletion) { - Deps_InitPmemAreaWithSuccessfulInitialCompletion depsMock; - AllocatorStub allocStub; - PmemUserspaceAllocator pma(depsMock, allocStub, fakePmemDev); - - int result = pma.init_pmem_area(); - ASSERT_EQ(0, result); -} - -/******************************************************************************/ - -typedef Deps_InitPmemAreaLockedWithEaccesOnOpen Deps_InitPmemAreaWithEaccesOnInitLocked; - -TEST(test_pmem_userspace_allocator, testInitPmemAreaWithEaccesOnInitLocked) { - Deps_InitPmemAreaWithEaccesOnInitLocked depsMock; - AllocatorStub allocStub; - PmemUserspaceAllocator pma(depsMock, allocStub, fakePmemDev); - - int result = pma.init_pmem_area(); - ASSERT_EQ(-EACCES, result); -} - -/******************************************************************************/ - -TEST(test_pmem_userspace_allocator, testInitPmemAreaAfterSuccessfulInitialCompletion) { - DepsStub depsStub; - AllocatorStub allocStub; - PmemUserspaceAllocator pma(depsStub, allocStub, fakePmemDev); - - pma.set_master_values(1234, 0); // Indicate that the pma has been successfully init'd - - int result = pma.init_pmem_area(); - ASSERT_EQ(0, result); - //XXX JMG: Add this back in maybe? ASSERT_EQ(1234, pmi.master); // Make sure the master fd wasn't changed -} - -/******************************************************************************/ - -TEST(test_pmem_userspace_allocator, testInitPmemAreaAfterFailedInit) { - DepsStub depsStub; - AllocatorStub allocStub; - PmemUserspaceAllocator pma(depsStub, allocStub, fakePmemDev); - - pma.set_master_values(-EACCES, 0); // Indicate that the pma has failed init - - int result = pma.init_pmem_area(); - ASSERT_EQ(-EACCES, result); -} - -/******************************************************************************/ - -struct Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags : public DepsStub { - - virtual int open(const char* pathname, int flags, int mode) { - EXPECT_EQ(fakePmemDev, pathname); - EXPECT_EQ(O_RDWR, flags & O_RDWR); - EXPECT_EQ(0, mode); - return 5678; - } - - virtual int connectPmem(int fd, int master_fd) { - EXPECT_EQ(5678, fd); - EXPECT_EQ(1234, master_fd); - return 0; - } - - virtual int mapPmem(int fd, int offset, size_t size) { - EXPECT_EQ(5678, fd); - EXPECT_EQ(0x300, offset); - EXPECT_EQ(size_t(0x100), size); - return 0; - } -}; - - -struct Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags : public AllocatorStub { - - virtual ssize_t allocate(size_t size, uint32_t flags = 0) { - EXPECT_EQ(size_t(0x100), size); - EXPECT_EQ(uint32_t(0x0), flags); - return 0x300; - } -}; - -TEST(test_pmem_userspace_allocator, testAllocPmemBufferWithSuccessfulCompletionWithNoFlags) { - Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags depsMock; - Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags allocMock; - PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev); - - uint8_t buf[0x300 + 0x100]; // Create a buffer to get memzero'd - pma.set_master_values(1234, buf); // Indicate that the pma has been successfully init'd - - void* base = 0; - int offset = -9182, fd = -9182; - int size = 0x100; - int flags = 0; - int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd); - ASSERT_EQ(0, result); - ASSERT_EQ(0x300, offset); - ASSERT_EQ(5678, fd); - for (int i = 0x300; i < 0x400; ++i) { - ASSERT_EQ(uint8_t(0), buf[i]); - } -} - -/******************************************************************************/ - -typedef Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags Deps_InitPmemAreaLockedWithSuccessfulCompletionWithAllFlags; - -typedef Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags Allocator_AllocPmemBufferWithSuccessfulCompletionWithAllFlags; - -TEST(test_pmem_userspace_allocator, testAllocPmemBufferWithSuccessfulCompletionWithAllFlags) { - Deps_InitPmemAreaLockedWithSuccessfulCompletionWithAllFlags depsMock; - Allocator_AllocPmemBufferWithSuccessfulCompletionWithAllFlags allocMock; - PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev); - - uint8_t buf[0x300 + 0x100]; // Create a buffer to get memzero'd - pma.set_master_values(1234, buf); // Indicate that the pma has been successfully init'd - - void* base = 0; - int offset = -9182, fd = -9182; - int size = 0x100; - int flags = ~0; - int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd); - ASSERT_EQ(0, result); - ASSERT_EQ(0x300, offset); - ASSERT_EQ(5678, fd); - for (int i = 0x300; i < 0x400; ++i) { - ASSERT_EQ(0, buf[i]); - } -} - -/******************************************************************************/ - -struct Deps_InitPmemAreaLockedWithEnodevOnOpen : public Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags { - - virtual int getErrno() { - return ENODEV; - } - - virtual int open(const char* pathname, int flags, int mode) { - EXPECT_EQ(fakePmemDev, pathname); - EXPECT_EQ(O_RDWR, flags & O_RDWR); - EXPECT_EQ(0, mode); - return -1; - } -}; - -typedef Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags Allocator_AllocPmemBufferWithEnodevOnOpen; - -TEST(test_pmem_userspace_allocator, testAllocPmemBufferWithSuccessfulCompletionWithEnodevOnOpen) { - Deps_InitPmemAreaLockedWithEnodevOnOpen depsMock; - Allocator_AllocPmemBufferWithEnodevOnOpen allocMock; - PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev); - - uint8_t buf[0x300 + 0x100]; // Create a buffer to get memzero'd - pma.set_master_values(1234, buf); // Indicate that the pma has been successfully init'd - - void* base = 0; - int offset = -9182, fd = -9182; - int size = 0x100; - int flags = ~0; - int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd); - ASSERT_EQ(-ENODEV, result); -} - -/******************************************************************************/ - -struct Deps_InitPmemAreaLockedWithEnomemOnConnectPmem : public Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags { - - virtual int getErrno() { - return ENOMEM; - } - - virtual int connectPmem(int fd, int master_fd) { - EXPECT_EQ(5678, fd); - EXPECT_EQ(1234, master_fd); - return -1; - } -}; - -typedef Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags Allocator_AllocPmemBufferWithEnomemOnConnectPmem; - -TEST(test_pmem_userspace_allocator, testAllocPmemBufferWithSuccessfulCompletionWithEnomemOnConnectPmem) { - Deps_InitPmemAreaLockedWithEnomemOnConnectPmem depsMock; - Allocator_AllocPmemBufferWithEnomemOnConnectPmem allocMock; - PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev); - - uint8_t buf[0x300 + 0x100]; // Create a buffer to get memzero'd - pma.set_master_values(1234, buf); // Indicate that the pma has been successfully init'd - - void* base = 0; - int offset = -9182, fd = -9182; - int size = 0x100; - int flags = ~0; - int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd); - ASSERT_EQ(-ENOMEM, result); -} - -/******************************************************************************/ - -struct Deps_InitPmemAreaLockedWithEnomemOnMapPmem : public Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags { - - virtual int getErrno() { - return ENOMEM; - } - - virtual int mapPmem(int fd, int offset, size_t size) { - EXPECT_EQ(5678, fd); - EXPECT_EQ(0x300, offset); - EXPECT_EQ(size_t(0x100), size); - return -1; - } -}; - -typedef Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags Allocator_AllocPmemBufferWithEnomemOnMapPmem; - -TEST(test_pmem_userspace_allocator, testAllocPmemBufferWithEnomemOnMapPmem) { - Deps_InitPmemAreaLockedWithEnomemOnMapPmem depsMock; - Allocator_AllocPmemBufferWithEnomemOnMapPmem allocMock; - PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev); - - uint8_t buf[0x300 + 0x100]; // Create a buffer to get memzero'd - pma.set_master_values(1234, buf); // Indicate that the pma has been successfully init'd - - void* base = 0; - int offset = -9182, fd = -9182; - int size = 0x100; - int flags = ~0; - int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd); - ASSERT_EQ(-ENOMEM, result); -} - -/******************************************************************************/ - -struct Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithNoFlags : public DepsStub { - - void* mmapResult; - - Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithNoFlags(void* mmapResult) : - mmapResult(mmapResult) {} - - virtual int open(const char* pathname, int flags, int mode) { - EXPECT_EQ(fakePmemDev, pathname); - EXPECT_EQ(O_RDWR, flags & O_RDWR); - EXPECT_EQ(0, mode); - return 5678; - } - - virtual void* mmap(void* start, size_t length, int prot, int flags, int fd, - off_t offset) { - EXPECT_EQ(5678, fd); - return mmapResult; - } -}; - -TEST(test_pmem_kernel_allocator, testAllocPmemBufferWithSuccessfulCompletionWithNoFlags) { - uint8_t buf[0x100]; // Create a buffer to get memzero'd - Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithNoFlags depsMock(buf); - PmemKernelAllocator pma(depsMock, fakePmemDev); - - void* base = 0; - int offset = -9182, fd = -9182; - int size = 0x100; - int flags = 0; - int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd); - ASSERT_EQ(0, result); - ASSERT_EQ(buf, base); - ASSERT_EQ(0, offset); - ASSERT_EQ(5678, fd); - for (int i = 0; i < 0x100; ++i) { - ASSERT_EQ(0, buf[i]); - } -} - -/******************************************************************************/ - -typedef Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithNoFlags Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithAllFlags; - -TEST(test_pmem_kernel_allocator, testAllocPmemBufferWithSuccessfulCompletionWithAllFlags) { - uint8_t buf[0x100]; // Create a buffer to get memzero'd - Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithAllFlags depsMock(buf); - PmemKernelAllocator pma(depsMock, fakePmemDev); - - void* base = 0; - int offset = -9182, fd = -9182; - int size = 0x100; - int flags = ~0; - int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd); - ASSERT_EQ(0, result); - ASSERT_EQ(buf, base); - ASSERT_EQ(0, offset); - ASSERT_EQ(5678, fd); - for (int i = 0; i < 0x100; ++i) { - ASSERT_EQ(0, buf[i]); - } -} - -/******************************************************************************/ - -struct Deps_KernelAllocPmemBufferWithEpermOnOpen : public DepsStub { - - virtual int getErrno() { - return EPERM; - } - - virtual int open(const char* pathname, int flags, int mode) { - EXPECT_EQ(fakePmemDev, pathname); - EXPECT_EQ(O_RDWR, flags & O_RDWR); - EXPECT_EQ(0, mode); - return -1; - } -}; - - -TEST(test_pmem_kernel_allocator, testAllocPmemBufferWithEpermOnOpen) { - Deps_KernelAllocPmemBufferWithEpermOnOpen depsMock; - PmemKernelAllocator pma(depsMock, fakePmemDev); - - void* base = 0; - int offset = -9182, fd = -9182; - int size = 0x100; - int flags = ~0; - int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd); - ASSERT_EQ(-EPERM, result); - ASSERT_EQ(0, base); - ASSERT_EQ(0, offset); - ASSERT_EQ(-1, fd); -} - -/******************************************************************************/ - -struct Deps_KernelAllocPmemBufferWithEnomemOnMmap : DepsStub { - - virtual int open(const char* pathname, int flags, int mode) { - EXPECT_EQ(fakePmemDev, pathname); - EXPECT_EQ(O_RDWR, flags & O_RDWR); - EXPECT_EQ(0, mode); - return 5678; - } - - virtual void* mmap(void* start, size_t length, int prot, int flags, int fd, - off_t offset) { - return (void*)MAP_FAILED; - } - - virtual int getErrno() { - return ENOMEM; - } -}; - - -TEST(test_pmem_kernel_allocator, testAllocPmemBufferWithEnomemOnMmap) { - Deps_KernelAllocPmemBufferWithEnomemOnMmap depsMock; - PmemKernelAllocator pma(depsMock, fakePmemDev); - - void* base = 0; - int offset = -9182, fd = -9182; - int size = 0x100; - int flags = ~0; - int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd); - ASSERT_EQ(-ENOMEM, result); - ASSERT_EQ(0, base); - ASSERT_EQ(0, offset); - ASSERT_EQ(-1, fd); -} - -/******************************************************************************/ diff --git a/libgralloc-qsd8k/Android.mk b/libgralloc/Android.mk similarity index 51% rename from libgralloc-qsd8k/Android.mk rename to libgralloc/Android.mk index 1157e9f..bd8c3e8 100644 --- a/libgralloc-qsd8k/Android.mk +++ b/libgralloc/Android.mk @@ -11,7 +11,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -ifneq ($(TARGET_USES_ION),true) + +# Use this flag until pmem/ashmem is implemented in the new gralloc +ifeq ($(TARGET_USES_ION),true) LOCAL_PATH := $(call my-dir) # HAL module implemenation, not prelinked and stored in @@ -19,48 +21,50 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_PRELINK_MODULE := false LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw -LOCAL_SHARED_LIBRARIES := liblog libcutils libGLESv1_CM libutils +LOCAL_SHARED_LIBRARIES := liblog libcutils libGLESv1_CM libutils libmemalloc -LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include \ - hardware/qcom/display/libgralloc +LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr -LOCAL_SRC_FILES := \ - allocator.cpp \ - framebuffer.cpp \ - gpu.cpp \ - gralloc.cpp \ - mapper.cpp \ - pmemalloc.cpp - -LOCAL_MODULE := gralloc.$(TARGET_BOARD_PLATFORM) -LOCAL_CFLAGS:= -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).gralloc\" -DHOST -DDEBUG_CALC_FPS +LOCAL_SRC_FILES := framebuffer.cpp \ + gpu.cpp \ + gralloc.cpp \ + mapper.cpp \ + pmemalloc.cpp \ + pmem_bestfit_alloc.cpp -ifneq (, $(filter msm7625_ffa msm7625_surf msm7627_ffa msm7627_surf msm7627_7x_ffa msm7627_7x_surf, $(QCOM_TARGET_PRODUCT))) -LOCAL_CFLAGS += -DTARGET_MSM7x27 +LOCAL_MODULE := gralloc.$(TARGET_BOARD_PLATFORM) +LOCAL_CFLAGS:= -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).gralloc\" -DHOST -DDEBUG_CALC_FPS -DUSE_ION + +ifeq ($(call is-board-platform,msm7627_surf msm7627_6x),true) + LOCAL_CFLAGS += -DTARGET_MSM7x27 endif ifeq ($(TARGET_HAVE_HDMI_OUT),true) -LOCAL_CFLAGS += -DHDMI_DUAL_DISPLAY -LOCAL_C_INCLUDES += $(LOCAL_PATH)/../liboverlay -LOCAL_SHARED_LIBRARIES += liboverlay + LOCAL_CFLAGS += -DHDMI_DUAL_DISPLAY + LOCAL_C_INCLUDES += hardware/msm7k/liboverlay + LOCAL_SHARED_LIBRARIES += liboverlay +endif + +ifeq ($(TARGET_USES_SF_BYPASS),true) + LOCAL_CFLAGS += -DSF_BYPASS endif ifeq ($(TARGET_GRALLOC_USES_ASHMEM),true) -LOCAL_CFLAGS += -DUSE_ASHMEM + LOCAL_CFLAGS += -DUSE_ASHMEM endif include $(BUILD_SHARED_LIBRARY) - -# Build a host library for testing -ifeq ($(HOST_OS),linux) +#MemAlloc Library include $(CLEAR_VARS) -LOCAL_SRC_FILES := \ - gpu.cpp \ - pmemalloc.cpp - -LOCAL_MODULE_TAGS := tests -LOCAL_MODULE := libgralloc_qsd8k_host -LOCAL_CFLAGS:= -DLOG_TAG=\"gralloc-qsd8k\" -include $(BUILD_HOST_STATIC_LIBRARY) -endif -endif +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES) +LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include +LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr +LOCAL_SHARED_LIBRARIES := liblog libcutils libutils +LOCAL_SRC_FILES := ionalloc.cpp \ + ashmemalloc.cpp \ + alloc_controller.cpp +LOCAL_CFLAGS:= -DLOG_TAG=\"memalloc\" -DLOG_NDDEBUG=0 -DUSE_ION +LOCAL_MODULE := libmemalloc +include $(BUILD_SHARED_LIBRARY) +endif #TARGET_USES_ION diff --git a/libgralloc-qsd8k/MODULE_LICENSE_APACHE2 b/libgralloc/MODULE_LICENSE_APACHE2 similarity index 100% rename from libgralloc-qsd8k/MODULE_LICENSE_APACHE2 rename to libgralloc/MODULE_LICENSE_APACHE2 diff --git a/libgralloc-qsd8k/NOTICE b/libgralloc/NOTICE similarity index 100% rename from libgralloc-qsd8k/NOTICE rename to libgralloc/NOTICE diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp new file mode 100644 index 0000000..5cd07d3 --- /dev/null +++ b/libgralloc/alloc_controller.cpp @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2011, Code Aurora Forum. All rights reserved. + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Code Aurora Forum, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "gralloc_priv.h" +#include "alloc_controller.h" +#include "memalloc.h" +#include "ionalloc.h" + +using namespace gralloc; +using android::sp; + +sp IAllocController::sController = NULL; +sp IAllocController::getInstance(void) +{ + if(sController == NULL) { +#ifdef USE_ION + sController = new IonController(); +#else + // XXX: Return pmem/ashmem controller when completed +#endif + } + return sController; +} + +IonController::IonController() +{ + mIonAlloc = new IonAlloc(); +} + +static bool canFallback(int compositionType, int usage, int flags) +{ + // Fallback to system heap when alloc fails unless + // 1. Composition type is MDP + // 2. Earlier alloc attempt was from system heap + // 3. Contiguous heap requsted explicitly + + if(compositionType == MDP_COMPOSITION) + return false; + if(flags & ION_HEAP_SYSTEM_ID) + return false; + if(usage &(GRALLOC_USAGE_PRIVATE_ADSP_HEAP| + GRALLOC_USAGE_PRIVATE_EBI_HEAP | + GRALLOC_USAGE_PRIVATE_SMI_HEAP)) + return false; + //Return true by default + return true; +} + +int IonController::allocate(alloc_data& data, int usage, + int compositionType) +{ + int ionFlags = 0; + int ret; + + //System heap cannot be uncached + if (usage & GRALLOC_USAGE_PRIVATE_UNCACHED && + !(usage & GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP)) + data.uncached = true; + else + data.uncached = false; + + if(usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP) + ionFlags |= 1 << ION_HEAP_ADSP_ID; + + if(usage & GRALLOC_USAGE_PRIVATE_SMI_HEAP) + ionFlags |= 1 << ION_HEAP_SMI_ID; + + if(usage & GRALLOC_USAGE_PRIVATE_EBI_HEAP) + ionFlags |= 1 << ION_HEAP_EBI_ID; + + if(usage & GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP) + ionFlags |= 1 << ION_HEAP_SYSTEM_ID; + + // if no flags are set, default to + // EBI heap, so that bypass can work + // we can fall back to system heap if + // we run out. + if(!ionFlags) + ionFlags = 1 << ION_HEAP_EBI_ID; + + data.flags = ionFlags; + ret = mIonAlloc->alloc_buffer(data); + + // Fallback + if(ret < 0 && canFallback(compositionType, usage, ionFlags)) { + LOGW("Falling back to system heap"); + data.flags = 1 << ION_HEAP_SYSTEM_ID; + ret = mIonAlloc->alloc_buffer(data); + } + + if(ret >= 0 ) + data.allocType = private_handle_t::PRIV_FLAGS_USES_ION; + + return ret; +} + +sp IonController::getAllocator(int flags) +{ + sp memalloc; + if (flags & private_handle_t::PRIV_FLAGS_USES_ION) { + memalloc = mIonAlloc; + } else { + LOGE("%s: Invalid flags passed: 0x%x", __FUNCTION__, flags); + } + + return memalloc; +} + +int PmemAshmemController::allocate(alloc_data& data, int usage, + int compositionType) +{ + //XXX PMEM with ashmem fallback strategy + return 0; +} + +sp PmemAshmemController::getAllocator(int flags) +{ + sp memalloc; + if (flags & private_handle_t::PRIV_FLAGS_USES_PMEM) { + // XXX Return right allocator based on flags + memalloc = NULL; + } else { + LOGE("%s: Invalid flags passed: 0x%x", __FUNCTION__, flags); + memalloc = NULL; + } + + return memalloc; +} + + diff --git a/libgralloc/alloc_controller.h b/libgralloc/alloc_controller.h new file mode 100644 index 0000000..fbdd401 --- /dev/null +++ b/libgralloc/alloc_controller.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2011, Code Aurora Forum. All rights reserved. + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Code Aurora Forum, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef GRALLOC_ALLOCCONTROLLER_H +#define GRALLOC_ALLOCCONTROLLER_H + +#include + +namespace gralloc { + + struct alloc_data; + class IMemAlloc; + class IonAlloc; + + class IAllocController : public android::RefBase { + + public: + /* Allocate using a suitable method + * Returns the type of buffer allocated + */ + virtual int allocate(alloc_data& data, int usage, + int compositionType) = 0; + + virtual android::sp getAllocator(int flags) = 0; + + virtual ~IAllocController() {}; + + static android::sp getInstance(void); + + private: + static android::sp sController; + + }; + + class IonController : public IAllocController { + + public: + virtual int allocate(alloc_data& data, int usage, + int compositionType); + + virtual android::sp getAllocator(int flags); + + IonController(); + + private: + android::sp mIonAlloc; + + }; + + class PmemAshmemController : public IAllocController { + + public: + virtual int allocate(alloc_data& data, int usage, + int compositionType); + + virtual android::sp getAllocator(int flags); + // XXX: Pmem and ashmem alloc objects + + }; + +} //end namespace gralloc +#endif // GRALLOC_ALLOCCONTROLLER_H diff --git a/libgralloc/ashmemalloc.cpp b/libgralloc/ashmemalloc.cpp new file mode 100644 index 0000000..e60137b --- /dev/null +++ b/libgralloc/ashmemalloc.cpp @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2011, Code Aurora Forum. All rights reserved. + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Code Aurora Forum, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "ashmemalloc.h" + +using gralloc::AshmemAlloc; +int AshmemAlloc::alloc_buffer(alloc_data& data) +{ + int err = 0; + int fd = -1; + void* base = 0; + int offset = 0; + char name[ASHMEM_NAME_LEN]; + snprintf(name, ASHMEM_NAME_LEN, "gralloc-buffer-%x", data.pHandle); + int prot = PROT_READ | PROT_WRITE; + fd = ashmem_create_region(name, data.size); + if (fd < 0) { + LOGE("couldn't create ashmem (%s)", strerror(errno)); + err = -errno; + } else { + if (ashmem_set_prot_region(fd, prot) < 0) { + LOGE("ashmem_set_prot_region(fd=%d, prot=%x) failed (%s)", + fd, prot, strerror(errno)); + close(fd); + err = -errno; + } else { + base = mmap(0, data.size, prot, MAP_SHARED|MAP_POPULATE|MAP_LOCKED, fd, 0); + if (base == MAP_FAILED) { + LOGE("alloc mmap(fd=%d, size=%d, prot=%x) failed (%s)", + fd, data.size, prot, strerror(errno)); + close(fd); + err = -errno; + } else { + memset((char*)base + offset, 0, data.size); + } + } + } + if(err == 0) { + data.fd = fd; + data.base = base; + data.offset = offset; + clean_buffer(base, data.size, offset, fd); + } + return err; + +} + +int AshmemAlloc::free_buffer(void* base, size_t size, int offset, int fd) +{ + LOGD("%s:Freeing buffer size=%d base=%p fd=%d PID=%d", + __FUNCTION__, size, base, fd, getpid()); + int err = 0; + + if(!base) { + LOGE("Invalid free"); + return -EINVAL; + } + err = unmap_buffer(base, size, offset); + close(fd); + return err; +} + +int AshmemAlloc::map_buffer(void **pBase, size_t size, int offset, int fd) +{ + LOGD("%s: Mapping buffer fd=%d size=%d PID=%d", __FUNCTION__, + fd, size, getpid()); + int err = 0; + void *base = 0; + if (err) + return err; + + base = mmap(0, size, PROT_READ| PROT_WRITE, + MAP_SHARED, fd, 0); + *pBase = base; + if(base == MAP_FAILED) { + LOGD("%s: Failed to map memory in the client: %s", + __FUNCTION__, strerror(errno)); + err = -errno; + } else { + LOGD("%s: Successfully mapped %d bytes", __FUNCTION__, size); + } + return err; +} + +int AshmemAlloc::unmap_buffer(void *base, size_t size, int offset) +{ + LOGD("%s: Unmapping buffer at address %p", __FUNCTION__, base); + int err = munmap(base, size); + if(err) { + LOGE("%s: Failed to unmap memory at %p: %s", + __FUNCTION__, base, strerror(errno)); + } + return err; + +} +int AshmemAlloc::clean_buffer(void *base, size_t size, int offset, int fd) +{ + // LOGD("%s: Clean buffer fd=%d base = %p size=%d PID=%d", __FUNCTION__, + // fd, base, size, getpid()); + int err = 0; + if (ioctl(fd, ASHMEM_CACHE_INV_RANGE, NULL)) { + LOGE("ASHMEM_CACHE_INV_RANGE failed fd = %d", fd); + } + + return err; +} + diff --git a/libgralloc/ashmemalloc.h b/libgralloc/ashmemalloc.h new file mode 100644 index 0000000..051dcd1 --- /dev/null +++ b/libgralloc/ashmemalloc.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2011, Code Aurora Forum. All rights reserved. + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Code Aurora Forum, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GRALLOC_ASHMEMALLOC_H +#define GRALLOC_ASHMEMALLOC_H + +#include "memalloc.h" +#include + +namespace gralloc { + class AshmemAlloc : public IMemAlloc { + + public: + virtual int alloc_buffer(alloc_data& data); + + virtual int free_buffer(void *base, size_t size, + int offset, int fd); + + virtual int map_buffer(void **pBase, size_t size, + int offset, int fd); + + virtual int unmap_buffer(void *base, size_t size, + int offset); + + virtual int clean_buffer(void*base, size_t size, + int offset, int fd); + + }; +} +#endif /* GRALLOC_ASHMEMALLOC_H */ diff --git a/libgralloc-qsd8k/framebuffer.cpp b/libgralloc/framebuffer.cpp similarity index 95% rename from libgralloc-qsd8k/framebuffer.cpp rename to libgralloc/framebuffer.cpp index dc51e08..8259f96 100644 --- a/libgralloc-qsd8k/framebuffer.cpp +++ b/libgralloc/framebuffer.cpp @@ -174,7 +174,6 @@ static int fb_setUpdateRect(struct framebuffer_device_t* dev, { if (((w|h) <= 0) || ((l|t)<0)) return -EINVAL; - fb_context_t* ctx = (fb_context_t*)dev; private_module_t* m = reinterpret_cast( dev->common.module); @@ -680,14 +679,13 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) } else { void* fb_vaddr; void* buffer_vaddr; - - m->base.lock(&m->base, m->framebuffer, - GRALLOC_USAGE_SW_WRITE_RARELY, + m->base.lock(&m->base, m->framebuffer, + GRALLOC_USAGE_SW_WRITE_RARELY, 0, 0, m->info.xres, m->info.yres, &fb_vaddr); - m->base.lock(&m->base, buffer, - GRALLOC_USAGE_SW_READ_RARELY, + m->base.lock(&m->base, buffer, + GRALLOC_USAGE_SW_READ_RARELY, 0, 0, m->info.xres, m->info.yres, &buffer_vaddr); @@ -699,8 +697,8 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) m->info.xoffset, m->info.yoffset, m->info.width, m->info.height); - m->base.unlock(&m->base, buffer); - m->base.unlock(&m->base, m->framebuffer); + m->base.unlock(&m->base, buffer); + m->base.unlock(&m->base, m->framebuffer); } LOGD_IF(FB_DEBUG, "Framebuffer state: [0] = %c [1] = %c [2] = %c", @@ -745,7 +743,6 @@ int mapFrameBufferLocked(struct private_module_t* module) if (module->framebuffer) { return 0; } - char const * const device_template[] = { "/dev/graphics/fb%u", "/dev/fb%u", @@ -787,42 +784,42 @@ int mapFrameBufferLocked(struct private_module_t* module) */ if(info.bits_per_pixel == 32) { - /* - * Explicitly request RGBA_8888 - */ - info.bits_per_pixel = 32; - info.red.offset = 24; - info.red.length = 8; - info.green.offset = 16; - info.green.length = 8; - info.blue.offset = 8; - info.blue.length = 8; - info.transp.offset = 0; - info.transp.length = 8; + /* + * Explicitly request RGBA_8888 + */ + info.bits_per_pixel = 32; + info.red.offset = 24; + info.red.length = 8; + info.green.offset = 16; + info.green.length = 8; + info.blue.offset = 8; + info.blue.length = 8; + info.transp.offset = 0; + info.transp.length = 8; - /* Note: the GL driver does not have a r=8 g=8 b=8 a=0 config, so if we do - * not use the MDP for composition (i.e. hw composition == 0), ask for - * RGBA instead of RGBX. */ - if (property_get("debug.sf.hw", property, NULL) > 0 && atoi(property) == 0) - module->fbFormat = HAL_PIXEL_FORMAT_RGBX_8888; - else if(property_get("debug.composition.type", property, NULL) > 0 && (strncmp(property, "mdp", 3) == 0)) - module->fbFormat = HAL_PIXEL_FORMAT_RGBX_8888; - else - module->fbFormat = HAL_PIXEL_FORMAT_RGBA_8888; + /* Note: the GL driver does not have a r=8 g=8 b=8 a=0 config, so if we do + * not use the MDP for composition (i.e. hw composition == 0), ask for + * RGBA instead of RGBX. */ + if (property_get("debug.sf.hw", property, NULL) > 0 && atoi(property) == 0) + module->fbFormat = HAL_PIXEL_FORMAT_RGBX_8888; + else if(property_get("debug.composition.type", property, NULL) > 0 && (strncmp(property, "mdp", 3) == 0)) + module->fbFormat = HAL_PIXEL_FORMAT_RGBX_8888; + else + module->fbFormat = HAL_PIXEL_FORMAT_RGBA_8888; } else { - /* - * Explicitly request 5/6/5 - */ - info.bits_per_pixel = 16; - info.red.offset = 11; - info.red.length = 5; - info.green.offset = 5; - info.green.length = 6; - info.blue.offset = 0; - info.blue.length = 5; - info.transp.offset = 0; - info.transp.length = 0; - module->fbFormat = HAL_PIXEL_FORMAT_RGB_565; + /* + * Explicitly request 5/6/5 + */ + info.bits_per_pixel = 16; + info.red.offset = 11; + info.red.length = 5; + info.green.offset = 5; + info.green.length = 6; + info.blue.offset = 0; + info.blue.length = 5; + info.transp.offset = 0; + info.transp.length = 0; + module->fbFormat = HAL_PIXEL_FORMAT_RGB_565; } /* * Request NUM_BUFFERS screens (at lest 2 for page flipping) @@ -956,7 +953,7 @@ int mapFrameBufferLocked(struct private_module_t* module) pthread_cond_init(&(module->avail[i].cond), NULL); module->avail[i].is_avail = true; module->avail[i].state = AVL; - } + } /* create display update thread */ pthread_t thread1; @@ -1117,7 +1114,7 @@ msm_copy_buffer(buffer_handle_t handle, int fd, blit.req.dst.width = width; blit.req.dst.height = height; blit.req.dst.offset = 0; - blit.req.dst.memory_id = fd; + blit.req.dst.memory_id = fd; blit.req.dst.format = format; blit.req.src_rect.x = blit.req.dst_rect.x = x; diff --git a/libgralloc-qsd8k/gpu.cpp b/libgralloc/gpu.cpp old mode 100755 new mode 100644 similarity index 55% rename from libgralloc-qsd8k/gpu.cpp rename to libgralloc/gpu.cpp index cabcda9..135d84f --- a/libgralloc-qsd8k/gpu.cpp +++ b/libgralloc/gpu.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 The Android Open Source Project + * Copyright (c) 2011 Code Aurora Forum. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,27 +18,25 @@ #include #include #include - -#include - #include -#ifdef HOST -#include -#endif +#include #include "gr.h" #include "gpu.h" +#include "memalloc.h" +#include "alloc_controller.h" static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00; static const int QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka = 0x7FA30C03; static const int QOMX_INTERLACE_FLAG = 0x49283654; static const int QOMX_3D_VIDEO_FLAG = 0x23784238; -gpu_context_t::gpu_context_t(Deps& deps, PmemAllocator& pmemAllocator, - PmemAllocator& pmemAdspAllocator, const private_module_t* module) : - deps(deps), - pmemAllocator(pmemAllocator), - pmemAdspAllocator(pmemAdspAllocator) +using namespace gralloc; +using android::sp; + +gpu_context_t::gpu_context_t(const private_module_t* module, + sp alloc_ctrl ) : + mAllocCtrl(alloc_ctrl) { // Zero out the alloc_device_t memset(static_cast(this), 0, sizeof(alloc_device_t)); @@ -72,6 +71,7 @@ gpu_context_t::gpu_context_t(Deps& deps, PmemAllocator& pmemAllocator, alloc = gralloc_alloc; allocSize = gralloc_alloc_size; free = gralloc_free; + } int gpu_context_t::gralloc_alloc_framebuffer_locked(size_t size, int usage, @@ -84,14 +84,9 @@ int gpu_context_t::gralloc_alloc_framebuffer_locked(size_t size, int usage, return -EINVAL; } - // allocate the framebuffer if (m->framebuffer == NULL) { - // initialize the framebuffer, the framebuffer is mapped once - // and forever. - int err = deps.mapFrameBufferLocked(m); - if (err < 0) { - return err; - } + LOGE("%s: Invalid framebuffer", __FUNCTION__); + return -EINVAL; } const uint32_t bufferMask = m->bufferMask; @@ -102,7 +97,8 @@ int gpu_context_t::gralloc_alloc_framebuffer_locked(size_t size, int usage, // we return a regular buffer which will be memcpy'ed to the main // screen when post is called. int newUsage = (usage & ~GRALLOC_USAGE_HW_FB) | GRALLOC_USAGE_HW_2D; - return gralloc_alloc_buffer(bufferSize, newUsage, pHandle, BUFFER_TYPE_UI, m->fbFormat, m->info.xres, m->info.yres); + return gralloc_alloc_buffer(bufferSize, newUsage, pHandle, BUFFER_TYPE_UI, + m->fbFormat, m->info.xres, m->info.yres); } if (bufferMask >= ((1LU<framebuffer->base); private_handle_t* hnd = new private_handle_t(dup(m->framebuffer->fd), bufferSize, private_handle_t::PRIV_FLAGS_USES_PMEM | private_handle_t::PRIV_FLAGS_FRAMEBUFFER, - BUFFER_TYPE_UI, m->fbFormat, m->info.xres, m->info.yres); + BUFFER_TYPE_UI, m->fbFormat, m->info.xres, + m->info.yres); // find a free slot for (uint32_t i=0 ; ibase = vaddr; hnd->offset = vaddr - intptr_t(m->framebuffer->base); *pHandle = hnd; - return 0; } @@ -144,161 +142,38 @@ int gpu_context_t::gralloc_alloc_framebuffer(size_t size, int usage, return err; } -int gpu_context_t::alloc_ashmem_buffer(size_t size, unsigned int postfix, void** pBase, - int* pOffset, int* pFd) -{ - int err = 0; - int fd = -1; - void* base = 0; - int offset = 0; - - char name[ASHMEM_NAME_LEN]; - snprintf(name, ASHMEM_NAME_LEN, "gralloc-buffer-%x", postfix); - int prot = PROT_READ | PROT_WRITE; - fd = ashmem_create_region(name, size); - if (fd < 0) { - LOGE("couldn't create ashmem (%s)", strerror(errno)); - err = -errno; - } else { - if (ashmem_set_prot_region(fd, prot) < 0) { - LOGE("ashmem_set_prot_region(fd=%d, prot=%x) failed (%s)", - fd, prot, strerror(errno)); - close(fd); - err = -errno; - } else { - base = mmap(0, size, prot, MAP_SHARED|MAP_POPULATE|MAP_LOCKED, fd, 0); - if (base == MAP_FAILED) { - LOGE("alloc mmap(fd=%d, size=%d, prot=%x) failed (%s)", - fd, size, prot, strerror(errno)); - close(fd); - err = -errno; - } else { - memset((char*)base + offset, 0, size); - } - } - } - if(err == 0) { - *pFd = fd; - *pBase = base; - *pOffset = offset; -#ifdef HOST - if (ioctl(fd, ASHMEM_CACHE_INV_RANGE, NULL)) { - LOGE("ASHMEM_CACHE_INV_RANGE failed fd = %d", fd); - } -#endif - } - return err; -} - -int gpu_context_t::gralloc_alloc_buffer(size_t size, int usage, buffer_handle_t* pHandle, - int bufferType, int format, int width, int height) +int gpu_context_t::gralloc_alloc_buffer(size_t size, int usage, + buffer_handle_t* pHandle, int bufferType, + int format, int width, int height) { int err = 0; int flags = 0; - - int fd = -1; - void* base = 0; // XXX JMG: This should change to just get an address from - // the PmemAllocator rather than getting the base & offset separately - int offset = 0; - int lockState = 0; - size = roundUpToPageSize(size); -#ifndef USE_ASHMEM - if (usage & GRALLOC_USAGE_HW_TEXTURE) { - // enable pmem in that case, so our software GL can fallback to - // the copybit module. - flags |= private_handle_t::PRIV_FLAGS_USES_PMEM; - } - - if (usage & GRALLOC_USAGE_HW_2D) { - flags |= private_handle_t::PRIV_FLAGS_USES_PMEM; - } -#else - // Enable use of PMEM only when MDP composition is used (and other conditions apply). - // Else fall back on using ASHMEM - if ((get_composition_type() == MDP_COMPOSITION) && - ((usage & GRALLOC_USAGE_HW_TEXTURE) || (usage & GRALLOC_USAGE_HW_2D)) ) { - flags |= private_handle_t::PRIV_FLAGS_USES_PMEM; - } - - if (usage & GRALLOC_USAGE_PRIVATE_EBI_HEAP) { - flags |= private_handle_t::PRIV_FLAGS_USES_PMEM; - } -#endif - if ((usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP) || (usage & GRALLOC_USAGE_PRIVATE_SMI_HEAP) - || (usage & GRALLOC_USAGE_EXTERNAL_DISP) || (usage & GRALLOC_USAGE_PROTECTED)) { - flags |= private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP; - flags &= ~private_handle_t::PRIV_FLAGS_USES_PMEM; - } - - private_module_t* m = reinterpret_cast(common.module); - if((flags & private_handle_t::PRIV_FLAGS_USES_PMEM) == 0 && - (flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP) == 0) { - flags |= private_handle_t::PRIV_FLAGS_USES_ASHMEM; - err = alloc_ashmem_buffer(size, (unsigned int)pHandle, &base, &offset, &fd); - if(err >= 0) - lockState |= private_handle_t::LOCK_STATE_MAPPED; - } - else if ((flags & private_handle_t::PRIV_FLAGS_USES_PMEM) != 0 || - (flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP) != 0) { - - PmemAllocator* pma = 0; - - if ((flags & private_handle_t::PRIV_FLAGS_USES_PMEM) != 0) { - if ((flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP) != 0) { - LOGE("attempting to allocate a gralloc buffer with both the " - "USES_PMEM and USES_PMEM_ADSP flags. Unsetting the " - "USES_PMEM_ADSP flag."); - flags &= ~private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP; - } - pma = &pmemAllocator; - } else { // (flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP) != 0 - pma = &pmemAdspAllocator; - } - - // PMEM buffers are always mmapped - lockState |= private_handle_t::LOCK_STATE_MAPPED; - - err = pma->alloc_pmem_buffer(size, usage, &base, &offset, &fd, format); - if (err < 0) { - // Pmem allocation failed. Try falling back to ashmem iff we are: - // a. not using MDP composition - // b. not allocating memory for a buffer to be used by overlays - // c. The client has not explicitly requested a PMEM buffer - if ((get_composition_type() != MDP_COMPOSITION) && - (bufferType != BUFFER_TYPE_VIDEO) && - ((usage & GRALLOC_USAGE_PRIVATE_EBI_HEAP) == 0) && - ((usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP) == 0)) { - // the caller didn't request PMEM, so we can try something else - flags &= ~private_handle_t::PRIV_FLAGS_USES_PMEM; - err = 0; - LOGE("Pmem allocation failed. Trying ashmem"); - goto try_ashmem; - } else { - LOGE("couldn't open pmem (%s)", strerror(errno)); - } - } - } else { -try_ashmem: - err = alloc_ashmem_buffer(size, (unsigned int)pHandle, &base, &offset, &fd); - if (err >= 0) { - lockState |= private_handle_t::LOCK_STATE_MAPPED; - flags |= private_handle_t::PRIV_FLAGS_USES_ASHMEM; - } else { - LOGE("Ashmem fallback failed"); - } - } + alloc_data data; + data.offset = 0; + data.fd = -1; + data.base = 0; + data.size = size; + if(format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) + data.align = 8192; + else + data.align = getpagesize(); + data.pHandle = (unsigned int) pHandle; + data.bufferType = bufferType; + err = mAllocCtrl->allocate(data, usage, compositionType); if (err == 0) { - private_handle_t* hnd = new private_handle_t(fd, size, flags, bufferType, format, width, height); - hnd->offset = offset; - hnd->base = int(base)+offset; - hnd->lockState = lockState; + flags |= data.allocType; + private_handle_t* hnd = new private_handle_t(data.fd, size, flags, + bufferType, format, width, height); + + hnd->offset = data.offset; + hnd->base = int(data.base) + data.offset; + hnd->lockState = private_handle_t::LOCK_STATE_MAPPED; *pHandle = hnd; } LOGE_IF(err, "gralloc failed err=%s", strerror(-err)); - return err; } @@ -306,7 +181,9 @@ static inline size_t ALIGN(size_t x, size_t align) { return (x + align-1) & ~(align-1); } -void gpu_context_t::getGrallocInformationFromFormat(int inputFormat, int *colorFormat, int *bufferType) +void gpu_context_t::getGrallocInformationFromFormat(int inputFormat, + int *colorFormat, + int *bufferType) { *bufferType = BUFFER_TYPE_VIDEO; *colorFormat = inputFormat; @@ -331,7 +208,7 @@ void gpu_context_t::getGrallocInformationFromFormat(int inputFormat, int *colorF } int gpu_context_t::alloc_impl(int w, int h, int format, int usage, - buffer_handle_t* pHandle, int* pStride, int bufferSize) { + buffer_handle_t* pHandle, int* pStride, size_t bufferSize) { if (!pHandle || !pStride) return -EINVAL; @@ -341,7 +218,6 @@ int gpu_context_t::alloc_impl(int w, int h, int format, int usage, alignedh = ALIGN(h, 32); int colorFormat, bufferType; getGrallocInformationFromFormat(format, &colorFormat, &bufferType); - switch (colorFormat) { case HAL_PIXEL_FORMAT_RGBA_8888: case HAL_PIXEL_FORMAT_RGBX_8888: @@ -357,7 +233,7 @@ int gpu_context_t::alloc_impl(int w, int h, int format, int usage, size = alignedw * alignedh * 2; break; - // adreno formats + // adreno formats case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO: // NV21 size = ALIGN(alignedw*alignedh, 4096); size += ALIGN(2 * ALIGN(w/2, 32) * ALIGN(h/2, 32), 4096); @@ -371,7 +247,7 @@ int gpu_context_t::alloc_impl(int w, int h, int format, int usage, size += ALIGN( alignedw * ALIGN(h/2, 32), 8192); break; case HAL_PIXEL_FORMAT_YCbCr_420_SP: - case HAL_PIXEL_FORMAT_YCrCb_420_SP: + case HAL_PIXEL_FORMAT_YCrCb_420_SP: case HAL_PIXEL_FORMAT_YV12: if ((w&1) || (h&1)) { LOGE("w or h is odd for the YUV format"); @@ -404,7 +280,8 @@ int gpu_context_t::alloc_impl(int w, int h, int format, int usage, if (usage & GRALLOC_USAGE_HW_FB) { err = gralloc_alloc_framebuffer(size, usage, pHandle); } else { - err = gralloc_alloc_buffer(size, usage, pHandle, bufferType, format, alignedw, alignedh); + err = gralloc_alloc_buffer(size, usage, pHandle, bufferType, + format, alignedw, alignedh); } if (err < 0) { @@ -421,41 +298,19 @@ int gpu_context_t::free_impl(private_handle_t const* hnd) { // free this buffer const size_t bufferSize = m->finfo.line_length * m->info.yres; int index = (hnd->base - m->framebuffer->base) / bufferSize; - m->bufferMask &= ~(1<bufferMask &= ~(1<flags & private_handle_t::PRIV_FLAGS_USES_PMEM) { - pmem_allocator = &pmemAllocator; - } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP) { - pmem_allocator = &pmemAdspAllocator; - } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ASHMEM) { - // free ashmem - if (hnd->fd >= 0) { - if (hnd->base) { - int err = munmap((void*)hnd->base, hnd->size); - LOGE_IF(err<0, "ASHMEM_UNMAP failed (%s), " - "fd=%d, sub.offset=%d, sub.size=%d", - strerror(errno), hnd->fd, hnd->offset, hnd->size); - } - } - } - if (pmem_allocator) { - pmem_allocator->free_pmem_buffer(hnd->size, (void*)hnd->base, - hnd->offset, hnd->fd); - } - - deps.terminateBuffer(&m->base, const_cast(hnd)); + sp memalloc = mAllocCtrl->getAllocator(hnd->flags); + int err = memalloc->free_buffer((void*)hnd->base, (size_t) hnd->size, + hnd->offset, hnd->fd); + if(err) + return err; } - - deps.close(hnd->fd); - delete hnd; // XXX JMG: move this to the deps + // XXX any additional cleanup. + delete hnd; return 0; } -/****************************************************************************** - * Static functions - *****************************************************************************/ - int gpu_context_t::gralloc_alloc(alloc_device_t* dev, int w, int h, int format, int usage, buffer_handle_t* pHandle, int* pStride) { @@ -465,7 +320,6 @@ int gpu_context_t::gralloc_alloc(alloc_device_t* dev, int w, int h, int format, gpu_context_t* gpu = reinterpret_cast(dev); return gpu->alloc_impl(w, h, format, usage, pHandle, pStride, 0); } - int gpu_context_t::gralloc_alloc_size(alloc_device_t* dev, int w, int h, int format, int usage, buffer_handle_t* pHandle, int* pStride, int bufferSize) { @@ -476,8 +330,9 @@ int gpu_context_t::gralloc_alloc_size(alloc_device_t* dev, int w, int h, int for return gpu->alloc_impl(w, h, format, usage, pHandle, pStride, bufferSize); } + int gpu_context_t::gralloc_free(alloc_device_t* dev, - buffer_handle_t handle) + buffer_handle_t handle) { if (private_handle_t::validate(handle) < 0) return -EINVAL; @@ -501,5 +356,3 @@ int gpu_context_t::gralloc_close(struct hw_device_t *dev) return 0; } - -gpu_context_t::Deps::~Deps() {} diff --git a/libgralloc/gpu.h b/libgralloc/gpu.h new file mode 100644 index 0000000..301c411 --- /dev/null +++ b/libgralloc/gpu.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * Copyright (c) 2011 Code Aurora Forum. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef GRALLOC_GPU_H_ +#define GRALLOC_GPU_H_ + +#include +#include +#include +#include + +#include +#include +#include + +#include "gralloc_priv.h" + +namespace gralloc { + class IAllocController; + class gpu_context_t : public alloc_device_t { + public: + gpu_context_t(const private_module_t* module, + android::spalloc_ctrl); + + int gralloc_alloc_framebuffer_locked(size_t size, int usage, + buffer_handle_t* pHandle); + + int gralloc_alloc_framebuffer(size_t size, int usage, + buffer_handle_t* pHandle); + + int gralloc_alloc_buffer(size_t size, int usage, + buffer_handle_t* pHandle, + int bufferType, int format, + int width, int height); + + int free_impl(private_handle_t const* hnd); + + int alloc_impl(int w, int h, int format, int usage, + buffer_handle_t* pHandle, int* pStride, + size_t bufferSize = 0); + + static int gralloc_alloc(alloc_device_t* dev, int w, int h, + int format, int usage, + buffer_handle_t* pHandle, + int* pStride); + + static int gralloc_free(alloc_device_t* dev, buffer_handle_t handle); + + static int gralloc_alloc_size(alloc_device_t* dev, + int w, int h, int format, + int usage, buffer_handle_t* pHandle, + int* pStride, int bufferSize); + + static int gralloc_close(struct hw_device_t *dev); + + int get_composition_type() const { return compositionType; } + + + private: + android::sp mAllocCtrl; + int compositionType; + void getGrallocInformationFromFormat(int inputFormat, + int *colorFormat, + int *bufferType); + }; +} +#endif // GRALLOC_GPU_H diff --git a/libgralloc-qsd8k/gr.h b/libgralloc/gr.h similarity index 97% rename from libgralloc-qsd8k/gr.h rename to libgralloc/gr.h index 49a0513..034a546 100644 --- a/libgralloc-qsd8k/gr.h +++ b/libgralloc/gr.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2008 The Android Open Source Project + * Copyright (c) 2011 Code Aurora Forum. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/libgralloc/gralloc.cpp b/libgralloc/gralloc.cpp new file mode 100644 index 0000000..640b255 --- /dev/null +++ b/libgralloc/gralloc.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2008, The Android Open Source Project + * Copyright (c) 2011, Code Aurora Forum. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "gr.h" +#include "gpu.h" +#include "memalloc.h" +#include "alloc_controller.h" + +using namespace gralloc; +using android::sp; + +int fb_device_open(const hw_module_t* module, const char* name, + hw_device_t** device); + +static int gralloc_device_open(const hw_module_t* module, const char* name, + hw_device_t** device); + +extern int gralloc_lock(gralloc_module_t const* module, + buffer_handle_t handle, int usage, + int l, int t, int w, int h, + void** vaddr); + +extern int gralloc_unlock(gralloc_module_t const* module, + buffer_handle_t handle); + +extern int gralloc_register_buffer(gralloc_module_t const* module, + buffer_handle_t handle); + +extern int gralloc_unregister_buffer(gralloc_module_t const* module, + buffer_handle_t handle); + +extern int gralloc_perform(struct gralloc_module_t const* module, + int operation, ... ); + +// HAL module methods +static struct hw_module_methods_t gralloc_module_methods = { + open: gralloc_device_open +}; + +// HAL module initialize +struct private_module_t HAL_MODULE_INFO_SYM = { + base: { + common: { + tag: HARDWARE_MODULE_TAG, + version_major: 1, + version_minor: 0, + id: GRALLOC_HARDWARE_MODULE_ID, + name: "Graphics Memory Allocator Module", + author: "The Android Open Source Project", + methods: &gralloc_module_methods, + dso: 0, + reserved: {0}, + }, + registerBuffer: gralloc_register_buffer, + unregisterBuffer: gralloc_unregister_buffer, + lock: gralloc_lock, + unlock: gralloc_unlock, + perform: gralloc_perform, + reserved_proc: {0}, + }, + framebuffer: 0, + fbFormat: 0, + flags: 0, + numBuffers: 0, + bufferMask: 0, + lock: PTHREAD_MUTEX_INITIALIZER, + currentBuffer: 0, +}; + +// Open Gralloc device +int gralloc_device_open(const hw_module_t* module, const char* name, + hw_device_t** device) +{ + int status = -EINVAL; + if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) { + const private_module_t* m = reinterpret_cast( + module); + gpu_context_t *dev; + sp alloc_ctrl = IAllocController::getInstance(); + dev = new gpu_context_t(m, alloc_ctrl); + *device = &dev->common; + status = 0; + } else { + status = fb_device_open(module, name, device); + } + return status; +} diff --git a/libgralloc-qsd8k/gralloc_priv.h b/libgralloc/gralloc_priv.h old mode 100755 new mode 100644 similarity index 96% rename from libgralloc-qsd8k/gralloc_priv.h rename to libgralloc/gralloc_priv.h index 8037812..9f305cc --- a/libgralloc-qsd8k/gralloc_priv.h +++ b/libgralloc/gralloc_priv.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2008 The Android Open Source Project - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2011, Code Aurora Forum. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -45,6 +45,11 @@ enum { /* Set this for allocating uncached memory (using O_DSYNC) * cannot be used with the system heap */ GRALLOC_USAGE_PRIVATE_UNCACHED = 0x00010000, + /* This flag needs to be set when using a system heap + * from ION. If not set, the system heap is assumed + * to be coming from ashmem + */ + GRALLOC_USAGE_PRIVATE_ION = 0x00020000, }; enum { @@ -68,6 +73,8 @@ enum { #define DEVICE_PMEM_SMIPOOL "/dev/pmem_smipool" /*****************************************************************************/ #ifdef __cplusplus + +//XXX: Remove framebuffer specific classes and defines to a different header template struct Node { @@ -226,7 +233,7 @@ struct private_module_t { float fps; int swapInterval; #ifdef __cplusplus - Queue disp; // non-empty when buffer is ready for display + Queue disp; // non-empty when buffer is ready for display #endif int currentIdx; struct avail_t avail[NUM_FRAMEBUFFERS_MAX]; @@ -262,7 +269,6 @@ struct private_handle_t : public native_handle { struct private_handle_t { native_handle_t nativeHandle; #endif - enum { PRIV_FLAGS_FRAMEBUFFER = 0x00000001, PRIV_FLAGS_USES_PMEM = 0x00000002, @@ -324,7 +330,7 @@ struct private_handle_t { const private_handle_t* hnd = (const private_handle_t*)h; if (!h || h->version != sizeof(native_handle) || h->numInts != sNumInts || h->numFds != sNumFds || - hnd->magic != sMagic) + hnd->magic != sMagic) { LOGE("invalid gralloc handle (at %p)", h); return -EINVAL; diff --git a/libgralloc/ionalloc.cpp b/libgralloc/ionalloc.cpp new file mode 100644 index 0000000..d92dedc --- /dev/null +++ b/libgralloc/ionalloc.cpp @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2011, Code Aurora Forum. All rights reserved. + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Code Aurora Forum, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include +#include +#include "ionalloc.h" + +using gralloc::IonAlloc; + +#define ION_DEVICE "/dev/ion" + +int IonAlloc::open_device() +{ + if(mIonFd == FD_INIT) + mIonFd = open(ION_DEVICE, O_RDONLY); + + if(mIonFd < 0 ) { + LOGE("%s: Failed to open ion device - %s", + __FUNCTION__, strerror(errno)); + mIonFd = FD_INIT; + return -errno; + } + return 0; +} + +void IonAlloc::close_device() +{ + if(mIonFd > 0) + close(mIonFd); + mIonFd = FD_INIT; +} + +int IonAlloc::alloc_buffer(alloc_data& data) +{ + int err = 0; + int ionSyncFd = FD_INIT; + int iFd = FD_INIT; + struct ion_handle_data handle_data; + struct ion_fd_data fd_data; + struct ion_allocation_data ionAllocData; + + void *base = 0; + + ionAllocData.len = data.size; + ionAllocData.align = data.align; + ionAllocData.flags = data.flags; + + err = open_device(); + if (err) + return err; + + if(data.uncached) { + // Use the sync FD to alloc and map + // when we need uncached memory + ionSyncFd = open(ION_DEVICE, O_RDONLY|O_DSYNC); + if(ionSyncFd < 0) { + LOGE("%s: Failed to open ion device - %s", + __FUNCTION__, strerror(errno)); + close_device(); + return -errno; + } + iFd = ionSyncFd; + } else { + iFd = mIonFd; + } + + err = ioctl(iFd, ION_IOC_ALLOC, &ionAllocData); + if(err) { + LOGE("ION_IOC_ALLOC failed with error - %s", strerror(errno)); + close_device(); + if(ionSyncFd >= 0) + close(ionSyncFd); + ionSyncFd = FD_INIT; + return err; + } + + fd_data.handle = ionAllocData.handle; + handle_data.handle = ionAllocData.handle; + LOGD("%s: Trying ION_IOC_MAP pid=%d handle=%p size=%d mIonFd=%d flags=%x", + __FUNCTION__, getpid(), ionAllocData.handle, + ionAllocData.len, mIonFd, ionAllocData.flags); + + err = ioctl(iFd, ION_IOC_MAP, &fd_data); + if(err) { + LOGE("%s: ION_IOC_MAP failed with error - %s", + __FUNCTION__, strerror(errno)); + ioctl(mIonFd, ION_IOC_FREE, &handle_data); + close_device(); + if(ionSyncFd >= 0) + close(ionSyncFd); + ionSyncFd = FD_INIT; + return err; + } + + base = mmap(0, ionAllocData.len, PROT_READ|PROT_WRITE, + MAP_SHARED, fd_data.fd, 0); + if(base == MAP_FAILED) { + LOGD("%s: Failed to map the allocated memory: %s", + __FUNCTION__, strerror(errno)); + err = -errno; + ioctl(mIonFd, ION_IOC_FREE, &handle_data); + close_device(); + ionSyncFd = FD_INIT; + return err; + } + //Close the uncached FD since we no longer need it; + if(ionSyncFd >= 0) + close(ionSyncFd); + ionSyncFd = FD_INIT; + + // Not doing memset for ION, uncomment if needed + // memset(base, 0, ionAllocData.len); + // Clean cache after memset + // clean_buffer(base, data.size, data.offset, fd_data.fd); + data.base = base; + data.fd = fd_data.fd; + ioctl(mIonFd, ION_IOC_FREE, &handle_data); + LOGD("%s: ION alloc succeeded - mIonFd=%d, SharedFD=%d PID=%d size=%d" + " ionHandle=%p", __FUNCTION__, mIonFd, fd_data.fd, getpid(), + ionAllocData.len, ionAllocData.handle); + return err; +} + + +int IonAlloc::free_buffer(void* base, size_t size, int offset, int fd) +{ + LOGD("%s:Freeing buffer size=%d base=%p mIonFd=%d fd=%d PID=%d", + __FUNCTION__, size, base, mIonFd, fd, getpid()); + int err = 0; + err = open_device(); + if (err) + return err; + + if(!base) { + LOGE("Invalid free"); + return -EINVAL; + } + err = unmap_buffer(base, size, offset); + close(fd); + return err; +} + +int IonAlloc::map_buffer(void **pBase, size_t size, int offset, int fd) +{ + LOGD("%s: Mapping buffer fd=%d size=%d PID=%d", __FUNCTION__, + fd, size, getpid()); + int err = 0; + void *base = 0; + // It is a (quirky) requirement of ION to have opened the + // ion fd in the process that is doing the mapping + err = open_device(); + if (err) + return err; + + base = mmap(0, size, PROT_READ| PROT_WRITE, + MAP_SHARED, fd, 0); + *pBase = base; + if(base == MAP_FAILED) { + LOGD("%s: Failed to map memory in the client: %s", + __FUNCTION__, strerror(errno)); + err = -errno; + } else { + LOGD("%s: Successfully mapped %d bytes", __FUNCTION__, size); + } + return err; +} + +int IonAlloc::unmap_buffer(void *base, size_t size, int offset) +{ + LOGD("%s: Unmapping buffer at address %p", __FUNCTION__, base); + int err = munmap(base, size); + if(err) { + LOGE("%s: Failed to unmap memory at %p: %s", + __FUNCTION__, base, strerror(errno)); + } + return err; + +} +int IonAlloc::clean_buffer(void *base, size_t size, int offset, int fd) +{ + // LOGD("%s: Clean buffer fd=%d base = %p size=%d PID=%d", __FUNCTION__, + // fd, base, size, getpid()); + struct ion_flush_data flush_data; + struct ion_fd_data fd_data; + struct ion_handle_data handle_data; + struct ion_handle* handle; + int err = 0; + + err = open_device(); + if (err) + return err; + + fd_data.fd = fd; + err = ioctl(mIonFd, ION_IOC_IMPORT, &fd_data); + if(err) { + LOGE("%s: ION_IOC_IMPORT failed with error - %s", + __FUNCTION__, strerror(errno)); + close_device(); + return err; + } + + handle_data.handle = fd_data.handle; + flush_data.handle = fd_data.handle; + flush_data.vaddr = base; + flush_data.offset = offset; + flush_data.length = size; + err = ioctl(mIonFd, ION_IOC_CLEAN_INV_CACHES, &flush_data); + if(err) { + LOGE("%s: ION_IOC_CLEAN_INV_CACHES failed with error - %s", + __FUNCTION__, strerror(errno)); + ioctl(mIonFd, ION_IOC_FREE, &handle_data); + close_device(); + return err; + } + ioctl(mIonFd, ION_IOC_FREE, &handle_data); + return err; +} + diff --git a/libgralloc/ionalloc.h b/libgralloc/ionalloc.h new file mode 100644 index 0000000..91a1d65 --- /dev/null +++ b/libgralloc/ionalloc.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2011, Code Aurora Forum. All rights reserved. + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Code Aurora Forum, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GRALLOC_IONALLOC_H +#define GRALLOC_IONALLOC_H + +#include "memalloc.h" +#include + +namespace gralloc { + + class IonAlloc : public IMemAlloc { + + public: + virtual int alloc_buffer(alloc_data& data); + + virtual int free_buffer(void *base, size_t size, + int offset, int fd); + + virtual int map_buffer(void **pBase, size_t size, + int offset, int fd); + + virtual int unmap_buffer(void *base, size_t size, + int offset); + + virtual int clean_buffer(void*base, size_t size, + int offset, int fd); + + IonAlloc() { mIonFd = FD_INIT; } + + ~IonAlloc() { close_device(); } + + private: + int mIonFd; + + int open_device(); + + void close_device(); + + }; + +} + +#endif /* GRALLOC_IONALLOC_H */ + diff --git a/libgralloc-qsd8k/mapper.cpp b/libgralloc/mapper.cpp old mode 100755 new mode 100644 similarity index 69% rename from libgralloc-qsd8k/mapper.cpp rename to libgralloc/mapper.cpp index 0e495be..e2ec899 --- a/libgralloc-qsd8k/mapper.cpp +++ b/libgralloc/mapper.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2008 The Android Open Source Project + * Copyright (c) 2011 Code Aurora Forum. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,20 +39,31 @@ #include "gralloc_priv.h" #include "gr.h" +#include "ionalloc.h" +#include "ashmemalloc.h" -// we need this for now because pmem cannot mmap at an offset -#define PMEM_HACK 1 - -/* desktop Linux needs a little help with gettid() */ -#if defined(ARCH_X86) && !defined(HAVE_ANDROID_OS) -#define __KERNEL__ -# include -pid_t gettid() { return syscall(__NR_gettid);} -#undef __KERNEL__ -#endif - +using gralloc::IMemAlloc; +using gralloc::IonAlloc; +using gralloc::AshmemAlloc; +using android::sp; /*****************************************************************************/ +// Return the type of allocator - +// these are used for mapping/unmapping +static sp getAllocator(int flags) +{ + sp memalloc; + if (flags & private_handle_t::PRIV_FLAGS_USES_ION) { + memalloc = new IonAlloc(); + } + if (flags & private_handle_t::PRIV_FLAGS_USES_ASHMEM) { + memalloc = new AshmemAlloc(); + } + + // XXX Return allocator for pmem + return memalloc; +} + static int gralloc_map(gralloc_module_t const* module, buffer_handle_t handle, void** vaddr) @@ -60,16 +72,16 @@ static int gralloc_map(gralloc_module_t const* module, void *mappedAddress; if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { size_t size = hnd->size; -#if PMEM_HACK - size += hnd->offset; -#endif - if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ASHMEM) { - mappedAddress = mmap(0, size, - PROT_READ|PROT_WRITE, MAP_SHARED | MAP_POPULATE, hnd->fd, 0); - } else { - mappedAddress = mmap(0, size, - PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0); + sp memalloc = getAllocator(hnd->flags) ; + int err = memalloc->map_buffer(&mappedAddress, size, + hnd->offset, hnd->fd); + if(err) { + LOGE("Could not mmap handle %p, fd=%d (%s)", + handle, hnd->fd, strerror(errno)); + hnd->base = 0; + return -errno; } + if (mappedAddress == MAP_FAILED) { LOGE("Could not mmap handle %p, fd=%d (%s)", handle, hnd->fd, strerror(errno)); @@ -77,7 +89,7 @@ static int gralloc_map(gralloc_module_t const* module, return -errno; } hnd->base = intptr_t(mappedAddress) + hnd->offset; - //LOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p", + //LOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p", // hnd->fd, hnd->offset, hnd->size, mappedAddress); } *vaddr = (void*)hnd->base; @@ -89,15 +101,14 @@ static int gralloc_unmap(gralloc_module_t const* module, { private_handle_t* hnd = (private_handle_t*)handle; if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { + int err = -EINVAL; void* base = (void*)hnd->base; size_t size = hnd->size; -#if PMEM_HACK - base = (void*)(intptr_t(base) - hnd->offset); - size += hnd->offset; -#endif - //LOGD("unmapping from %p, size=%d", base, size); - if (munmap(base, size) < 0) { - LOGE("Could not unmap %s", strerror(errno)); + sp memalloc = getAllocator(hnd->flags) ; + if(memalloc != NULL) + err = memalloc->unmap_buffer(base, size, hnd->offset); + if (err) { + LOGE("Could not unmap memory at address %p", base); } } hnd->base = 0; @@ -106,7 +117,7 @@ static int gralloc_unmap(gralloc_module_t const* module, /*****************************************************************************/ -static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER; /*****************************************************************************/ @@ -121,9 +132,9 @@ int gralloc_register_buffer(gralloc_module_t const* module, /* NOTE: we need to initialize the buffer as not mapped/not locked * because it shouldn't when this function is called the first time * in a new process. Ideally these flags shouldn't be part of the - * handle, but instead maintained in the kernel or at least + * handle, but instead maintained in the kernel or at least * out-of-line - */ + */ // if this handle was created in this process, then we keep it as is. private_handle_t* hnd = (private_handle_t*)handle; @@ -148,7 +159,7 @@ int gralloc_unregister_buffer(gralloc_module_t const* module, */ private_handle_t* hnd = (private_handle_t*)handle; - + LOGE_IF(hnd->lockState & private_handle_t::LOCK_STATE_READ_MASK, "[unregister] handle %p still locked (state=%08x)", hnd, hnd->lockState); @@ -215,7 +226,7 @@ int gralloc_lock(gralloc_module_t const* module, new_value = current_value; if (current_value & private_handle_t::LOCK_STATE_WRITE) { - // already locked for write + // already locked for write LOGE("handle %p already locked for write", handle); return -EBUSY; } else if (current_value & private_handle_t::LOCK_STATE_READ_MASK) { @@ -225,7 +236,7 @@ int gralloc_lock(gralloc_module_t const* module, return -EBUSY; } else { // this is not an error - //LOGD("%p already locked for read... count = %d", + //LOGD("%p already locked for read... count = %d", // handle, (current_value & ~(1<<31))); } } @@ -237,7 +248,7 @@ int gralloc_lock(gralloc_module_t const* module, } new_value++; - retry = android_atomic_cmpxchg(current_value, new_value, + retry = android_atomic_cmpxchg(current_value, new_value, (volatile int32_t*)&hnd->lockState); } while (retry); @@ -274,7 +285,7 @@ int gralloc_lock(gralloc_module_t const* module, return err; } -int gralloc_unlock(gralloc_module_t const* module, +int gralloc_unlock(gralloc_module_t const* module, buffer_handle_t handle) { if (private_handle_t::validate(handle) < 0) @@ -285,18 +296,9 @@ int gralloc_unlock(gralloc_module_t const* module, if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) { int err; - if (hnd->flags & (private_handle_t::PRIV_FLAGS_USES_PMEM | - private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP)) { - struct pmem_addr pmem_addr; - pmem_addr.vaddr = hnd->base; - pmem_addr.offset = hnd->offset; - pmem_addr.length = hnd->size; - err = ioctl( hnd->fd, PMEM_CLEAN_CACHES, &pmem_addr); - } else if ((hnd->flags & private_handle_t::PRIV_FLAGS_USES_ASHMEM)) { - unsigned long addr = hnd->base + hnd->offset; - err = ioctl(hnd->fd, ASHMEM_CACHE_FLUSH_RANGE, NULL); - } - + sp memalloc = getAllocator(hnd->flags) ; + err = memalloc->clean_buffer((void*)hnd->base, + hnd->size, hnd->offset, hnd->fd); LOGE_IF(err < 0, "cannot flush handle %p (offs=%x len=%x, flags = 0x%x) err=%s\n", hnd, hnd->offset, hnd->size, hnd->flags, strerror(errno)); hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH; @@ -321,8 +323,8 @@ int gralloc_unlock(gralloc_module_t const* module, new_value--; - } while (android_atomic_cmpxchg(current_value, new_value, - (volatile int32_t*)&hnd->lockState)); + } while (android_atomic_cmpxchg(current_value, new_value, + (volatile int32_t*)&hnd->lockState)); return 0; } @@ -337,48 +339,64 @@ int gralloc_perform(struct gralloc_module_t const* module, va_start(args, operation); switch (operation) { - case GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER: { - int fd = va_arg(args, int); - size_t size = va_arg(args, size_t); - size_t offset = va_arg(args, size_t); - void* base = va_arg(args, void*); + case GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER: + { + int fd = va_arg(args, int); + size_t size = va_arg(args, size_t); + size_t offset = va_arg(args, size_t); + void* base = va_arg(args, void*); - // validate that it's indeed a pmem buffer - pmem_region region; - if (ioctl(fd, PMEM_GET_SIZE, ®ion) < 0) { + native_handle_t** handle = va_arg(args, native_handle_t**); + int memoryFlags = va_arg(args, int); + private_handle_t* hnd = (private_handle_t*)native_handle_create( + private_handle_t::sNumFds, private_handle_t::sNumInts); + hnd->magic = private_handle_t::sMagic; + hnd->fd = fd; + unsigned int contigFlags = GRALLOC_USAGE_PRIVATE_ADSP_HEAP | + GRALLOC_USAGE_PRIVATE_EBI_HEAP | + GRALLOC_USAGE_PRIVATE_SMI_HEAP; + + if (memoryFlags & contigFlags) { + // check if the buffer is a pmem buffer + pmem_region region; + if (ioctl(fd, PMEM_GET_SIZE, ®ion) < 0) + hnd->flags = private_handle_t::PRIV_FLAGS_USES_ION; + else + hnd->flags = private_handle_t::PRIV_FLAGS_USES_PMEM | + private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH; + } else { + if (memoryFlags & GRALLOC_USAGE_PRIVATE_ION) + hnd->flags = private_handle_t::PRIV_FLAGS_USES_ION; + else + hnd->flags = private_handle_t::PRIV_FLAGS_USES_ASHMEM; + } + + hnd->size = size; + hnd->offset = offset; + hnd->base = intptr_t(base) + offset; + hnd->lockState = private_handle_t::LOCK_STATE_MAPPED; + hnd->gpuaddr = 0; + *handle = (native_handle_t *)hnd; + res = 0; + break; + + } + case GRALLOC_MODULE_PERFORM_UPDATE_BUFFER_HANDLE: + { + native_handle_t* handle = va_arg(args, native_handle_t*); + int w = va_arg(args, int); + int h = va_arg(args, int); + int f = va_arg(args, int); + private_handle_t* hnd = (private_handle_t*)handle; + hnd->width = w; + hnd->height = h; + if (hnd->format != f) { + hnd->format = f; + } break; } - - native_handle_t** handle = va_arg(args, native_handle_t**); - private_handle_t* hnd = (private_handle_t*)native_handle_create( - private_handle_t::sNumFds, private_handle_t::sNumInts); - hnd->magic = private_handle_t::sMagic; - hnd->fd = fd; - hnd->flags = private_handle_t::PRIV_FLAGS_USES_PMEM; - hnd->size = size; - hnd->offset = offset; - hnd->base = intptr_t(base) + offset; - hnd->lockState = private_handle_t::LOCK_STATE_MAPPED; - hnd->gpuaddr = 0; - *handle = (native_handle_t *)hnd; - res = 0; + default: break; - } - case GRALLOC_MODULE_PERFORM_UPDATE_BUFFER_HANDLE: { - native_handle_t* handle = va_arg(args, native_handle_t*); - int w = va_arg(args, int); - int h = va_arg(args, int); - int f = va_arg(args, int); - private_handle_t* hnd = (private_handle_t*)handle; - hnd->width = w; - hnd->height = h; - if (hnd->format != f) { - hnd->format = f; - } - break; - } - default: - break; } va_end(args); diff --git a/libgralloc/memalloc.h b/libgralloc/memalloc.h new file mode 100644 index 0000000..7b76d06 --- /dev/null +++ b/libgralloc/memalloc.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2011, Code Aurora Forum. All rights reserved. + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Code Aurora Forum, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GRALLOC_MEMALLOC_H +#define GRALLOC_MEMALLOC_H + +#include +#include + +namespace gralloc { + + struct alloc_data { + void *base; + int fd; + int offset; + size_t size; + size_t align; + unsigned int pHandle; + bool uncached; + unsigned int flags; + int bufferType; + int allocType; + }; + + class IMemAlloc : public android::RefBase { + + public: + // Allocate buffer - fill in the alloc_data + // structure and pass it in. Mapped address + // and fd are returned in the alloc_data struct + virtual int alloc_buffer(alloc_data& data) = 0; + + // Free buffer + virtual int free_buffer(void *base, size_t size, + int offset, int fd) = 0; + + // Map buffer + virtual int map_buffer(void **pBase, size_t size, + int offset, int fd) = 0; + + // Unmap buffer + virtual int unmap_buffer(void *base, size_t size, + int offset) = 0; + + // Clean and invalidate + virtual int clean_buffer(void *base, size_t size, + int offset, int fd) = 0; + + // Destructor + virtual ~IMemAlloc() {}; + + enum { + FD_INIT = -1, + }; + + }; + +} // end gralloc namespace +#endif // GRALLOC_MEMALLOC_H diff --git a/libgralloc-qsd8k/allocator.cpp b/libgralloc/pmem_bestfit_alloc.cpp similarity index 98% rename from libgralloc-qsd8k/allocator.cpp rename to libgralloc/pmem_bestfit_alloc.cpp index e7645b1..d13317e 100644 --- a/libgralloc-qsd8k/allocator.cpp +++ b/libgralloc/pmem_bestfit_alloc.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2009 The Android Open Source Project + * Copyright (c) 2011 Code Aurora Forum. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +17,7 @@ #include -#include "allocator.h" +#include "pmem_bestfit_alloc.h" // align all the memory blocks on a cache-line boundary @@ -50,8 +51,7 @@ ssize_t SimpleBestFitAllocator::setSize(size_t size) mList.insertHead(node); return size; } - - + size_t SimpleBestFitAllocator::size() const { return mHeapSize; diff --git a/libgralloc-qsd8k/allocator.h b/libgralloc/pmem_bestfit_alloc.h similarity index 97% rename from libgralloc-qsd8k/allocator.h rename to libgralloc/pmem_bestfit_alloc.h index dc81f51..16ff58a 100644 --- a/libgralloc-qsd8k/allocator.h +++ b/libgralloc/pmem_bestfit_alloc.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2009 The Android Open Source Project + * Copyright (c) 2011 Code Aurora Forum. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -71,7 +72,7 @@ public: mFirst = newNode; } } - + void insertTail(NODE* newNode) { if (mLast == 0) { insertHead(newNode); @@ -108,7 +109,7 @@ public: private: struct chunk_t { - chunk_t(size_t start, size_t size) + chunk_t(size_t start, size_t size) : start(start), size(size), free(1), prev(0), next(0) { } size_t start; diff --git a/libgralloc-qsd8k/pmemalloc.cpp b/libgralloc/pmemalloc.cpp old mode 100755 new mode 100644 similarity index 96% rename from libgralloc-qsd8k/pmemalloc.cpp rename to libgralloc/pmemalloc.cpp index fce2d87..010734b --- a/libgralloc-qsd8k/pmemalloc.cpp +++ b/libgralloc/pmemalloc.cpp @@ -54,7 +54,8 @@ PmemAllocator::~PmemAllocator() } -PmemUserspaceAllocator::PmemUserspaceAllocator(Deps& deps, Deps::Allocator& allocator, const char* pmemdev): +PmemUserspaceAllocator::PmemUserspaceAllocator(Deps& deps, + Deps::Allocator& allocator, const char* pmemdev): deps(deps), allocator(allocator), pmemdev(pmemdev), @@ -201,7 +202,8 @@ int PmemUserspaceAllocator::alloc_pmem_buffer(size_t size, int usage, } -int PmemUserspaceAllocator::free_pmem_buffer(size_t size, void* base, int offset, int fd) +int PmemUserspaceAllocator::free_pmem_buffer(size_t size, void* base, + int offset, int fd) { BEGIN_FUNC; int err = 0; @@ -277,7 +279,6 @@ int PmemKernelAllocator::alloc_pmem_buffer(size_t size, int usage, int err, offset = 0; int openFlags = get_open_flags(usage); const char *device; - if (usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP) { device = DEVICE_PMEM_ADSP; } else if (usage & GRALLOC_USAGE_PRIVATE_SMI_HEAP) { @@ -335,10 +336,12 @@ int PmemKernelAllocator::alloc_pmem_buffer(size_t size, int usage, } -int PmemKernelAllocator::free_pmem_buffer(size_t size, void* base, int offset, int fd) +int PmemKernelAllocator::free_pmem_buffer(size_t size, void* base, + int offset, int fd) { BEGIN_FUNC; - // The size should already be page aligned, now round it up to a power of 2 + // The size should already be page aligned, + // now round it up to a power of 2 // like we did when allocating. //size = clp2(size); diff --git a/libgralloc-qsd8k/pmemalloc.h b/libgralloc/pmemalloc.h old mode 100755 new mode 100644 similarity index 100% rename from libgralloc-qsd8k/pmemalloc.h rename to libgralloc/pmemalloc.h