diff options
-rw-r--r-- | include/private/ui/sw_gralloc_handle.h | 83 | ||||
-rw-r--r-- | libs/ui/GraphicBufferAllocator.cpp | 22 | ||||
-rw-r--r-- | libs/ui/GraphicBufferMapper.cpp | 158 |
3 files changed, 253 insertions, 10 deletions
diff --git a/include/private/ui/sw_gralloc_handle.h b/include/private/ui/sw_gralloc_handle.h new file mode 100644 index 0000000..b3d333e --- /dev/null +++ b/include/private/ui/sw_gralloc_handle.h @@ -0,0 +1,83 @@ +/* + * 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 ANDROID_UI_PRIVATE_SW_GRALLOC_HANDLE_H +#define ANDROID_UI_PRIVATE_SW_GRALLOC_HANDLE_H + +#include <stdint.h> +#include <limits.h> +#include <sys/cdefs.h> +#include <hardware/gralloc.h> +#include <errno.h> + +#include <cutils/native_handle.h> + +namespace android { + +/*****************************************************************************/ + +struct sw_gralloc_handle_t : public native_handle +{ + // file-descriptors + int fd; + // ints + int magic; + int size; + int base; + int prot; + int pid; + + static const int sNumInts = 5; + static const int sNumFds = 1; + static const int sMagic = '_sgh'; + + sw_gralloc_handle_t() : + fd(-1), magic(sMagic), size(0), base(0), prot(0), pid(getpid()) + { + version = sizeof(native_handle); + numInts = sNumInts; + numFds = sNumFds; + } + ~sw_gralloc_handle_t() { + magic = 0; + } + + static int validate(const native_handle* h) { + const sw_gralloc_handle_t* hnd = (const sw_gralloc_handle_t*)h; + if (!h || h->version != sizeof(native_handle) || + h->numInts != sNumInts || h->numFds != sNumFds || + hnd->magic != sMagic) + { + return -EINVAL; + } + return 0; + } + + static status_t alloc(uint32_t w, uint32_t h, int format, + int usage, buffer_handle_t* handle, int32_t* stride); + static status_t free(sw_gralloc_handle_t* hnd); + static status_t registerBuffer(sw_gralloc_handle_t* hnd); + static status_t unregisterBuffer(sw_gralloc_handle_t* hnd); + static status_t lock(sw_gralloc_handle_t* hnd, int usage, + int l, int t, int w, int h, void** vaddr); + static status_t unlock(sw_gralloc_handle_t* hnd); +}; + +/*****************************************************************************/ + +}; // namespace android + +#endif /* ANDROID_UI_PRIVATE_SW_GRALLOC_HANDLE_H */ diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp index 10b1051..57d5fc3 100644 --- a/libs/ui/GraphicBufferAllocator.cpp +++ b/libs/ui/GraphicBufferAllocator.cpp @@ -22,6 +22,7 @@ #include <ui/GraphicBufferAllocator.h> +#include <private/ui/sw_gralloc_handle.h> namespace android { // --------------------------------------------------------------------------- @@ -29,7 +30,8 @@ namespace android { ANDROID_SINGLETON_STATIC_INSTANCE( GraphicBufferAllocator ) Mutex GraphicBufferAllocator::sLock; -KeyedVector<buffer_handle_t, GraphicBufferAllocator::alloc_rec_t> GraphicBufferAllocator::sAllocList; +KeyedVector<buffer_handle_t, + GraphicBufferAllocator::alloc_rec_t> GraphicBufferAllocator::sAllocList; GraphicBufferAllocator::GraphicBufferAllocator() : mAllocDev(0) @@ -83,8 +85,13 @@ status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat forma h = clamp(h); // we have a h/w allocator and h/w buffer is requested - status_t err = mAllocDev->alloc(mAllocDev, - w, h, format, usage, handle, stride); + status_t err; + + if (usage & GRALLOC_USAGE_HW_MASK) { + err = mAllocDev->alloc(mAllocDev, w, h, format, usage, handle, stride); + } else { + err = sw_gralloc_handle_t::alloc(w, h, format, usage, handle, stride); + } LOGW_IF(err, "alloc(%u, %u, %d, %08x, ...) failed %d (%s)", w, h, format, usage, err, strerror(-err)); @@ -113,9 +120,14 @@ status_t GraphicBufferAllocator::free(buffer_handle_t handle) { Mutex::Autolock _l(mLock); - status_t err = mAllocDev->free(mAllocDev, handle); + status_t err; + if (sw_gralloc_handle_t::validate(handle) < 0) { + err = mAllocDev->free(mAllocDev, handle); + } else { + err = sw_gralloc_handle_t::free((sw_gralloc_handle_t*)handle); + } + LOGW_IF(err, "free(...) failed %d (%s)", err, strerror(-err)); - if (err == NO_ERROR) { Mutex::Autolock _l(sLock); KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList); diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp index dd529e6..ce2acd0 100644 --- a/libs/ui/GraphicBufferMapper.cpp +++ b/libs/ui/GraphicBufferMapper.cpp @@ -17,7 +17,15 @@ #define LOG_TAG "GraphicBufferMapper" #include <stdint.h> +#ifdef HAVE_ANDROID_OS // just want PAGE_SIZE define +# include <asm/page.h> +#else +# include <sys/user.h> +#endif #include <errno.h> +#include <sys/mman.h> + +#include <cutils/ashmem.h> #include <utils/Errors.h> #include <utils/Log.h> @@ -27,6 +35,8 @@ #include <hardware/gralloc.h> +#include <private/ui/sw_gralloc_handle.h> + namespace android { // --------------------------------------------------------------------------- @@ -46,7 +56,12 @@ GraphicBufferMapper::GraphicBufferMapper() status_t GraphicBufferMapper::registerBuffer(buffer_handle_t handle) { - status_t err = mAllocMod->registerBuffer(mAllocMod, handle); + status_t err; + if (sw_gralloc_handle_t::validate(handle) < 0) { + err = mAllocMod->registerBuffer(mAllocMod, handle); + } else { + err = sw_gralloc_handle_t::registerBuffer((sw_gralloc_handle_t*)handle); + } LOGW_IF(err, "registerBuffer(%p) failed %d (%s)", handle, err, strerror(-err)); return err; @@ -54,7 +69,12 @@ status_t GraphicBufferMapper::registerBuffer(buffer_handle_t handle) status_t GraphicBufferMapper::unregisterBuffer(buffer_handle_t handle) { - status_t err = mAllocMod->unregisterBuffer(mAllocMod, handle); + status_t err; + if (sw_gralloc_handle_t::validate(handle) < 0) { + err = mAllocMod->unregisterBuffer(mAllocMod, handle); + } else { + err = sw_gralloc_handle_t::unregisterBuffer((sw_gralloc_handle_t*)handle); + } LOGW_IF(err, "unregisterBuffer(%p) failed %d (%s)", handle, err, strerror(-err)); return err; @@ -63,18 +83,146 @@ status_t GraphicBufferMapper::unregisterBuffer(buffer_handle_t handle) status_t GraphicBufferMapper::lock(buffer_handle_t handle, int usage, const Rect& bounds, void** vaddr) { - status_t err = mAllocMod->lock(mAllocMod, handle, usage, - bounds.left, bounds.top, bounds.width(), bounds.height(), vaddr); + status_t err; + if (sw_gralloc_handle_t::validate(handle) < 0) { + err = mAllocMod->lock(mAllocMod, handle, usage, + bounds.left, bounds.top, bounds.width(), bounds.height(), + vaddr); + } else { + err = sw_gralloc_handle_t::lock((sw_gralloc_handle_t*)handle, usage, + bounds.left, bounds.top, bounds.width(), bounds.height(), + vaddr); + } LOGW_IF(err, "lock(...) failed %d (%s)", err, strerror(-err)); return err; } status_t GraphicBufferMapper::unlock(buffer_handle_t handle) { - status_t err = mAllocMod->unlock(mAllocMod, handle); + status_t err; + if (sw_gralloc_handle_t::validate(handle) < 0) { + err = mAllocMod->unlock(mAllocMod, handle); + } else { + err = sw_gralloc_handle_t::unlock((sw_gralloc_handle_t*)handle); + } LOGW_IF(err, "unlock(...) failed %d (%s)", err, strerror(-err)); return err; } // --------------------------------------------------------------------------- + +status_t sw_gralloc_handle_t::alloc(uint32_t w, uint32_t h, int format, + int usage, buffer_handle_t* pHandle, int32_t* pStride) +{ + int align = 4; + int bpp = 0; + switch (format) { + case HAL_PIXEL_FORMAT_RGBA_8888: + case HAL_PIXEL_FORMAT_RGBX_8888: + case HAL_PIXEL_FORMAT_BGRA_8888: + bpp = 4; + break; + case HAL_PIXEL_FORMAT_RGB_888: + bpp = 3; + break; + case HAL_PIXEL_FORMAT_RGB_565: + case HAL_PIXEL_FORMAT_RGBA_5551: + case HAL_PIXEL_FORMAT_RGBA_4444: + bpp = 2; + break; + default: + return -EINVAL; + } + size_t bpr = (w*bpp + (align-1)) & ~(align-1); + size_t size = bpr * h; + size_t stride = bpr / bpp; + size = (size + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1); + + int fd = ashmem_create_region("sw-gralloc-buffer", size); + if (fd < 0) { + LOGE("ashmem_create_region(size=%d) failed (%s)", + size, strerror(-errno)); + return -errno; + } + + int prot = PROT_READ; + if (usage & GRALLOC_USAGE_SW_WRITE_MASK) + prot |= PROT_WRITE; + + 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); + return -errno; + } + + void* base = mmap(0, size, prot, MAP_SHARED, fd, 0); + if (base == MAP_FAILED) { + LOGE("alloc mmap(fd=%d, size=%d, prot=%x) failed (%s)", + fd, size, prot, strerror(-errno)); + close(fd); + return -errno; + } + + sw_gralloc_handle_t* hnd = new sw_gralloc_handle_t(); + hnd->fd = fd; + hnd->size = size; + hnd->base = intptr_t(base); + hnd->prot = prot; + *pStride = stride; + *pHandle = hnd; + + return NO_ERROR; +} + +status_t sw_gralloc_handle_t::free(sw_gralloc_handle_t* hnd) +{ + if (hnd->base) { + munmap((void*)hnd->base, hnd->size); + } + if (hnd->fd >= 0) { + close(hnd->fd); + } + delete hnd; + return NO_ERROR; +} + +status_t sw_gralloc_handle_t::registerBuffer(sw_gralloc_handle_t* hnd) +{ + if (hnd->pid != getpid()) { + void* base = mmap(0, hnd->size, hnd->prot, MAP_SHARED, hnd->fd, 0); + if (base == MAP_FAILED) { + LOGE("registerBuffer mmap(fd=%d, size=%d, prot=%x) failed (%s)", + hnd->fd, hnd->size, hnd->prot, strerror(-errno)); + return -errno; + } + hnd->base = intptr_t(base); + } + return NO_ERROR; +} + +status_t sw_gralloc_handle_t::unregisterBuffer(sw_gralloc_handle_t* hnd) +{ + if (hnd->pid != getpid()) { + if (hnd->base) { + munmap((void*)hnd->base, hnd->size); + } + hnd->base = 0; + } + return NO_ERROR; +} + +status_t sw_gralloc_handle_t::lock(sw_gralloc_handle_t* hnd, int usage, + int l, int t, int w, int h, void** vaddr) +{ + *vaddr = (void*)hnd->base; + return NO_ERROR; +} + +status_t sw_gralloc_handle_t::unlock(sw_gralloc_handle_t* hnd) +{ + return NO_ERROR; +} + +// --------------------------------------------------------------------------- }; // namespace android |