drm_gralloc: Implement lock_ycbcr method

It is needed for flexible YUV formats. Currently only flexible YUV420 is
supported and always maps to NV12 format.

Change-Id: I4b2f2d1cdd3f2495b63d84438130dc7ab99fbf8c
diff --git a/gralloc.cpp b/gralloc.cpp
index 521d6cb..8162e91 100644
--- a/gralloc.cpp
+++ b/gralloc.cpp
@@ -110,6 +110,46 @@
 	return gralloc_drm_bo_lock(bo, usage, x, y, w, h, ptr);
 }
 
+static int drm_mod_lock_ycbcr(const gralloc_module_t *mod, buffer_handle_t bhandle,
+		int usage, int x, int y, int w, int h, struct android_ycbcr *ycbcr)
+{
+	struct gralloc_drm_handle_t *handle;
+	struct gralloc_drm_bo_t *bo;
+	void *ptr;
+	int err;
+
+	bo = gralloc_drm_bo_from_handle(bhandle);
+	if (!bo)
+		return -EINVAL;
+	handle = bo->handle;
+
+	switch(handle->format) {
+	case HAL_PIXEL_FORMAT_YCbCr_420_888:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	err = gralloc_drm_bo_lock(bo, usage, x, y, w, h, &ptr);
+	if (err)
+		return err;
+
+	switch(handle->format) {
+	case HAL_PIXEL_FORMAT_YCbCr_420_888:
+		ycbcr->y = ptr;
+		ycbcr->cb = (uint8_t *)ptr + handle->stride * handle->height;
+		ycbcr->cr = (uint8_t *)ycbcr->cb + 1;
+		ycbcr->ystride = handle->stride;
+		ycbcr->cstride = handle->stride;
+		ycbcr->chroma_step = 2;
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
 static int drm_mod_unlock(const gralloc_module_t *mod, buffer_handle_t handle)
 {
 	struct drm_module_t *dmod = (struct drm_module_t *) mod;
@@ -231,7 +271,8 @@
 		.unregisterBuffer = drm_mod_unregister_buffer,
 		.lock = drm_mod_lock,
 		.unlock = drm_mod_unlock,
-		.perform = drm_mod_perform
+		.perform = drm_mod_perform,
+		.lock_ycbcr = drm_mod_lock_ycbcr,
 	},
 
 	.mutex = PTHREAD_MUTEX_INITIALIZER,