summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/hardware/gralloc.h62
-rw-r--r--modules/gralloc/framebuffer.cpp25
-rw-r--r--modules/gralloc/gralloc.cpp52
-rw-r--r--modules/gralloc/gralloc_priv.h16
-rw-r--r--modules/gralloc/mapper.cpp122
5 files changed, 190 insertions, 87 deletions
diff --git a/include/hardware/gralloc.h b/include/hardware/gralloc.h
index c473de0..c1724cc 100644
--- a/include/hardware/gralloc.h
+++ b/include/hardware/gralloc.h
@@ -42,7 +42,7 @@ __BEGIN_DECLS
enum {
/* buffer is never read in software */
- GRALLOC_USAGE_SW_READ_NEVER = 0x00000001,
+ GRALLOC_USAGE_SW_READ_NEVER = 0x00000000,
/* buffer is rarely read in software */
GRALLOC_USAGE_SW_READ_RARELY = 0x00000002,
/* buffer is often read in software */
@@ -51,7 +51,7 @@ enum {
GRALLOC_USAGE_SW_READ_MASK = 0x0000000F,
/* buffer is never written in software */
- GRALLOC_USAGE_SW_WRITE_NEVER = 0x00000010,
+ GRALLOC_USAGE_SW_WRITE_NEVER = 0x00000000,
/* buffer is never written in software */
GRALLOC_USAGE_SW_WRITE_RARELY = 0x00000020,
/* buffer is never written in software */
@@ -89,47 +89,63 @@ typedef const native_handle* buffer_handle_t;
struct gralloc_module_t {
struct hw_module_t common;
- /*
- * The (*map)() method maps the buffer in the caller's address space
- * if this operation is allowed (see below).
- * Mapped buffers are reference-counted in a given process, that is,
- * if a the buffer is already mapped, this function must return the
- * same address and the internal reference counter is incremented.
+
+ /*
+ * (*registerBuffer)() must be called before a buffer_handle_t that has not
+ * been created with (*alloc_device_t::alloc)() can be used.
+ *
+ * This is intended to be used with buffer_handle_t's that have been
+ * received in this process through IPC.
*
- * Returns 0 on success or -errno on error.
+ * This function checks that the handle is indeed a valid one and prepares
+ * it for use with (*lock)() and (*unlock)().
+ *
+ * It is not necessary to call (*registerBuffer)() on a handle created
+ * with (*alloc_device_t::alloc)().
+ *
+ * returns an error if this buffer_handle_t is not valid.
*/
-
- int (*map)(struct gralloc_module_t const* module,
- buffer_handle_t handle, void** vaddr);
+ int (*registerBuffer)(struct gralloc_module_t const* module,
+ buffer_handle_t handle);
/*
- * The (*unmap)() method, unmaps the buffer from the caller's address
- * space, if the buffer has been mapped more than once,
- * the (*unmap)() needs to be called the same number of time before
- * the buffer is actually unmapped.
+ * (*unregisterBuffer)() is called once this handle is no longer needed in
+ * this process. After this call, it is an error to call (*lock)(),
+ * (*unlock)(), or (*registerBuffer)().
*
- * Returns 0 on success or -errno on error.
+ * This function doesn't close or free the handle itself; this is done
+ * by other means, usually through libcutils's native_handle_close() and
+ * native_handle_free().
+ *
+ * It is an error to call (*unregisterBuffer)() on a buffer that wasn't
+ * explicitly registered first.
*/
-
- int (*unmap)(struct gralloc_module_t const* module, buffer_handle_t handle);
-
+ int (*unregisterBuffer)(struct gralloc_module_t const* module,
+ buffer_handle_t handle);
/*
* The (*lock)() method is called before a buffer is accessed for the
* specified usage. This call may block, for instance if the h/w needs
* to finish rendering or if CPU caches need to be synchronized.
*
- * The caller promises to modify ALL PIXELS and ONLY THE PIXELS in the area
- * specified by (l,t,w,h).
+ * The caller promises to modify only pixels in the area specified
+ * by (l,t,w,h).
*
* The content of the buffer outside of the specified area is NOT modified
* by this call.
+ *
+ * If usage specifies GRALLOC_USAGE_SW_*, vaddr is filled with the address
+ * of the buffer in virtual memory.
+ *
+ * If the buffer was created with a usage mask incompatible with the
+ * requested usage flags here, -EINVAL is returned.
*
*/
int (*lock)(struct gralloc_module_t const* module,
buffer_handle_t handle, int usage,
- int l, int t, int w, int h);
+ int l, int t, int w, int h,
+ void** vaddr);
/*
diff --git a/modules/gralloc/framebuffer.cpp b/modules/gralloc/framebuffer.cpp
index 05b9418..31adfca 100644
--- a/modules/gralloc/framebuffer.cpp
+++ b/modules/gralloc/framebuffer.cpp
@@ -97,7 +97,7 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
m->base.lock(&m->base, buffer,
private_module_t::PRIV_USAGE_LOCKED_FOR_POST,
- 0, 0, m->info.xres, m->info.yres);
+ 0, 0, m->info.xres, m->info.yres, NULL);
const size_t offset = hnd->base - m->framebuffer->base;
m->info.activate = FB_ACTIVATE_VBL;
@@ -113,14 +113,23 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
// If we can't do the page_flip, just copy the buffer to the front
// FIXME: use copybit HAL instead of memcpy
- m->base.lock(&m->base, buffer,
- private_module_t::PRIV_USAGE_LOCKED_FOR_POST,
- 0, 0, m->info.xres, m->info.yres);
+ void* fb_vaddr;
+ void* buffer_vaddr;
- memcpy((void*)m->framebuffer->base, (void*)hnd->base,
- m->finfo.line_length * m->info.yres);
+ 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,
+ 0, 0, m->info.xres, m->info.yres,
+ &buffer_vaddr);
+
+ memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres);
m->base.unlock(&m->base, buffer);
+ m->base.unlock(&m->base, m->framebuffer);
}
return 0;
@@ -283,9 +292,9 @@ int mapFrameBufferLocked(struct private_module_t* module)
module->numBuffers = info.yres_virtual / info.yres;
module->bufferMask = 0;
-
+
void* vaddr;
- module->base.map(&module->base, module->framebuffer, &vaddr);
+ gralloc_map(&module->base, module->framebuffer, &vaddr);
memset(vaddr, 0, fbSize);
return 0;
diff --git a/modules/gralloc/gralloc.cpp b/modules/gralloc/gralloc.cpp
index abb8c96..5a38b33 100644
--- a/modules/gralloc/gralloc.cpp
+++ b/modules/gralloc/gralloc.cpp
@@ -53,19 +53,20 @@ int fb_device_open(const hw_module_t* module, const char* name,
static int gralloc_device_open(const hw_module_t* module, const char* name,
hw_device_t** device);
-extern int gralloc_map(gralloc_module_t const* module,
- buffer_handle_t handle, void** vaddr);
-
-extern int gralloc_unmap(gralloc_module_t const* module,
- buffer_handle_t handle);
-
extern int gralloc_lock(gralloc_module_t const* module,
buffer_handle_t handle, int usage,
- int l, int t, int w, int h);
+ 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);
+
/*****************************************************************************/
static struct hw_module_methods_t gralloc_module_methods = {
@@ -83,8 +84,8 @@ struct private_module_t HAL_MODULE_INFO_SYM = {
author: "The Android Open Source Project",
methods: &gralloc_module_methods
},
- map: gralloc_map,
- unmap: gralloc_unmap,
+ registerBuffer: gralloc_register_buffer,
+ unregisterBuffer: gralloc_unregister_buffer,
lock: gralloc_lock,
unlock: gralloc_unlock,
},
@@ -98,12 +99,6 @@ struct private_module_t HAL_MODULE_INFO_SYM = {
/*****************************************************************************/
-/*
- * This function creates a buffer_handle_t initialized with the given fd.
- * the offset passed in parameter is used to mmap() this fd later at this
- * offset.
- */
-
static int gralloc_alloc_framebuffer_locked(alloc_device_t* dev,
size_t size, int usage, buffer_handle_t* pHandle)
{
@@ -112,18 +107,14 @@ static int gralloc_alloc_framebuffer_locked(alloc_device_t* dev,
// allocate the framebuffer
if (m->framebuffer == NULL) {
- // initialize the framebuffer
+ // initialize the framebuffer, the framebuffer is mapped once
+ // and forever.
int err = mapFrameBufferLocked(m);
if (err < 0) {
return err;
}
}
- if (m->framebuffer->base == 0) {
- void *vaddr;
- m->base.map(&m->base, m->framebuffer, &vaddr);
- }
-
const uint32_t bufferMask = m->bufferMask;
const uint32_t numBuffers = m->numBuffers;
const size_t bufferSize = m->finfo.line_length * m->info.yres;
@@ -258,11 +249,10 @@ static int gralloc_free(alloc_device_t* dev,
int index = (hnd->base - m->framebuffer->base) / bufferSize;
m->bufferMask &= ~(1<<index);
}
-
- if (hnd->base) {
- LOGW("handle %p still mapped at %p", hnd, hnd->base);
- //gralloc_unmap((gralloc_module_t*) dev->common.module, handle);
- }
+
+ gralloc_module_t* m = reinterpret_cast<gralloc_module_t*>(
+ dev->common.module);
+ gralloc_unregister_buffer(m, handle);
close(hnd->fd);
delete hnd;
@@ -276,16 +266,8 @@ static int gralloc_close(struct hw_device_t *dev)
gralloc_context_t* ctx = reinterpret_cast<gralloc_context_t*>(dev);
if (ctx) {
/* TODO: keep a list of all buffer_handle_t created, and free them
- * all here
+ * all here.
*/
-
- private_module_t* m = reinterpret_cast<private_module_t*>(dev->module);
- pthread_mutex_lock(&m->lock);
- if (m->framebuffer) {
- m->base.unmap(&m->base, m->framebuffer);
- }
- pthread_mutex_unlock(&m->lock);
-
free(ctx);
}
return 0;
diff --git a/modules/gralloc/gralloc_priv.h b/modules/gralloc/gralloc_priv.h
index a6fa69a..b0f2c6c 100644
--- a/modules/gralloc/gralloc_priv.h
+++ b/modules/gralloc/gralloc_priv.h
@@ -36,6 +36,13 @@ inline size_t roundUpToPageSize(size_t x) {
return (x + (PAGESIZE-1)) & ~(PAGESIZE-1);
}
+int gralloc_map(gralloc_module_t const* module,
+ buffer_handle_t handle, void** vaddr);
+
+int gralloc_unmap(gralloc_module_t const* module,
+ buffer_handle_t handle);
+
+
int mapFrameBufferLocked(struct private_module_t* module);
/*****************************************************************************/
@@ -58,6 +65,7 @@ struct private_module_t {
float fps;
enum {
+ // flag to indicate we'll post this buffer
PRIV_USAGE_LOCKED_FOR_POST = 0x80000000
};
};
@@ -68,16 +76,18 @@ struct private_handle_t : public native_handle
{
enum {
PRIV_FLAGS_FRAMEBUFFER = 0x00000001,
- PRIV_FLAGS_USES_PMEM = 0x00000002
+ PRIV_FLAGS_USES_PMEM = 0x00000002,
+ PRIV_FLAGS_MAPPED = 0x00000004, // FIXME: should be out-of-line
+ PRIV_FLAGS_LOCKED = 0x00000008 // FIXME: should be out-of-line
};
int fd;
int magic;
- int base;
+ int base; // FIXME: should be out-of-line (meaningless with ipc)
int flags;
int size;
- static const int sNumInts = 5;
+ static const int sNumInts = 4;
static const int sNumFds = 1;
static const int sMagic = 0x3141592;
diff --git a/modules/gralloc/mapper.cpp b/modules/gralloc/mapper.cpp
index a5f52ed..94be43b 100644
--- a/modules/gralloc/mapper.cpp
+++ b/modules/gralloc/mapper.cpp
@@ -38,14 +38,9 @@ struct mapped_buffer_t {
int base;
int refCount;
- int init(private_handle_t* hnd) {
- size = hnd->size;
- base = 0;
- refCount = 0;
- struct stat buf;
- int result = 0;
- key = intptr_t(hnd);
- return result;
+ mapped_buffer_t() { /* no init */ };
+ mapped_buffer_t(private_handle_t* hnd)
+ : key(intptr_t(hnd)), size(hnd->size), base(0), refCount(0) {
}
};
@@ -68,12 +63,9 @@ struct mapped_buffers_t {
void** vaddr)
{
private_handle_t* hnd = (private_handle_t*)(handle);
- mapped_buffer_t key;
- int result = key.init(hnd);
+ mapped_buffer_t key(hnd);
//printRecord(ANDROID_LOG_DEBUG, "map", &key);
- if (result) {
- return result;
- }
+ int result = 0;
mapped_buffer_t* record = 0;
pthread_mutex_lock(&mutex);
// From here to the end of the function we return by jumping to "exit"
@@ -116,11 +108,9 @@ struct mapped_buffers_t {
int unmap(gralloc_module_t const* module,
buffer_handle_t handle)
{
- mapped_buffer_t key;
- key.init((private_handle_t*) handle);
+ mapped_buffer_t key((private_handle_t*) handle);
//printRecord(ANDROID_LOG_DEBUG, "unmap", &key);
int index = -1;
-
int result = 0;
mapped_buffer_t* record = 0;
pthread_mutex_lock(&mutex);
@@ -214,18 +204,114 @@ int gralloc_unmap(gralloc_module_t const* module,
return sMappedBuffers.unmap(module, handle);
}
+int gralloc_register_buffer(gralloc_module_t const* module,
+ buffer_handle_t handle)
+{
+ if (private_handle_t::validate(handle) < 0)
+ return -EINVAL;
+
+ // In this implementation, we don't need to do anything here
+
+ /* FIXME: 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
+ */
+ private_handle_t* hnd = (private_handle_t*)(handle);
+ hnd->base = 0;
+ hnd->flags &= ~(private_handle_t::PRIV_FLAGS_LOCKED |
+ private_handle_t::PRIV_FLAGS_MAPPED);
+
+ return 0;
+}
+
+int gralloc_unregister_buffer(gralloc_module_t const* module,
+ buffer_handle_t handle)
+{
+ if (private_handle_t::validate(handle) < 0)
+ return -EINVAL;
+
+ /*
+ * If the buffer has been mapped during a lock operation, it's time
+ * to unmap 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->flags & private_handle_t::PRIV_FLAGS_LOCKED,
+ "handle %p still locked", hnd);
+
+ if (hnd->flags & private_handle_t::PRIV_FLAGS_MAPPED) {
+ if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
+ gralloc_unmap(module, handle);
+ LOGE_IF(hnd->base,
+ "handle %p still mapped at %p",
+ hnd, (void*)hnd->base);
+ }
+ }
+
+ return 0;
+}
int gralloc_lock(gralloc_module_t const* module,
buffer_handle_t handle, int usage,
- int l, int t, int w, int h)
+ int l, int t, int w, int h,
+ void** vaddr)
{
// FIXME: gralloc_lock() needs implementation
- return 0;
+
+ if (private_handle_t::validate(handle) < 0)
+ return -EINVAL;
+
+ int err = 0;
+ private_handle_t* hnd = (private_handle_t*)(handle);
+
+ // already locked
+ if (hnd->flags & private_handle_t::PRIV_FLAGS_LOCKED) {
+ LOGE("handle %p already locked", handle);
+ return -EBUSY;
+ }
+
+ uint32_t mask = GRALLOC_USAGE_SW_READ_MASK |
+ GRALLOC_USAGE_SW_WRITE_MASK;
+ if ((usage & mask) && vaddr){
+ if (hnd->flags & private_handle_t::PRIV_FLAGS_MAPPED) {
+ *vaddr = (void*)hnd->base;
+ } else {
+ hnd->flags |= private_handle_t::PRIV_FLAGS_MAPPED;
+ err = gralloc_map(module, handle, vaddr);
+ }
+ }
+
+ hnd->flags |= private_handle_t::PRIV_FLAGS_LOCKED;
+ return err;
}
int gralloc_unlock(gralloc_module_t const* module,
buffer_handle_t handle)
{
// FIXME: gralloc_unlock() needs implementation
+ if (private_handle_t::validate(handle) < 0)
+ return -EINVAL;
+
+ private_handle_t* hnd = (private_handle_t*)(handle);
+
+ // not locked
+ if (!(hnd->flags & private_handle_t::PRIV_FLAGS_LOCKED)) {
+ LOGE("handle %p is not locked", handle);
+ return -EINVAL;
+ }
+
+ /* FOR DEBUGGING
+ if (hnd->flags & private_handle_t::PRIV_FLAGS_MAPPED) {
+ if (gralloc_unmap(module, handle) == 0) {
+ hnd->flags &= ~private_handle_t::PRIV_FLAGS_MAPPED;
+ }
+ }
+ */
+
+ hnd->flags &= ~private_handle_t::PRIV_FLAGS_LOCKED;
return 0;
}