summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gralloc.c4
-rw-r--r--gralloc_drm.c53
-rw-r--r--gralloc_drm.h4
-rw-r--r--gralloc_drm_priv.h3
4 files changed, 51 insertions, 13 deletions
diff --git a/gralloc.c b/gralloc.c
index fd4f848..e134e81 100644
--- a/gralloc.c
+++ b/gralloc.c
@@ -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);