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