diff options
-rw-r--r-- | modules/gralloc/Android.mk | 1 | ||||
-rw-r--r-- | modules/gralloc/allocator.cpp | 165 | ||||
-rw-r--r-- | modules/gralloc/allocator.h | 129 | ||||
-rw-r--r-- | modules/gralloc/framebuffer.cpp | 13 | ||||
-rw-r--r-- | modules/gralloc/gr.h | 1 | ||||
-rw-r--r-- | modules/gralloc/gralloc.cpp | 180 | ||||
-rw-r--r-- | modules/gralloc/gralloc_priv.h | 22 | ||||
-rw-r--r-- | modules/gralloc/mapper.cpp | 171 |
8 files changed, 45 insertions, 637 deletions
diff --git a/modules/gralloc/Android.mk b/modules/gralloc/Android.mk index 8f044c5..8946fac 100644 --- a/modules/gralloc/Android.mk +++ b/modules/gralloc/Android.mk @@ -23,7 +23,6 @@ LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw LOCAL_SHARED_LIBRARIES := liblog libcutils LOCAL_SRC_FILES := \ - allocator.cpp \ gralloc.cpp \ framebuffer.cpp \ mapper.cpp diff --git a/modules/gralloc/allocator.cpp b/modules/gralloc/allocator.cpp deleted file mode 100644 index e7645b1..0000000 --- a/modules/gralloc/allocator.cpp +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (C) 2009 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 <cutils/log.h> - -#include "allocator.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); - } - - LOGE_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; - } - 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/modules/gralloc/allocator.h b/modules/gralloc/allocator.h deleted file mode 100644 index b0d89e9..0000000 --- a/modules/gralloc/allocator.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (C) 2009 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_ALLOCATOR_H_ -#define GRALLOC_ALLOCATOR_H_ - -#include <stdint.h> -#include <sys/types.h> - -#include "gr.h" - -// ---------------------------------------------------------------------------- - -/* - * A simple templatized doubly linked-list implementation - */ - -template <typename NODE> -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: - - SimpleBestFitAllocator(); - SimpleBestFitAllocator(size_t size); - ~SimpleBestFitAllocator(); - - ssize_t setSize(size_t size); - - ssize_t allocate(size_t size, uint32_t flags = 0); - ssize_t deallocate(size_t offset); - 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<chunk_t> mList; - size_t mHeapSize; -}; - -#endif /* GRALLOC_ALLOCATOR_H_ */ diff --git a/modules/gralloc/framebuffer.cpp b/modules/gralloc/framebuffer.cpp index 7d2b582..0195103 100644 --- a/modules/gralloc/framebuffer.cpp +++ b/modules/gralloc/framebuffer.cpp @@ -92,18 +92,8 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(buffer); private_module_t* m = reinterpret_cast<private_module_t*>( dev->common.module); - - if (m->currentBuffer) { - m->base.unlock(&m->base, m->currentBuffer); - m->currentBuffer = 0; - } if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) { - - m->base.lock(&m->base, buffer, - private_module_t::PRIV_USAGE_LOCKED_FOR_POST, - 0, 0, m->info.xres, m->info.yres, NULL); - const size_t offset = hnd->base - m->framebuffer->base; m->info.activate = FB_ACTIVATE_VBL; m->info.yoffset = offset / m->finfo.line_length; @@ -292,8 +282,7 @@ int mapFrameBufferLocked(struct private_module_t* module) int err; size_t fbSize = roundUpToPageSize(finfo.line_length * info.yres_virtual); - module->framebuffer = new private_handle_t(dup(fd), fbSize, - private_handle_t::PRIV_FLAGS_USES_PMEM); + module->framebuffer = new private_handle_t(dup(fd), fbSize, 0); module->numBuffers = info.yres_virtual / info.yres; module->bufferMask = 0; diff --git a/modules/gralloc/gr.h b/modules/gralloc/gr.h index 1775bfa..3a43aa7 100644 --- a/modules/gralloc/gr.h +++ b/modules/gralloc/gr.h @@ -42,6 +42,7 @@ inline size_t roundUpToPageSize(size_t x) { int mapFrameBufferLocked(struct private_module_t* module); int terminateBuffer(gralloc_module_t const* module, private_handle_t* hnd); +int mapBuffer(gralloc_module_t const* module, private_handle_t* hnd); /*****************************************************************************/ diff --git a/modules/gralloc/gralloc.cpp b/modules/gralloc/gralloc.cpp index 404d8b8..a9ae784 100644 --- a/modules/gralloc/gralloc.cpp +++ b/modules/gralloc/gralloc.cpp @@ -35,15 +35,7 @@ #include <hardware/gralloc.h> #include "gralloc_priv.h" -#include "allocator.h" - -#if HAVE_ANDROID_OS -#include <linux/android_pmem.h> -#endif - -/*****************************************************************************/ - -static SimpleBestFitAllocator sAllocator; +#include "gr.h" /*****************************************************************************/ @@ -105,8 +97,6 @@ struct private_module_t HAL_MODULE_INFO_SYM = { bufferMask: 0, lock: PTHREAD_MUTEX_INITIALIZER, currentBuffer: 0, - pmem_master: -1, - pmem_master_base: 0 }; /*****************************************************************************/ @@ -146,7 +136,6 @@ static int gralloc_alloc_framebuffer_locked(alloc_device_t* dev, // create a "fake" handles for it intptr_t vaddr = intptr_t(m->framebuffer->base); private_handle_t* hnd = new private_handle_t(dup(m->framebuffer->fd), size, - private_handle_t::PRIV_FLAGS_USES_PMEM | private_handle_t::PRIV_FLAGS_FRAMEBUFFER); // find a free slot @@ -176,160 +165,28 @@ static int gralloc_alloc_framebuffer(alloc_device_t* dev, return err; } -static int init_pmem_area_locked(private_module_t* m) -{ - int err = 0; -#if HAVE_ANDROID_OS // should probably define HAVE_PMEM somewhere - int master_fd = open("/dev/pmem", O_RDWR, 0); - if (master_fd >= 0) { - - size_t size; - pmem_region region; - if (ioctl(master_fd, PMEM_GET_TOTAL_SIZE, ®ion) < 0) { - LOGE("PMEM_GET_TOTAL_SIZE failed, limp mode"); - size = 8<<20; // 8 MiB - } else { - size = region.len; - } - sAllocator.setSize(size); - - void* base = mmap(0, size, - PROT_READ|PROT_WRITE, MAP_SHARED, master_fd, 0); - if (base == MAP_FAILED) { - err = -errno; - base = 0; - close(master_fd); - master_fd = -1; - } - m->pmem_master = master_fd; - m->pmem_master_base = base; - } else { - err = -errno; - } - return err; -#else - return -1; -#endif -} - -static int init_pmem_area(private_module_t* m) -{ - pthread_mutex_lock(&m->lock); - int err = m->pmem_master; - if (err == -1) { - // first time, try to initialize pmem - err = init_pmem_area_locked(m); - if (err) { - m->pmem_master = err; - } - } else if (err < 0) { - // pmem couldn't be initialized, never use it - } else { - // pmem OK - err = 0; - } - pthread_mutex_unlock(&m->lock); - return err; -} - static int gralloc_alloc_buffer(alloc_device_t* dev, size_t size, int usage, buffer_handle_t* pHandle) { int err = 0; - int flags = 0; - int fd = -1; - void* base = 0; - int offset = 0; - int lockState = 0; size = roundUpToPageSize(size); -#if HAVE_ANDROID_OS // should probably define HAVE_PMEM somewhere - - 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; - } - - if ((flags & private_handle_t::PRIV_FLAGS_USES_PMEM) == 0) { -try_ashmem: - fd = ashmem_create_region("gralloc-buffer", size); - if (fd < 0) { - LOGE("couldn't create ashmem (%s)", strerror(-errno)); - err = -errno; - } - } else { - private_module_t* m = reinterpret_cast<private_module_t*>( - dev->common.module); - - err = init_pmem_area(m); - if (err == 0) { - // PMEM buffers are always mmapped - base = m->pmem_master_base; - lockState |= private_handle_t::LOCK_STATE_MAPPED; - - offset = sAllocator.allocate(size); - if (offset < 0) { - // no more pmem memory - err = -ENOMEM; - } else { - struct pmem_region sub = { offset, size }; - - // now create the "sub-heap" - fd = open("/dev/pmem", O_RDWR, 0); - err = fd < 0 ? fd : 0; - - // and connect to it - if (err == 0) - err = ioctl(fd, PMEM_CONNECT, m->pmem_master); - - // and make it available to the client process - if (err == 0) - err = ioctl(fd, PMEM_MAP, &sub); - - if (err < 0) { - err = -errno; - close(fd); - sAllocator.deallocate(offset); - fd = -1; - } - //LOGD_IF(!err, "allocating pmem size=%d, offset=%d", size, offset); - memset((char*)base + offset, 0, size); - } - } else { - if ((usage & GRALLOC_USAGE_HW_2D) == 0) { - // the caller didn't request PMEM, so we can try something else - flags &= ~private_handle_t::PRIV_FLAGS_USES_PMEM; - err = 0; - goto try_ashmem; - } else { - LOGE("couldn't open pmem (%s)", strerror(-errno)); - } - } - } - -#else // HAVE_ANDROID_OS - - fd = ashmem_create_region("Buffer", size); + fd = ashmem_create_region("gralloc-buffer", size); if (fd < 0) { LOGE("couldn't create ashmem (%s)", strerror(-errno)); err = -errno; } -#endif // HAVE_ANDROID_OS - if (err == 0) { - private_handle_t* hnd = new private_handle_t(fd, size, flags); - hnd->offset = offset; - hnd->base = int(base)+offset; - hnd->lockState = lockState; - *pHandle = hnd; + private_handle_t* hnd = new private_handle_t(fd, size, 0); + gralloc_module_t* module = reinterpret_cast<gralloc_module_t*>( + dev->common.module); + err = mapBuffer(module, hnd); + if (err == 0) { + *pHandle = hnd; + } } LOGE_IF(err, "gralloc failed err=%s", strerror(-err)); @@ -348,7 +205,7 @@ static int gralloc_alloc(alloc_device_t* dev, size_t size, stride; if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP || - format == HAL_PIXEL_FORMAT_YCbCr_422_SP) + format == HAL_PIXEL_FORMAT_YCbCr_422_SP) { // FIXME: there is no way to return the vstride int vstride; @@ -419,23 +276,6 @@ static int gralloc_free(alloc_device_t* dev, int index = (hnd->base - m->framebuffer->base) / bufferSize; m->bufferMask &= ~(1<<index); } else { -#if HAVE_ANDROID_OS - if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_PMEM) { - if (hnd->fd >= 0) { - struct pmem_region sub = { hnd->offset, hnd->size }; - int err = ioctl(hnd->fd, PMEM_UNMAP, &sub); - LOGE_IF(err<0, "PMEM_UNMAP failed (%s), " - "fd=%d, sub.offset=%lu, sub.size=%lu", - strerror(errno), hnd->fd, hnd->offset, hnd->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. - sAllocator.deallocate(hnd->offset); - } - } - } -#endif // HAVE_ANDROID_OS gralloc_module_t* module = reinterpret_cast<gralloc_module_t*>( dev->common.module); terminateBuffer(module, const_cast<private_handle_t*>(hnd)); diff --git a/modules/gralloc/gralloc_priv.h b/modules/gralloc/gralloc_priv.h index c3655a5..5d7db26 100644 --- a/modules/gralloc/gralloc_priv.h +++ b/modules/gralloc/gralloc_priv.h @@ -51,11 +51,6 @@ struct private_module_t { float xdpi; float ydpi; float fps; - - enum { - // flag to indicate we'll post this buffer - PRIV_USAGE_LOCKED_FOR_POST = 0x80000000 - }; }; /*****************************************************************************/ @@ -68,14 +63,7 @@ struct private_handle_t { #endif enum { - PRIV_FLAGS_FRAMEBUFFER = 0x00000001, - PRIV_FLAGS_USES_PMEM = 0x00000002, - }; - - enum { - LOCK_STATE_WRITE = 1<<31, - LOCK_STATE_MAPPED = 1<<30, - LOCK_STATE_READ_MASK = 0x3FFFFFFF + PRIV_FLAGS_FRAMEBUFFER = 0x00000001 }; // file-descriptors @@ -88,18 +76,16 @@ struct private_handle_t { // FIXME: the attributes below should be out-of-line int base; - int lockState; - int writeOwner; int pid; #ifdef __cplusplus - static const int sNumInts = 8; + static const int sNumInts = 6; static const int sNumFds = 1; static const int sMagic = 0x3141592; private_handle_t(int fd, int size, int flags) : fd(fd), magic(sMagic), flags(flags), size(size), offset(0), - base(0), lockState(0), writeOwner(0), pid(getpid()) + base(0), pid(getpid()) { version = sizeof(native_handle); numInts = sNumInts; @@ -110,7 +96,7 @@ struct private_handle_t { } bool usesPhysicallyContiguousMemory() { - return (flags & PRIV_FLAGS_USES_PMEM) != 0; + return false; } static int validate(const native_handle* h) { diff --git a/modules/gralloc/mapper.cpp b/modules/gralloc/mapper.cpp index e2caf79..33d0958 100644 --- a/modules/gralloc/mapper.cpp +++ b/modules/gralloc/mapper.cpp @@ -33,9 +33,6 @@ #include "gralloc_priv.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__ @@ -53,9 +50,6 @@ static int gralloc_map(gralloc_module_t const* module, private_handle_t* hnd = (private_handle_t*)handle; if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { size_t size = hnd->size; -#if PMEM_HACK - size += hnd->offset; -#endif void* mappedAddress = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0); if (mappedAddress == MAP_FAILED) { @@ -63,7 +57,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; @@ -77,10 +71,6 @@ static int gralloc_unmap(gralloc_module_t const* module, if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) { 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)); @@ -102,23 +92,14 @@ int gralloc_register_buffer(gralloc_module_t const* module, if (private_handle_t::validate(handle) < 0) return -EINVAL; - // In this implementation, we don't need to do anything here - - /* 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 - * out-of-line - */ - // if this handle was created in this process, then we keep it as is. + int err = 0; private_handle_t* hnd = (private_handle_t*)handle; if (hnd->pid != getpid()) { - hnd->base = 0; - hnd->lockState = 0; - hnd->writeOwner = 0; + void *vaddr; + err = gralloc_map(module, handle, &vaddr); } - return 0; + return err; } int gralloc_unregister_buffer(gralloc_module_t const* module, @@ -127,52 +108,29 @@ int gralloc_unregister_buffer(gralloc_module_t const* module, if (private_handle_t::validate(handle) < 0) return -EINVAL; - /* - * If the buffer has been mapped during a lock operation, it's time - * to un-map it. It's an error to be here with a locked buffer. - * NOTE: the framebuffer is handled differently and is never unmapped. - */ - - 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); - // never unmap buffers that were created in this process + private_handle_t* hnd = (private_handle_t*)handle; if (hnd->pid != getpid()) { - if (hnd->lockState & private_handle_t::LOCK_STATE_MAPPED) { + if (hnd->base) { gralloc_unmap(module, handle); } - hnd->base = 0; - hnd->lockState = 0; - hnd->writeOwner = 0; } return 0; } -int terminateBuffer(gralloc_module_t const* module, +int mapBuffer(gralloc_module_t const* module, private_handle_t* hnd) { - /* - * If the buffer has been mapped during a lock operation, it's time - * to un-map it. It's an error to be here with a locked buffer. - */ + void* vaddr; + return gralloc_map(module, hnd, &vaddr); +} - LOGE_IF(hnd->lockState & private_handle_t::LOCK_STATE_READ_MASK, - "[terminate] handle %p still locked (state=%08x)", - hnd, hnd->lockState); - - if (hnd->lockState & private_handle_t::LOCK_STATE_MAPPED) { +int terminateBuffer(gralloc_module_t const* module, + private_handle_t* hnd) +{ + if (hnd->base) { // this buffer was mapped, unmap it now - if ((hnd->flags & private_handle_t::PRIV_FLAGS_USES_PMEM) && - (hnd->pid == getpid())) { - // ... unless it's a "master" pmem buffer, that is a buffer - // mapped in the process it's been allocated. - // (see gralloc_alloc_buffer()) - } else { - gralloc_unmap(module, hnd); - } + gralloc_unmap(module, hnd); } return 0; @@ -183,100 +141,29 @@ int gralloc_lock(gralloc_module_t const* module, int l, int t, int w, int h, void** vaddr) { + // this is called when a buffer is being locked for software + // access. in thin implementation we have nothing to do since + // not synchronization with the h/w is needed. + // typically this is used to wait for the h/w to finish with + // this buffer if relevant. the data cache may need to be + // flushed or invalidated depending on the usage bits and the + // hardware. + if (private_handle_t::validate(handle) < 0) return -EINVAL; - int err = 0; private_handle_t* hnd = (private_handle_t*)handle; - int32_t current_value, new_value; - int retry; - - do { - current_value = hnd->lockState; - new_value = current_value; - - if (current_value & private_handle_t::LOCK_STATE_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) { - // already locked for read - if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_HW_RENDER)) { - LOGE("handle %p already locked for read", handle); - return -EBUSY; - } else { - // this is not an error - //LOGD("%p already locked for read... count = %d", - // handle, (current_value & ~(1<<31))); - } - } - - // not currently locked - if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_HW_RENDER)) { - // locking for write - new_value |= private_handle_t::LOCK_STATE_WRITE; - } - new_value++; - - retry = android_atomic_cmpxchg(current_value, new_value, - (volatile int32_t*)&hnd->lockState); - } while (retry); - - if (new_value & private_handle_t::LOCK_STATE_WRITE) { - // locking for write, store the tid - hnd->writeOwner = gettid(); - } - - if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) { - if (!(current_value & private_handle_t::LOCK_STATE_MAPPED)) { - // we need to map for real - pthread_mutex_t* const lock = &sMapLock; - pthread_mutex_lock(lock); - if (!(hnd->lockState & private_handle_t::LOCK_STATE_MAPPED)) { - err = gralloc_map(module, handle, vaddr); - if (err == 0) { - android_atomic_or(private_handle_t::LOCK_STATE_MAPPED, - (volatile int32_t*)&(hnd->lockState)); - } - } - pthread_mutex_unlock(lock); - } - *vaddr = (void*)hnd->base; - } - - return err; + *vaddr = (void*)hnd->base; + return 0; } int gralloc_unlock(gralloc_module_t const* module, buffer_handle_t handle) { + // we're done with a software buffer. nothing to do in this + // implementation. typically this is used to flush the data cache. + if (private_handle_t::validate(handle) < 0) return -EINVAL; - - private_handle_t* hnd = (private_handle_t*)handle; - int32_t current_value, new_value; - - do { - current_value = hnd->lockState; - new_value = current_value; - - if (current_value & private_handle_t::LOCK_STATE_WRITE) { - // locked for write - if (hnd->writeOwner == gettid()) { - hnd->writeOwner = 0; - new_value &= ~private_handle_t::LOCK_STATE_WRITE; - } - } - - if ((new_value & private_handle_t::LOCK_STATE_READ_MASK) == 0) { - LOGE("handle %p not locked", handle); - return -EINVAL; - } - - new_value--; - - } while (android_atomic_cmpxchg(current_value, new_value, - (volatile int32_t*)&hnd->lockState)); - return 0; } |