From e25f40c946b4b66e8fb30f4a19f4a3f974afe49b Mon Sep 17 00:00:00 2001 From: Andrew Sutherland Date: Thu, 2 Aug 2012 21:38:40 -0500 Subject: [PATCH] bring back pmem/ashmem allocators o removed RefBase usages o ifdef for TARGET_USES_ION Change-Id: Ief331f4c847b86be0e37d24983097af1f53234a2 --- common.mk | 3 + libcopybit/copybit.cpp | 3 +- libcopybit/copybit_c2d.cpp | 2 +- libgralloc/Android.mk | 9 +- libgralloc/alloc_controller.cpp | 161 ++++++++++++- libgralloc/alloc_controller.h | 41 +++- libgralloc/ashmemalloc.cpp | 138 +++++++++++ libgralloc/ashmemalloc.h | 56 +++++ libgralloc/gralloc.cpp | 2 +- libgralloc/gralloc_priv.h | 74 ++++++ libgralloc/mapper.cpp | 7 +- libgralloc/pmem_bestfit_alloc.cpp | 195 +++++++++++++++ libgralloc/pmem_bestfit_alloc.h | 129 ++++++++++ libgralloc/pmemalloc.cpp | 388 ++++++++++++++++++++++++++++++ libgralloc/pmemalloc.h | 105 ++++++++ libhwcomposer/hwc_copybit.cpp | 3 +- liboverlay/overlayMem.h | 5 +- 17 files changed, 1310 insertions(+), 11 deletions(-) create mode 100644 libgralloc/ashmemalloc.cpp create mode 100644 libgralloc/ashmemalloc.h create mode 100644 libgralloc/pmem_bestfit_alloc.cpp create mode 100644 libgralloc/pmem_bestfit_alloc.h create mode 100644 libgralloc/pmemalloc.cpp create mode 100644 libgralloc/pmemalloc.h diff --git a/common.mk b/common.mk index a48476e..287da3e 100644 --- a/common.mk +++ b/common.mk @@ -16,6 +16,9 @@ common_libs := liblog libutils libcutils libhardware #Common C flags common_flags := -DDEBUG_CALC_FPS -Wno-missing-field-initializers +ifeq ($(TARGET_USES_ION),true) +common_flags += -DUSE_ION +endif ifeq ($(ARCH_ARM_HAVE_NEON),true) common_flags += -D__ARM_HAVE_NEON endif diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp index 2e2956c..ee8c12e 100644 --- a/libcopybit/copybit.cpp +++ b/libcopybit/copybit.cpp @@ -426,7 +426,8 @@ static int stretch_copybit( } if(src->format == HAL_PIXEL_FORMAT_YV12) { - int usage = GRALLOC_USAGE_PRIVATE_MM_HEAP; + int usage = GRALLOC_USAGE_PRIVATE_ADSP_HEAP | + GRALLOC_USAGE_PRIVATE_MM_HEAP; if (0 == alloc_buffer(&yv12_handle,src->w,src->h, src->format, usage)){ if(0 == convertYV12toYCrCb420SP(src,yv12_handle)){ diff --git a/libcopybit/copybit_c2d.cpp b/libcopybit/copybit_c2d.cpp index 5eec414..4022385 100644 --- a/libcopybit/copybit_c2d.cpp +++ b/libcopybit/copybit_c2d.cpp @@ -932,7 +932,7 @@ static int get_temp_buffer(const bufferInfo& info, alloc_data& data) int allocFlags = GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP; if (sAlloc == 0) { - sAlloc = gralloc::IAllocController::getInstance(); + sAlloc = gralloc::IAllocController::getInstance(false); } if (sAlloc == 0) { diff --git a/libgralloc/Android.mk b/libgralloc/Android.mk index ae745f2..d87af79 100644 --- a/libgralloc/Android.mk +++ b/libgralloc/Android.mk @@ -35,5 +35,12 @@ LOCAL_MODULE_TAGS := optional LOCAL_C_INCLUDES := $(common_includes) LOCAL_SHARED_LIBRARIES := $(common_libs) libgenlock LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"memalloc\" -LOCAL_SRC_FILES := ionalloc.cpp alloc_controller.cpp +LOCAL_SRC_FILES := alloc_controller.cpp +ifeq ($(TARGET_USES_ION),true) + LOCAL_SRC_FILES += ionalloc.cpp +else + LOCAL_SRC_FILES += pmemalloc.cpp \ + ashmemalloc.cpp \ + pmem_bestfit_alloc.cpp +endif include $(BUILD_SHARED_LIBRARY) diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp index 1802a75..4b4675b 100644 --- a/libgralloc/alloc_controller.cpp +++ b/libgralloc/alloc_controller.cpp @@ -32,7 +32,12 @@ #include "gralloc_priv.h" #include "alloc_controller.h" #include "memalloc.h" +#ifdef USE_ION #include "ionalloc.h" +#else +#include "pmemalloc.h" +#include "ashmemalloc.h" +#endif #include "gr.h" #include "comptype.h" @@ -75,15 +80,23 @@ static bool useUncached(int usage) } IAllocController* IAllocController::sController = NULL; -IAllocController* IAllocController::getInstance(void) +IAllocController* IAllocController::getInstance(bool useMasterHeap) { if(sController == NULL) { +#ifdef USE_ION sController = new IonController(); +#else + if(useMasterHeap) + sController = new PmemAshmemController(); + else + sController = new PmemKernelController(); +#endif } return sController; } +#ifdef USE_ION //-------------- IonController-----------------------// IonController::IonController() { @@ -161,6 +174,148 @@ IMemAlloc* IonController::getAllocator(int flags) return memalloc; } +#else +//-------------- PmemKernelController-----------------------// +PmemKernelController::PmemKernelController() +{ + mPmemAdspAlloc = new PmemKernelAlloc(DEVICE_PMEM_ADSP); + // XXX: Right now, there is no need to maintain an instance + // of the SMI allocator as we need it only in a few cases +} + +PmemKernelController::~PmemKernelController() +{ +} + +int PmemKernelController::allocate(alloc_data& data, int usage) +{ + int ret = 0; + bool adspFallback = false; + if (!(usage & GRALLOC_USAGE_PRIVATE_SMI_HEAP)) + adspFallback = true; + + // Try SMI first + if ((usage & GRALLOC_USAGE_PRIVATE_SMI_HEAP) || + (usage & GRALLOC_USAGE_EXTERNAL_DISP) || + (usage & GRALLOC_USAGE_PROTECTED)) + { + int tempFd = open(DEVICE_PMEM_SMIPOOL, O_RDWR, 0); + if(tempFd > 0) { + close(tempFd); + IMemAlloc* memalloc; + memalloc = new PmemKernelAlloc(DEVICE_PMEM_SMIPOOL); + ret = memalloc->alloc_buffer(data); + if(ret >= 0) + return ret; + else { + if(adspFallback) + ALOGW("Allocation from SMI failed, trying ADSP"); + } + } + } + + if ((usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP) || adspFallback) { + ret = mPmemAdspAlloc->alloc_buffer(data); + } + return ret; +} + +IMemAlloc* PmemKernelController::getAllocator(int flags) +{ + IMemAlloc* memalloc; + if (flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP) + memalloc = mPmemAdspAlloc; + else { + ALOGE("%s: Invalid flags passed: 0x%x", __FUNCTION__, flags); + memalloc = NULL; + } + + return memalloc; +} + +//-------------- PmemAshmmemController-----------------------// + +PmemAshmemController::PmemAshmemController() +{ + mPmemUserspaceAlloc = new PmemUserspaceAlloc(); + mAshmemAlloc = new AshmemAlloc(); + mPmemKernelCtrl = new PmemKernelController(); +} + +PmemAshmemController::~PmemAshmemController() +{ +} + +int PmemAshmemController::allocate(alloc_data& data, int usage) +{ + int ret = 0; + data.allocType = 0; + + // Make buffers cacheable by default + data.uncached = false; + + // Override if we explicitly need uncached buffers + if (usage & GRALLOC_USAGE_PRIVATE_UNCACHED) + data.uncached = true; + + // If ADSP or SMI is requested use the kernel controller + if(usage & (GRALLOC_USAGE_PRIVATE_ADSP_HEAP| + GRALLOC_USAGE_PRIVATE_SMI_HEAP)) { + ret = mPmemKernelCtrl->allocate(data, usage); + if(ret < 0) + ALOGE("%s: Failed to allocate ADSP/SMI memory", __func__); + else + data.allocType = private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP; + return ret; + } + + if(usage & GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP) { + ret = mAshmemAlloc->alloc_buffer(data); + if(ret >= 0) { + data.allocType = private_handle_t::PRIV_FLAGS_USES_ASHMEM; + data.allocType |= private_handle_t::PRIV_FLAGS_NONCONTIGUOUS_MEM; + } + return ret; + } + + // if no memory specific flags are set, + // default to EBI heap, so that bypass + // can work. We can fall back to system + // heap if we run out. + ret = mPmemUserspaceAlloc->alloc_buffer(data); + + // Fallback + if(ret >= 0 ) { + data.allocType = private_handle_t::PRIV_FLAGS_USES_PMEM; + } else if(ret < 0 && canFallback(usage, false)) { + ALOGW("Falling back to ashmem"); + ret = mAshmemAlloc->alloc_buffer(data); + if(ret >= 0) { + data.allocType = private_handle_t::PRIV_FLAGS_USES_ASHMEM; + data.allocType |= private_handle_t::PRIV_FLAGS_NONCONTIGUOUS_MEM; + } + } + + return ret; +} + +IMemAlloc* PmemAshmemController::getAllocator(int flags) +{ + IMemAlloc* memalloc; + if (flags & private_handle_t::PRIV_FLAGS_USES_PMEM) + memalloc = mPmemUserspaceAlloc; + else if (flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP) + memalloc = mPmemKernelCtrl->getAllocator(flags); + else if (flags & private_handle_t::PRIV_FLAGS_USES_ASHMEM) + memalloc = mAshmemAlloc; + else { + ALOGE("%s: Invalid flags passed: 0x%x", __FUNCTION__, flags); + memalloc = NULL; + } + + return memalloc; +} +#endif size_t getBufferSizeAndDimensions(int width, int height, int format, int& alignedw, int &alignedh) @@ -243,7 +398,7 @@ int alloc_buffer(private_handle_t **pHnd, int w, int h, int format, int usage) alloc_data data; int alignedw, alignedh; gralloc::IAllocController* sAlloc = - gralloc::IAllocController::getInstance(); + gralloc::IAllocController::getInstance(false); data.base = 0; data.fd = -1; data.offset = 0; @@ -271,7 +426,7 @@ int alloc_buffer(private_handle_t **pHnd, int w, int h, int format, int usage) void free_buffer(private_handle_t *hnd) { gralloc::IAllocController* sAlloc = - gralloc::IAllocController::getInstance(); + gralloc::IAllocController::getInstance(false); if (hnd && hnd->fd > 0) { IMemAlloc* memalloc = sAlloc->getAllocator(hnd->flags); memalloc->free_buffer((void*)hnd->base, hnd->size, hnd->offset, hnd->fd); diff --git a/libgralloc/alloc_controller.h b/libgralloc/alloc_controller.h index f04917a..b3b1523 100644 --- a/libgralloc/alloc_controller.h +++ b/libgralloc/alloc_controller.h @@ -47,13 +47,14 @@ class IAllocController { virtual ~IAllocController() {}; - static IAllocController* getInstance(void); + static IAllocController* getInstance(bool useMasterHeap); private: static IAllocController* sController; }; +#ifdef USE_ION class IonController : public IAllocController { public: @@ -67,5 +68,43 @@ class IonController : public IAllocController { IonAlloc* mIonAlloc; }; +#else +class PmemKernelController : public IAllocController { + + public: + virtual int allocate(alloc_data& data, int usage); + + virtual IMemAlloc* getAllocator(int flags); + + PmemKernelController (); + + ~PmemKernelController (); + + private: + IMemAlloc* mPmemAdspAlloc; + +}; + +// Main pmem controller - this should only +// be used within gralloc +class PmemAshmemController : public IAllocController { + + public: + virtual int allocate(alloc_data& data, int usage); + + virtual IMemAlloc* getAllocator(int flags); + + PmemAshmemController(); + + ~PmemAshmemController(); + + private: + IMemAlloc* mPmemUserspaceAlloc; + IMemAlloc* mAshmemAlloc; + IAllocController* mPmemKernelCtrl; + +}; +#endif + } //end namespace gralloc #endif // GRALLOC_ALLOCCONTROLLER_H diff --git a/libgralloc/ashmemalloc.cpp b/libgralloc/ashmemalloc.cpp new file mode 100644 index 0000000..b659d90 --- /dev/null +++ b/libgralloc/ashmemalloc.cpp @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2011-2012, 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) { + ALOGE("couldn't create ashmem (%s)", strerror(errno)); + err = -errno; + } else { + if (ashmem_set_prot_region(fd, prot) < 0) { + ALOGE("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) { + ALOGE("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); + ALOGD("ashmem: Allocated buffer base:%p size:%d fd:%d", + base, data.size, fd); + + } + return err; + +} + +int AshmemAlloc::free_buffer(void* base, size_t size, int offset, int fd) +{ + ALOGD("ashmem: Freeing buffer base:%p size:%d fd:%d", + base, size, fd); + int err = 0; + + if(!base) { + ALOGE("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) +{ + int err = 0; + void *base = 0; + + base = mmap(0, size, PROT_READ| PROT_WRITE, + MAP_SHARED|MAP_POPULATE, fd, 0); + *pBase = base; + if(base == MAP_FAILED) { + ALOGE("ashmem: Failed to map memory in the client: %s", + strerror(errno)); + err = -errno; + } else { + ALOGD("ashmem: Mapped buffer base:%p size:%d fd:%d", + base, size, fd); + } + return err; +} + +int AshmemAlloc::unmap_buffer(void *base, size_t size, int offset) +{ + ALOGD("ashmem: Unmapping buffer base: %p size: %d", base, size); + int err = munmap(base, size); + if(err) { + ALOGE("ashmem: Failed to unmap memory at %p: %s", + base, strerror(errno)); + } + return err; + +} +int AshmemAlloc::clean_buffer(void *base, size_t size, int offset, int fd) +{ + int err = 0; + if (ioctl(fd, ASHMEM_CACHE_FLUSH_RANGE, NULL)) { + ALOGE("ashmem: ASHMEM_CACHE_FLUSH_RANGE failed fd = %d", fd); + } + + return err; +} + diff --git a/libgralloc/ashmemalloc.h b/libgralloc/ashmemalloc.h new file mode 100644 index 0000000..50daf04 --- /dev/null +++ b/libgralloc/ashmemalloc.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2011-2012, 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/gralloc.cpp b/libgralloc/gralloc.cpp index 7924ae3..97f0c6a 100644 --- a/libgralloc/gralloc.cpp +++ b/libgralloc/gralloc.cpp @@ -100,7 +100,7 @@ int gralloc_device_open(const hw_module_t* module, const char* name, const private_module_t* m = reinterpret_cast( module); gpu_context_t *dev; - IAllocController* alloc_ctrl = IAllocController::getInstance(); + IAllocController* alloc_ctrl = IAllocController::getInstance(true); dev = new gpu_context_t(m, alloc_ctrl); *device = &dev->common; status = 0; diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h index d199f4c..a848915 100644 --- a/libgralloc/gralloc_priv.h +++ b/libgralloc/gralloc_priv.h @@ -34,6 +34,7 @@ enum { /* gralloc usage bits indicating the type * of allocation that should be used */ +#ifdef USE_ION /* SYSTEM heap comes from kernel vmalloc, * can never be uncached, is not secured*/ GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP = GRALLOC_USAGE_PRIVATE_0, @@ -83,6 +84,65 @@ enum { */ GRALLOC_USAGE_PRIVATE_ADSP_HEAP = 0x0, GRALLOC_USAGE_PRIVATE_SMI_HEAP = 0x0, +#else + /* ADSP heap is deprecated, use only if using pmem */ + GRALLOC_USAGE_PRIVATE_ADSP_HEAP = GRALLOC_USAGE_PRIVATE_0, + /* SF heap is used for application buffers, is not secured */ + GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP = GRALLOC_USAGE_PRIVATE_1, + /* SMI heap is deprecated, use only if using pmem */ + GRALLOC_USAGE_PRIVATE_SMI_HEAP = GRALLOC_USAGE_PRIVATE_2, + /* SYSTEM heap comes from kernel vmalloc, + * can never be uncached, is not secured*/ + GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP = GRALLOC_USAGE_PRIVATE_3, + /* IOMMU heap comes from manually allocated pages, + * can be cached/uncached, is not secured */ + GRALLOC_USAGE_PRIVATE_IOMMU_HEAP = 0x01000000, + /* MM heap is a carveout heap for video, can be secured*/ + GRALLOC_USAGE_PRIVATE_MM_HEAP = 0x02000000, + /* WRITEBACK heap is a carveout heap for writeback, can be secured*/ + GRALLOC_USAGE_PRIVATE_WRITEBACK_HEAP = 0x04000000, + /* CAMERA heap is a carveout heap for camera, is not secured*/ + GRALLOC_USAGE_PRIVATE_CAMERA_HEAP = 0x08000000, + + /* Set this for allocating uncached memory (using O_DSYNC) + * cannot be used with noncontiguous heaps */ + GRALLOC_USAGE_PRIVATE_UNCACHED = 0x00100000, + + /* This flag needs to be set when using a non-contiguous heap from ION. + * If not set, the system heap is assumed to be coming from ashmem + */ + GRALLOC_USAGE_PRIVATE_ION = 0x00200000, + + /* This flag can be set to disable genlock synchronization + * for the gralloc buffer. If this flag is set the caller + * is required to perform explicit synchronization. + * WARNING - flag is outside the standard PRIVATE region + * and may need to be moved if the gralloc API changes + */ + GRALLOC_USAGE_PRIVATE_UNSYNCHRONIZED = 0X00400000, + + /* Set this flag when you need to avoid mapping the memory in userspace */ + GRALLOC_USAGE_PRIVATE_DO_NOT_MAP = 0X00800000, + + /* Buffer content should be displayed on an external display only */ + GRALLOC_USAGE_PRIVATE_EXTERNAL_ONLY = 0x00010000, + + /* Only this buffer content should be displayed on external, even if + * other EXTERNAL_ONLY buffers are available. Used during suspend. + */ + GRALLOC_USAGE_PRIVATE_EXTERNAL_BLOCK = 0x00020000, + + /* Use this flag to request content protected buffers. Please note + * that this flag is different from the GRALLOC_USAGE_PROTECTED flag + * which can be used for buffers that are not secured for DRM + * but still need to be protected from screen captures + * 0x00040000 is reserved and these values are subject to change. + */ + GRALLOC_USAGE_PRIVATE_CP_BUFFER = 0x00080000, + + /* Close Caption displayed on an external display only */ + GRALLOC_USAGE_PRIVATE_EXTERNAL_CC = 0x000F0000, +#endif }; enum { @@ -91,11 +151,25 @@ enum { GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER = 0x080000001, }; +#ifdef USE_ION #define GRALLOC_HEAP_MASK (GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP |\ GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP |\ GRALLOC_USAGE_PRIVATE_IOMMU_HEAP |\ GRALLOC_USAGE_PRIVATE_MM_HEAP |\ GRALLOC_USAGE_PRIVATE_CAMERA_HEAP) +#else +#define GRALLOC_HEAP_MASK (GRALLOC_USAGE_PRIVATE_ADSP_HEAP |\ + GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP |\ + GRALLOC_USAGE_PRIVATE_SMI_HEAP |\ + GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP |\ + GRALLOC_USAGE_PRIVATE_IOMMU_HEAP |\ + GRALLOC_USAGE_PRIVATE_MM_HEAP |\ + GRALLOC_USAGE_PRIVATE_WRITEBACK_HEAP |\ + GRALLOC_USAGE_PRIVATE_CAMERA_HEAP) +#define DEVICE_PMEM "/dev/pmem" +#define DEVICE_PMEM_ADSP "/dev/pmem_adsp" +#define DEVICE_PMEM_SMIPOOL "/dev/pmem_smipool" +#endif /*****************************************************************************/ enum { diff --git a/libgralloc/mapper.cpp b/libgralloc/mapper.cpp index 99f9f08..b099245 100644 --- a/libgralloc/mapper.cpp +++ b/libgralloc/mapper.cpp @@ -51,7 +51,7 @@ using namespace gralloc; static IMemAlloc* getAllocator(int flags) { IMemAlloc* memalloc; - IAllocController* alloc_ctrl = IAllocController::getInstance(); + IAllocController* alloc_ctrl = IAllocController::getInstance(true); memalloc = alloc_ctrl->getAllocator(flags); return memalloc; } @@ -327,7 +327,12 @@ int gralloc_perform(struct gralloc_module_t const* module, private_handle_t::sNumFds, private_handle_t::sNumInts); hnd->magic = private_handle_t::sMagic; hnd->fd = fd; +#ifdef USE_ION 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; +#endif hnd->size = size; hnd->offset = offset; hnd->base = intptr_t(base) + offset; diff --git a/libgralloc/pmem_bestfit_alloc.cpp b/libgralloc/pmem_bestfit_alloc.cpp new file mode 100644 index 0000000..82302fa --- /dev/null +++ b/libgralloc/pmem_bestfit_alloc.cpp @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * Copyright (c) 2011-2012, 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 "pmem_bestfit_alloc.h" + + +// align all the memory blocks on a cache-line boundary +const int SimpleBestFitAllocator::kMemoryAlign = 32; + +SimpleBestFitAllocator::SimpleBestFitAllocator() +: mHeapSize(0) +{ +} + +SimpleBestFitAllocator::SimpleBestFitAllocator(size_t size) +: mHeapSize(0) +{ + setSize(size); +} + +SimpleBestFitAllocator::~SimpleBestFitAllocator() +{ + while(!mList.isEmpty()) { + delete mList.remove(mList.head()); + } +} + +ssize_t SimpleBestFitAllocator::setSize(size_t size) +{ + Locker::Autolock _l(mLock); + if (mHeapSize != 0) return -EINVAL; + size_t pagesize = getpagesize(); + mHeapSize = ((size + pagesize-1) & ~(pagesize-1)); + chunk_t* node = new chunk_t(0, mHeapSize / kMemoryAlign); + mList.insertHead(node); + return size; +} + +size_t SimpleBestFitAllocator::size() const +{ + return mHeapSize; +} + +ssize_t SimpleBestFitAllocator::allocate(size_t size, uint32_t flags) +{ + Locker::Autolock _l(mLock); + if (mHeapSize == 0) return -EINVAL; + ssize_t offset = alloc(size, flags); + return offset; +} + +ssize_t SimpleBestFitAllocator::deallocate(size_t offset) +{ + Locker::Autolock _l(mLock); + if (mHeapSize == 0) return -EINVAL; + chunk_t const * const freed = dealloc(offset); + if (freed) { + return 0; + } + return -ENOENT; +} + +ssize_t SimpleBestFitAllocator::alloc(size_t size, uint32_t flags) +{ + if (size == 0) { + return 0; + } + size = (size + kMemoryAlign-1) / kMemoryAlign; + chunk_t* free_chunk = 0; + chunk_t* cur = mList.head(); + + size_t pagesize = getpagesize(); + while (cur) { + int extra = ( -cur->start & ((pagesize/kMemoryAlign)-1) ) ; + + // best fit + if (cur->free && (cur->size >= (size+extra))) { + if ((!free_chunk) || (cur->size < free_chunk->size)) { + free_chunk = cur; + } + if (cur->size == size) { + break; + } + } + cur = cur->next; + } + + if (free_chunk) { + const size_t free_size = free_chunk->size; + free_chunk->free = 0; + free_chunk->size = size; + if (free_size > size) { + int extra = ( -free_chunk->start & ((pagesize/kMemoryAlign)-1) ) ; + if (extra) { + chunk_t* split = new chunk_t(free_chunk->start, extra); + free_chunk->start += extra; + mList.insertBefore(free_chunk, split); + } + + ALOGE_IF(((free_chunk->start*kMemoryAlign)&(pagesize-1)), + "page is not aligned!!!"); + + const ssize_t tail_free = free_size - (size+extra); + if (tail_free > 0) { + chunk_t* split = new chunk_t( + free_chunk->start + free_chunk->size, tail_free); + mList.insertAfter(free_chunk, split); + } + } + return (free_chunk->start)*kMemoryAlign; + } + // we are out of PMEM. Print pmem stats + // check if there is any leak or fragmentation + + ALOGD (" Out of PMEM. Dumping PMEM stats for debugging"); + ALOGD (" ------------- PRINT PMEM STATS --------------"); + + cur = mList.head(); + static uint32_t node_count; + static uint64_t allocated, free_space; + + while (cur) { + ALOGD (" Node %d -> Start Address : %u Size %u Free info %d",\ + node_count++, cur->start, cur->size, cur->free); + + // if cur-> free is 1 , the node is free + // calculate the total allocated and total free stats also + + if (cur->free) + free_space += cur->size; + else + allocated += cur->size; + // read next node + cur = cur->next; + } + ALOGD (" Total Allocated: %l Total Free: %l", allocated, free_space ); + + node_count = 0; + allocated = 0; + free_space = 0; + ALOGD ("----------------------------------------------"); + return -ENOMEM; +} + +SimpleBestFitAllocator::chunk_t* SimpleBestFitAllocator::dealloc(size_t start) +{ + start = start / kMemoryAlign; + chunk_t* cur = mList.head(); + while (cur) { + if (cur->start == start) { + LOG_FATAL_IF(cur->free, + "block at offset 0x%08lX of size 0x%08lX already freed", + cur->start*kMemoryAlign, cur->size*kMemoryAlign); + + // merge freed blocks together + chunk_t* freed = cur; + cur->free = 1; + do { + chunk_t* const p = cur->prev; + chunk_t* const n = cur->next; + if (p && (p->free || !cur->size)) { + freed = p; + p->size += cur->size; + mList.remove(cur); + delete cur; + } + cur = n; + } while (cur && cur->free); + + LOG_FATAL_IF(!freed->free, + "freed block at offset 0x%08lX of size 0x%08lX is not free!", + freed->start * kMemoryAlign, freed->size * kMemoryAlign); + + return freed; + } + cur = cur->next; + } + return 0; +} diff --git a/libgralloc/pmem_bestfit_alloc.h b/libgralloc/pmem_bestfit_alloc.h new file mode 100644 index 0000000..4346ec3 --- /dev/null +++ b/libgralloc/pmem_bestfit_alloc.h @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * Copyright (c) 2011-2012, 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_ALLOCATOR_H_ +#define GRALLOC_ALLOCATOR_H_ + +#include +#include + +#include "gr.h" +#include "pmemalloc.h" + +// ---------------------------------------------------------------------------- + +/* + * A simple templatized doubly linked-list implementation + */ +template +class LinkedList +{ + NODE* mFirst; + NODE* mLast; + + public: + LinkedList() : mFirst(0), mLast(0) { } + bool isEmpty() const { return mFirst == 0; } + NODE const* head() const { return mFirst; } + NODE* head() { return mFirst; } + NODE const* tail() const { return mLast; } + NODE* tail() { return mLast; } + + void insertAfter(NODE* node, NODE* newNode) { + newNode->prev = node; + newNode->next = node->next; + if (node->next == 0) mLast = newNode; + else node->next->prev = newNode; + node->next = newNode; + } + + void insertBefore(NODE* node, NODE* newNode) { + newNode->prev = node->prev; + newNode->next = node; + if (node->prev == 0) mFirst = newNode; + else node->prev->next = newNode; + node->prev = newNode; + } + + void insertHead(NODE* newNode) { + if (mFirst == 0) { + mFirst = mLast = newNode; + newNode->prev = newNode->next = 0; + } else { + newNode->prev = 0; + newNode->next = mFirst; + mFirst->prev = newNode; + mFirst = newNode; + } + } + + void insertTail(NODE* newNode) { + if (mLast == 0) { + insertHead(newNode); + } else { + newNode->prev = mLast; + newNode->next = 0; + mLast->next = newNode; + mLast = newNode; + } + } + + NODE* remove(NODE* node) { + if (node->prev == 0) mFirst = node->next; + else node->prev->next = node->next; + if (node->next == 0) mLast = node->prev; + else node->next->prev = node->prev; + return node; + } +}; + +class SimpleBestFitAllocator : public gralloc::PmemUserspaceAlloc::Allocator +{ + public: + + SimpleBestFitAllocator(); + SimpleBestFitAllocator(size_t size); + virtual ~SimpleBestFitAllocator(); + + virtual ssize_t setSize(size_t size); + + virtual ssize_t allocate(size_t size, uint32_t flags = 0); + virtual ssize_t deallocate(size_t offset); + virtual size_t size() const; + + private: + struct chunk_t { + chunk_t(size_t start, size_t size) + : start(start), size(size), free(1), prev(0), next(0) { + } + size_t start; + size_t size : 28; + int free : 4; + mutable chunk_t* prev; + mutable chunk_t* next; + }; + + ssize_t alloc(size_t size, uint32_t flags); + chunk_t* dealloc(size_t start); + + static const int kMemoryAlign; + mutable Locker mLock; + LinkedList mList; + size_t mHeapSize; +}; +#endif /* GRALLOC_ALLOCATOR_H_ */ diff --git a/libgralloc/pmemalloc.cpp b/libgralloc/pmemalloc.cpp new file mode 100644 index 0000000..4f61308 --- /dev/null +++ b/libgralloc/pmemalloc.cpp @@ -0,0 +1,388 @@ +/* + * Copyright (c) 2011-2012, 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. + */ + +//#define LOG_NDEBUG 0 +#include +#include +#include +#include +#include +#include +#include +#include "gralloc_priv.h" +#include "pmemalloc.h" +#include "pmem_bestfit_alloc.h" + +using namespace gralloc; + +// Common functions between userspace +// and kernel allocators +static int getPmemTotalSize(int fd, size_t* size) +{ + //XXX: 7x27 + int err = 0; + pmem_region region; + if (ioctl(fd, PMEM_GET_TOTAL_SIZE, ®ion)) { + err = -errno; + } else { + *size = region.len; + } + return err; +} + +static int getOpenFlags(bool uncached) +{ + if(uncached) + return O_RDWR | O_SYNC; + else + return O_RDWR; +} + +static int connectPmem(int fd, int master_fd) { + if (ioctl(fd, PMEM_CONNECT, master_fd)) + return -errno; + return 0; +} + +static int mapSubRegion(int fd, int offset, size_t size) { + struct pmem_region sub = { offset, size }; + if (ioctl(fd, PMEM_MAP, &sub)) + return -errno; + return 0; +} + +static int unmapSubRegion(int fd, int offset, size_t size) { + struct pmem_region sub = { offset, size }; + if (ioctl(fd, PMEM_UNMAP, &sub)) + return -errno; + return 0; +} + +static int alignPmem(int fd, size_t size, int align) { + struct pmem_allocation allocation; + allocation.size = size; + allocation.align = align; + if (ioctl(fd, PMEM_ALLOCATE_ALIGNED, &allocation)) + return -errno; + return 0; +} + +static int cleanPmem(void *base, size_t size, int offset, int fd) { + struct pmem_addr pmem_addr; + pmem_addr.vaddr = (unsigned long) base; + pmem_addr.offset = offset; + pmem_addr.length = size; + if (ioctl(fd, PMEM_CLEAN_INV_CACHES, &pmem_addr)) + return -errno; + return 0; +} + +//-------------- PmemUserspaceAlloc-----------------------// +PmemUserspaceAlloc::PmemUserspaceAlloc() +{ + mPmemDev = DEVICE_PMEM; + mMasterFd = FD_INIT; + mAllocator = new SimpleBestFitAllocator(); + pthread_mutex_init(&mLock, NULL); +} + +PmemUserspaceAlloc::~PmemUserspaceAlloc() +{ +} + +int PmemUserspaceAlloc::init_pmem_area_locked() +{ + ALOGD("%s: Opening master pmem FD", __FUNCTION__); + int err = 0; + int fd = open(mPmemDev, O_RDWR, 0); + if (fd >= 0) { + size_t size = 0; + err = getPmemTotalSize(fd, &size); + ALOGD("%s: Total pmem size: %d", __FUNCTION__, size); + if (err < 0) { + ALOGE("%s: PMEM_GET_TOTAL_SIZE failed (%d), limp mode", mPmemDev, + err); + size = 8<<20; // 8 MiB + } + mAllocator->setSize(size); + + void* base = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, + 0); + if (base == MAP_FAILED) { + err = -errno; + ALOGE("%s: Failed to map pmem master fd: %s", mPmemDev, + strerror(errno)); + base = 0; + close(fd); + fd = -1; + } else { + mMasterFd = fd; + mMasterBase = base; + } + } else { + err = -errno; + ALOGE("%s: Failed to open pmem device: %s", mPmemDev, + strerror(errno)); + } + return err; +} + +int PmemUserspaceAlloc::init_pmem_area() +{ + pthread_mutex_lock(&mLock); + int err = mMasterFd; + if (err == FD_INIT) { + // first time, try to initialize pmem + ALOGD("%s: Initializing pmem area", __FUNCTION__); + err = init_pmem_area_locked(); + if (err) { + ALOGE("%s: failed to initialize pmem area", mPmemDev); + mMasterFd = err; + } + } else if (err < 0) { + // pmem couldn't be initialized, never use it + } else { + // pmem OK + err = 0; + } + pthread_mutex_unlock(&mLock); + return err; + +} + +int PmemUserspaceAlloc::alloc_buffer(alloc_data& data) +{ + int err = init_pmem_area(); + if (err == 0) { + void* base = mMasterBase; + size_t size = data.size; + int offset = mAllocator->allocate(size); + if (offset < 0) { + // no more pmem memory + ALOGE("%s: No more pmem available", mPmemDev); + err = -ENOMEM; + } else { + int openFlags = getOpenFlags(data.uncached); + + // now create the "sub-heap" + int fd = open(mPmemDev, openFlags, 0); + err = fd < 0 ? fd : 0; + + // and connect to it + if (err == 0) + err = connectPmem(fd, mMasterFd); + + // and make it available to the client process + if (err == 0) + err = mapSubRegion(fd, offset, size); + + if (err < 0) { + ALOGE("%s: Failed to initialize pmem sub-heap: %d", mPmemDev, + err); + close(fd); + mAllocator->deallocate(offset); + fd = -1; + } else { + ALOGV("%s: Allocated buffer base:%p size:%d offset:%d fd:%d", + mPmemDev, base, size, offset, fd); + memset((char*)base + offset, 0, size); + //Clean cache before flushing to ensure pmem is properly flushed + err = clean_buffer((void*)((intptr_t) base + offset), size, offset, fd); + if (err < 0) { + ALOGE("cleanPmem failed: (%s)", strerror(errno)); + } + cacheflush(intptr_t(base) + offset, intptr_t(base) + offset + size, 0); + data.base = base; + data.offset = offset; + data.fd = fd; + } + } + } + return err; + +} + +int PmemUserspaceAlloc::free_buffer(void* base, size_t size, int offset, int fd) +{ + ALOGV("%s: Freeing buffer base:%p size:%d offset:%d fd:%d", + mPmemDev, base, size, offset, fd); + int err = 0; + if (fd >= 0) { + int err = unmapSubRegion(fd, offset, size); + ALOGE_IF(err<0, "PMEM_UNMAP failed (%s), fd=%d, sub.offset=%u, " + "sub.size=%u", strerror(errno), fd, offset, size); + if (err == 0) { + // we can't deallocate the memory in case of UNMAP failure + // because it would give that process access to someone else's + // surfaces, which would be a security breach. + mAllocator->deallocate(offset); + } + close(fd); + } + return err; +} + +int PmemUserspaceAlloc::map_buffer(void **pBase, size_t size, int offset, int fd) +{ + int err = 0; + size += offset; + void *base = mmap(0, size, PROT_READ| PROT_WRITE, + MAP_SHARED, fd, 0); + *pBase = base; + if(base == MAP_FAILED) { + err = -errno; + ALOGE("%s: Failed to map buffer size:%d offset:%d fd:%d Error: %s", + mPmemDev, size, offset, fd, strerror(errno)); + } else { + ALOGV("%s: Mapped buffer base:%p size:%d offset:%d fd:%d", + mPmemDev, base, size, offset, fd); + } + return err; + +} + +int PmemUserspaceAlloc::unmap_buffer(void *base, size_t size, int offset) +{ + int err = 0; + //pmem hack + base = (void*)(intptr_t(base) - offset); + size += offset; + ALOGV("%s: Unmapping buffer base:%p size:%d offset:%d", + mPmemDev , base, size, offset); + if (munmap(base, size) < 0) { + err = -errno; + ALOGE("%s: Failed to unmap memory at %p :%s", + mPmemDev, base, strerror(errno)); + + } + + return err; +} + +int PmemUserspaceAlloc::clean_buffer(void *base, size_t size, int offset, int fd) +{ + return cleanPmem(base, size, offset, fd); +} + + +//-------------- PmemKernelAlloc-----------------------// + +PmemKernelAlloc::PmemKernelAlloc(const char* pmemdev) : + mPmemDev(pmemdev) +{ +} + +PmemKernelAlloc::~PmemKernelAlloc() +{ +} + +int PmemKernelAlloc::alloc_buffer(alloc_data& data) +{ + int err, offset = 0; + int openFlags = getOpenFlags(data.uncached); + int size = data.size; + + int fd = open(mPmemDev, openFlags, 0); + if (fd < 0) { + err = -errno; + ALOGE("%s: Error opening %s", __FUNCTION__, mPmemDev); + return err; + } + + if (data.align == 8192) { + // Tile format buffers need physical alignment to 8K + // Default page size does not need this ioctl + err = alignPmem(fd, size, 8192); + if (err < 0) { + ALOGE("alignPmem failed"); + } + } + void* base = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if (base == MAP_FAILED) { + err = -errno; + ALOGE("%s: failed to map pmem fd: %s", mPmemDev, + strerror(errno)); + close(fd); + return err; + } + memset(base, 0, size); + clean_buffer((void*)((intptr_t) base + offset), size, offset, fd); + data.base = base; + data.offset = 0; + data.fd = fd; + ALOGV("%s: Allocated buffer base:%p size:%d fd:%d", + mPmemDev, base, size, fd); + return 0; + +} + +int PmemKernelAlloc::free_buffer(void* base, size_t size, int offset, int fd) +{ + ALOGV("%s: Freeing buffer base:%p size:%d fd:%d", + mPmemDev, base, size, fd); + + int err = unmap_buffer(base, size, offset); + close(fd); + return err; +} + +int PmemKernelAlloc::map_buffer(void **pBase, size_t size, int offset, int fd) +{ + int err = 0; + void *base = mmap(0, size, PROT_READ| PROT_WRITE, + MAP_SHARED, fd, 0); + *pBase = base; + if(base == MAP_FAILED) { + err = -errno; + ALOGE("%s: Failed to map memory in the client: %s", + mPmemDev, strerror(errno)); + } else { + ALOGV("%s: Mapped buffer base:%p size:%d, fd:%d", + mPmemDev, base, size, fd); + } + return err; + +} + +int PmemKernelAlloc::unmap_buffer(void *base, size_t size, int offset) +{ + int err = 0; + if (munmap(base, size)) { + err = -errno; + ALOGW("%s: Error unmapping memory at %p: %s", + mPmemDev, base, strerror(err)); + } + return err; + +} +int PmemKernelAlloc::clean_buffer(void *base, size_t size, int offset, int fd) +{ + return cleanPmem(base, size, offset, fd); +} + diff --git a/libgralloc/pmemalloc.h b/libgralloc/pmemalloc.h new file mode 100644 index 0000000..1151d13 --- /dev/null +++ b/libgralloc/pmemalloc.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2011-2012, 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_PMEMALLOC_H +#define GRALLOC_PMEMALLOC_H + +#include +#include "memalloc.h" + +namespace gralloc { +class PmemUserspaceAlloc : public IMemAlloc { + + public: + class Allocator { + public: + virtual ~Allocator() {}; + virtual ssize_t setSize(size_t size) = 0; + virtual size_t size() const = 0; + virtual ssize_t allocate(size_t size, uint32_t flags = 0) = 0; + virtual ssize_t deallocate(size_t offset) = 0; + }; + + 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); + + PmemUserspaceAlloc(); + + ~PmemUserspaceAlloc(); + + private: + int mMasterFd; + void* mMasterBase; + const char* mPmemDev; + Allocator* mAllocator; + pthread_mutex_t mLock; + int init_pmem_area(); + int init_pmem_area_locked(); + +}; + +class PmemKernelAlloc : 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); + + PmemKernelAlloc(const char* device); + + ~PmemKernelAlloc(); + private: + const char* mPmemDev; + + +}; + +} +#endif /* GRALLOC_PMEMALLOC_H */ diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp index f14d00f..1ca77b9 100644 --- a/libhwcomposer/hwc_copybit.cpp +++ b/libhwcomposer/hwc_copybit.cpp @@ -382,7 +382,8 @@ int CopyBit::drawLayerUsingCopybit(hwc_context_t *dev, hwc_layer_t *layer, } ALOGE("%s:%d::tmp_w = %d,tmp_h = %d",__FUNCTION__,__LINE__,tmp_w,tmp_h); - int usage = GRALLOC_USAGE_PRIVATE_MM_HEAP; + int usage = GRALLOC_USAGE_PRIVATE_ADSP_HEAP | + GRALLOC_USAGE_PRIVATE_MM_HEAP; if (0 == alloc_buffer(&tmpHnd, tmp_w, tmp_h, fbHandle->format, usage)){ copybit_image_t tmp_dst; diff --git a/liboverlay/overlayMem.h b/liboverlay/overlayMem.h index 60ed8fe..d22e6f5 100644 --- a/liboverlay/overlayMem.h +++ b/liboverlay/overlayMem.h @@ -108,7 +108,7 @@ inline OvMem::OvMem() { mAllocType = 0; mBufSz = 0; mNumBuffers = 0; - mAlloc = gralloc::IAllocController::getInstance(); + mAlloc = gralloc::IAllocController::getInstance(false); } inline OvMem::~OvMem() { } @@ -121,6 +121,9 @@ inline bool OvMem::open(uint32_t numbufs, if(isSecure) { allocFlags |= GRALLOC_USAGE_PRIVATE_MM_HEAP; allocFlags |= GRALLOC_USAGE_PRIVATE_CP_BUFFER; +#ifndef USE_ION + allocFlags |= GRALLOC_USAGE_PRIVATE_DO_NOT_MAP; +#endif } int err = 0;