minigbm: deal with ArcCodec use case by exposing struct map_info
Let's keep a count of how many times a buffer has been locked, since
we have special lock_ycbcr() behavior that returns the offsets and
strides of a YUV buffer when an usage of zero is passed in. This behavior
is used by the ArcCodec. We have to take care not to call drv_bo_unmap
if we didn't map anything.
We also have to expose struct map_info so we can return the address if
we have mapped data, rather than incrementing the drv map count.
Additionally, the gralloc.h says:
"THREADING CONSIDERATIONS
It is legal for several different threads to lock a buffer from
read access, none of the threads are blocked."
This implies recursive locking, which this commit implements.
BUG=b:34419220
TEST=
android.video.cts.VideoEncoderDecoderTest#testAvcGoog0Qual0320x0240
Change-Id: Ibbe7dd5349594117aaaecca9647ad45264448575
Reviewed-on: https://chromium-review.googlesource.com/442835
Commit-Ready: Gurchetan Singh <gurchetansingh@chromium.org>
Tested-by: Gurchetan Singh <gurchetansingh@chromium.org>
Reviewed-by: Stéphane Marchesin <marcheu@chromium.org>
diff --git a/cros_gralloc/cros_gralloc.h b/cros_gralloc/cros_gralloc.h
index 6cd98dd..a24b862 100644
--- a/cros_gralloc/cros_gralloc.h
+++ b/cros_gralloc/cros_gralloc.h
@@ -17,7 +17,8 @@
struct bo *bo;
int32_t refcount;
struct cros_gralloc_handle *hnd;
- void *map_data;
+ struct map_info *map_data;
+ int32_t lockcount;
};
struct handle_info {
diff --git a/cros_gralloc/cros_gralloc_module.cc b/cros_gralloc/cros_gralloc_module.cc
index 470648c..73b258d 100644
--- a/cros_gralloc/cros_gralloc_module.cc
+++ b/cros_gralloc/cros_gralloc_module.cc
@@ -173,9 +173,13 @@
}
if (sw_access() & usage) {
- *vaddr = drv_bo_map(bo->bo, 0, 0, drv_bo_get_width(bo->bo),
- drv_bo_get_height(bo->bo), 0, &bo->map_data,
- 0);
+ if (bo->map_data) {
+ *vaddr = bo->map_data->addr;
+ } else {
+ *vaddr = drv_bo_map(bo->bo, 0, 0, drv_bo_get_width(bo->bo),
+ drv_bo_get_height(bo->bo), 0,
+ &bo->map_data, 0);
+ }
if (*vaddr == MAP_FAILED) {
cros_gralloc_error("Mapping failed.");
@@ -183,6 +187,8 @@
}
}
+ bo->lockcount++;
+
return CROS_GRALLOC_ERROR_NONE;
}
@@ -204,8 +210,10 @@
return CROS_GRALLOC_ERROR_BAD_HANDLE;
}
- if (bo->map_data)
+ if (!--bo->lockcount && bo->map_data) {
drv_bo_unmap(bo->bo, bo->map_data);
+ bo->map_data = NULL;
+ }
return CROS_GRALLOC_ERROR_NONE;
}
@@ -303,9 +311,14 @@
}
if (sw_access() & usage) {
- void *vaddr = drv_bo_map(bo->bo, 0, 0, drv_bo_get_width(bo->bo),
- drv_bo_get_height(bo->bo), 0,
- &bo->map_data, 0);
+ void *vaddr;
+ if (bo->map_data) {
+ vaddr = bo->map_data->addr;
+ } else {
+ vaddr = drv_bo_map(bo->bo, 0, 0, drv_bo_get_width(bo->bo),
+ drv_bo_get_height(bo->bo), 0,
+ &bo->map_data, 0);
+ }
if (vaddr == MAP_FAILED) {
cros_gralloc_error("Mapping failed.");
@@ -347,6 +360,8 @@
return CROS_GRALLOC_ERROR_UNSUPPORTED;
}
+ bo->lockcount++;
+
return CROS_GRALLOC_ERROR_NONE;
}
diff --git a/drv.c b/drv.c
index 4d6d981..64b7f71 100644
--- a/drv.c
+++ b/drv.c
@@ -352,7 +352,8 @@
}
void *drv_bo_map(struct bo *bo, uint32_t x, uint32_t y, uint32_t width,
- uint32_t height, uint32_t flags, void **map_data, size_t plane)
+ uint32_t height, uint32_t flags, struct map_info **map_data,
+ size_t plane)
{
void *ptr;
uint8_t *addr;
@@ -388,7 +389,7 @@
(void *) data);
success:
- *map_data = (void *) data;
+ *map_data = data;
offset = drv_bo_get_plane_stride(bo, plane) * y;
offset += drv_stride_from_format(bo->format, x, plane);
addr = (uint8_t *) data->addr;
@@ -398,9 +399,8 @@
return (void *) addr;
}
-int drv_bo_unmap(struct bo *bo, void *map_data)
+int drv_bo_unmap(struct bo *bo, struct map_info *data)
{
- struct map_info *data = map_data;
int ret = 0;
assert(data);
diff --git a/drv.h b/drv.h
index f1a15e0..62fc0d2 100644
--- a/drv.h
+++ b/drv.h
@@ -74,6 +74,14 @@
uint32_t format;
};
+struct map_info {
+ void *addr;
+ size_t length;
+ uint32_t handle;
+ int32_t refcount;
+ void *priv;
+};
+
struct driver *
drv_create(int fd);
@@ -111,10 +119,11 @@
void *
drv_bo_map(struct bo *bo, uint32_t x, uint32_t y, uint32_t width,
- uint32_t height, uint32_t flags, void **map_data, size_t plane);
+ uint32_t height, uint32_t flags, struct map_info **map_data,
+ size_t plane);
int
-drv_bo_unmap(struct bo *bo, void *map_data);
+drv_bo_unmap(struct bo *bo, struct map_info *map_data);
uint32_t
drv_bo_get_width(struct bo *bo);
diff --git a/drv_priv.h b/drv_priv.h
index 3e72706..d37532a 100644
--- a/drv_priv.h
+++ b/drv_priv.h
@@ -40,14 +40,6 @@
pthread_mutex_t driver_lock;
};
-struct map_info {
- void *addr;
- size_t length;
- uint32_t handle;
- int32_t refcount;
- void *priv;
-};
-
struct kms_item {
uint32_t format;
uint64_t modifier;
diff --git a/gbm.c b/gbm.c
index 89726dd..fb50286 100644
--- a/gbm.c
+++ b/gbm.c
@@ -255,7 +255,8 @@
return NULL;
*stride = gbm_bo_get_plane_stride(bo, plane);
- return drv_bo_map(bo->bo, x, y, width, height, 0, map_data, plane);
+ return drv_bo_map(bo->bo, x, y, width, height, 0,
+ (struct map_info**)map_data, plane);
}
PUBLIC void