gralloc_gbm: add .lock_ycbcr to support video use case

cherry-picked from https://android-review.googlesource.com/c/1345437

The .lock_ycbcr function hook is currently missing from gralloc driver,
and that stops video playback from working.  Add a .lock_ycbcr function
implementation to get SW video playback test start working, where
HAL_PIXEL_FORMAT_YV12 format is used/tested.

Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
Change-Id: I847db96bc3a08ad746560881d31cf296a5943cbf
diff --git a/gralloc/gralloc.cpp b/gralloc/gralloc.cpp
index 2753ee9..c71e901 100644
--- a/gralloc/gralloc.cpp
+++ b/gralloc/gralloc.cpp
@@ -150,6 +150,19 @@
 	return err;
 }
 
+static int gbm_mod_lock_ycbcr(gralloc_module_t const *mod, buffer_handle_t handle,
+		int usage, int x, int y, int w, int h, struct android_ycbcr *ycbcr)
+{
+	struct gbm_module_t *dmod = (struct gbm_module_t *) mod;
+	int err;
+
+	pthread_mutex_lock(&dmod->mutex);
+	err = gralloc_gbm_bo_lock_ycbcr(handle, usage, x, y, w, h, ycbcr);
+	pthread_mutex_unlock(&dmod->mutex);
+
+	return err;
+}
+
 static int gbm_mod_close_gpu0(struct hw_device_t *dev)
 {
 	struct gbm_module_t *dmod = (struct gbm_module_t *)dev->module;
@@ -251,6 +264,7 @@
 		.unregisterBuffer = gbm_mod_unregister_buffer,
 		.lock = gbm_mod_lock,
 		.unlock = gbm_mod_unlock,
+		.lock_ycbcr = gbm_mod_lock_ycbcr,
 		.perform = gbm_mod_perform
 	},
 
diff --git a/gralloc/gralloc_gbm.cpp b/gralloc/gralloc_gbm.cpp
index 43907e5..bdb41b8 100644
--- a/gralloc/gralloc_gbm.cpp
+++ b/gralloc/gralloc_gbm.cpp
@@ -482,3 +482,50 @@
 
 	return 0;
 }
+
+#define GRALLOC_ALIGN(value, base) (((value) + ((base)-1)) & ~((base)-1))
+
+int gralloc_gbm_bo_lock_ycbcr(buffer_handle_t handle,
+		int usage, int x, int y, int w, int h,
+		struct android_ycbcr *ycbcr)
+{
+	struct gralloc_handle_t *hnd = gralloc_handle(handle);
+	int ystride, cstride;
+	void *addr;
+	int err;
+
+	ALOGD("handle %p, hnd %p, usage 0x%x", handle, hnd, usage);
+
+	err = gralloc_gbm_bo_lock(handle, usage, x, y, w, h, &addr);
+	if (err)
+		return err;
+
+	memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
+
+	switch (hnd->format) {
+	case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+		ystride = cstride = GRALLOC_ALIGN(hnd->width, 16);
+		ycbcr->y = addr;
+		ycbcr->cr = (unsigned char *)addr + ystride * hnd->height;
+		ycbcr->cb = (unsigned char *)addr + ystride * hnd->height + 1;
+		ycbcr->ystride = ystride;
+		ycbcr->cstride = cstride;
+		ycbcr->chroma_step = 2;
+		break;
+	case HAL_PIXEL_FORMAT_YV12:
+		ystride = hnd->width;
+		cstride = GRALLOC_ALIGN(ystride / 2, 16);
+		ycbcr->y = addr;
+		ycbcr->cr = (unsigned char *)addr + ystride * hnd->height;
+		ycbcr->cb = (unsigned char *)addr + ystride * hnd->height + cstride * hnd->height / 2;
+		ycbcr->ystride = ystride;
+		ycbcr->cstride = cstride;
+		ycbcr->chroma_step = 1;
+		break;
+	default:
+		ALOGE("Can not lock buffer, invalid format: 0x%x", hnd->format);
+		return -EINVAL;
+	}
+
+	return 0;
+}
diff --git a/gralloc/gralloc_gbm_priv.h b/gralloc/gralloc_gbm_priv.h
index d0326c5..cbe9256 100644
--- a/gralloc/gralloc_gbm_priv.h
+++ b/gralloc/gralloc_gbm_priv.h
@@ -45,6 +45,8 @@
 
 int gralloc_gbm_bo_lock(buffer_handle_t handle, int usage, int x, int y, int w, int h, void **addr);
 int gralloc_gbm_bo_unlock(buffer_handle_t handle);
+int gralloc_gbm_bo_lock_ycbcr(buffer_handle_t handle, int usage,
+		int x, int y, int w, int h, struct android_ycbcr *ycbcr);
 
 struct gbm_device *gbm_dev_create(void);
 void gbm_dev_destroy(struct gbm_device *gbm);