lock will now return the vaddr of the buffer. map/umap are gone.
- make sure to return an error if a buffer is locked twice or unlocked while not locked. - added registerBuffer() and unregisterBuffer() to the gralloc module so that we can do some cleanup when a buffer is no longer needed. this became necessary after we removed map/unmap so we have a place to unmap buffers without the need of a kernel module. - change the constants for GRALLOC_USAGE_SW_{READ|WRITE}_NEVER to 0, so that NOT specifying them means "NEVER".
This commit is contained in:
parent
ccc13876d8
commit
988b8bd553
5 changed files with 191 additions and 88 deletions
|
@ -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.
|
||||
*
|
||||
* Returns 0 on success or -errno on error.
|
||||
*/
|
||||
|
||||
int (*map)(struct gralloc_module_t const* module,
|
||||
buffer_handle_t handle, void** vaddr);
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* (*registerBuffer)() must be called before a buffer_handle_t that has not
|
||||
* been created with (*alloc_device_t::alloc)() can be used.
|
||||
*
|
||||
* Returns 0 on success or -errno on error.
|
||||
* This is intended to be used with buffer_handle_t's that have been
|
||||
* received in this process through IPC.
|
||||
*
|
||||
* 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 (*registerBuffer)(struct gralloc_module_t const* module,
|
||||
buffer_handle_t handle);
|
||||
|
||||
int (*unmap)(struct gralloc_module_t const* module, buffer_handle_t handle);
|
||||
|
||||
/*
|
||||
* (*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)().
|
||||
*
|
||||
* 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 (*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);
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
|
@ -285,7 +294,7 @@ int mapFrameBufferLocked(struct private_module_t* module)
|
|||
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;
|
||||
|
|
|
@ -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;
|
||||
|
@ -259,10 +250,9 @@ static int gralloc_free(alloc_device_t* dev,
|
|||
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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue