diff options
-rw-r--r-- | gralloc.c | 4 | ||||
-rw-r--r-- | gralloc_drm.c | 53 | ||||
-rw-r--r-- | gralloc_drm.h | 4 | ||||
-rw-r--r-- | gralloc_drm_priv.h | 3 |
4 files changed, 51 insertions, 13 deletions
@@ -149,7 +149,7 @@ static int drm_mod_lock(const gralloc_module_t *mod, buffer_handle_t handle, if (!bo) return -EINVAL; - return gralloc_drm_bo_map(bo, x, y, w, h, 1, ptr); + return gralloc_drm_bo_lock(bo, usage, x, y, w, h, ptr); } static int drm_mod_unlock(const gralloc_module_t *mod, buffer_handle_t handle) @@ -161,7 +161,7 @@ static int drm_mod_unlock(const gralloc_module_t *mod, buffer_handle_t handle) if (!bo) return -EINVAL; - gralloc_drm_bo_unmap(bo); + gralloc_drm_bo_unlock(bo); return 0; } diff --git a/gralloc_drm.c b/gralloc_drm.c index e220ebe..2ec11ef 100644 --- a/gralloc_drm.c +++ b/gralloc_drm.c @@ -294,22 +294,57 @@ void gralloc_drm_bo_unregister(struct gralloc_drm_bo_t *bo) } /* - * Map a bo for CPU access. + * Lock a bo. XXX thread-safety? */ -int gralloc_drm_bo_map(struct gralloc_drm_bo_t *bo, - int x, int y, int w, int h, - int enable_write, void **addr) +int gralloc_drm_bo_lock(struct gralloc_drm_bo_t *bo, + int usage, int x, int y, int w, int h, + void **addr) { - return bo->drm->drv->map(bo->drm->drv, bo, - x, y, w, h, enable_write, addr); + if ((bo->handle->usage & usage) != usage) + return -EINVAL; + + /* allow multiple locks with compatible usages */ + if (bo->lock_count && (bo->locked_for & usage) != usage) + return -EINVAL; + + usage |= bo->locked_for; + + if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | + GRALLOC_USAGE_SW_READ_MASK)) { + /* the driver is supposed to wait for the bo */ + int write = !!(usage & GRALLOC_USAGE_SW_WRITE_MASK); + int err = bo->drm->drv->map(bo->drm->drv, bo, + x, y, w, h, write, addr); + if (err) + return err; + } + else { + /* kernel handles the synchronization here */ + } + + bo->lock_count++; + bo->locked_for |= usage; + + return 0; } /* - * Unmap a bo. + * Unlock a bo. */ -void gralloc_drm_bo_unmap(struct gralloc_drm_bo_t *bo) +void gralloc_drm_bo_unlock(struct gralloc_drm_bo_t *bo) { - bo->drm->drv->unmap(bo->drm->drv, bo); + int mapped = bo->locked_for & + (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_SW_READ_MASK); + + if (!bo->lock_count) + return; + + if (mapped) + bo->drm->drv->unmap(bo->drm->drv, bo); + + bo->lock_count--; + if (!bo->lock_count) + bo->locked_for = 0; } /* diff --git a/gralloc_drm.h b/gralloc_drm.h index 3907dfd..794abf3 100644 --- a/gralloc_drm.h +++ b/gralloc_drm.h @@ -79,8 +79,8 @@ static inline struct gralloc_drm_bo_t *gralloc_drm_bo_validate(struct gralloc_dr return gralloc_drm_bo_register(drm, handle, 0); } -int gralloc_drm_bo_map(struct gralloc_drm_bo_t *bo, int x, int y, int w, int h, int enable_write, void **addr); -void gralloc_drm_bo_unmap(struct gralloc_drm_bo_t *bo); +int gralloc_drm_bo_lock(struct gralloc_drm_bo_t *bo, int x, int y, int w, int h, int enable_write, void **addr); +void gralloc_drm_bo_unlock(struct gralloc_drm_bo_t *bo); buffer_handle_t gralloc_drm_bo_get_handle(struct gralloc_drm_bo_t *bo, int *stride); int gralloc_drm_bo_need_fb(const struct gralloc_drm_bo_t *bo); diff --git a/gralloc_drm_priv.h b/gralloc_drm_priv.h index 0838db7..ada152d 100644 --- a/gralloc_drm_priv.h +++ b/gralloc_drm_priv.h @@ -107,6 +107,9 @@ struct gralloc_drm_bo_t { int imported; /* the handle is from a remote proces when true */ int fb_handle; /* the GEM handle of the bo */ int fb_id; /* the fb id */ + + int lock_count; + int locked_for; }; struct gralloc_drm_drv_t *gralloc_drm_drv_create_for_pipe(int fd, const char *name); |