drm_gralloc: fix random crash with wildpointer
am: 99e2a21625

Change-Id: I26067bf3de95c6d5b23549b53fdcd1417654aaf4
diff --git a/gralloc.cpp b/gralloc.cpp
index 521d6cb..421aeb5 100644
--- a/gralloc.cpp
+++ b/gralloc.cpp
@@ -62,7 +62,7 @@
 
 	va_start(args, op);
 	switch (op) {
-	case GRALLOC_MODULE_PERFORM_GET_DRM_FD:
+	case static_cast<int>(GRALLOC_MODULE_PERFORM_GET_DRM_FD):
 		{
 			int *fd = va_arg(args, int *);
 			*fd = gralloc_drm_get_fd(dmod->drm);
@@ -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,
diff --git a/gralloc_drm.h b/gralloc_drm.h
index 3ad818f..f92ba5e 100644
--- a/gralloc_drm.h
+++ b/gralloc_drm.h
@@ -66,6 +66,7 @@
 	case HAL_PIXEL_FORMAT_YV12:
 	case HAL_PIXEL_FORMAT_YCbCr_422_SP:
 	case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+	case HAL_PIXEL_FORMAT_YCbCr_420_888:
 		bpp = 1;
 		break;
 	default:
@@ -91,6 +92,7 @@
 		extra_height_div = 1;
 		break;
 	case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+	case HAL_PIXEL_FORMAT_YCbCr_420_888:
 		align_w = 2;
 		align_h = 2;
 		extra_height_div = 2;
diff --git a/gralloc_drm_rockchip.c b/gralloc_drm_rockchip.c
index b383208..f9dcb0e 100644
--- a/gralloc_drm_rockchip.c
+++ b/gralloc_drm_rockchip.c
@@ -40,7 +40,7 @@
 	struct rockchip_info *info = (struct rockchip_info *)drv;
 	struct rockchip_buffer *buf;
 	struct drm_gem_close args;
-	int ret, cpp, pitch;
+	int ret, cpp, pitch, aligned_width, aligned_height;
 	uint32_t size, gem_handle;
 
 	buf = calloc(1, sizeof(*buf));
@@ -55,12 +55,26 @@
 		return NULL;
 	}
 
+	aligned_width = handle->width;
+	aligned_height = handle->height;
 	gralloc_drm_align_geometry(handle->format,
-			&handle->width, &handle->height);
+			&aligned_width, &aligned_height);
 
 	/* TODO: We need to sort out alignment */
-	pitch = ALIGN(handle->width * cpp, 64);
-	size = handle->height * pitch;
+	pitch = ALIGN(aligned_width * cpp, 64);
+	size = aligned_height * pitch;
+
+	if (handle->format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+		/*
+		 * WAR for H264 decoder requiring additional space
+		 * at the end of destination buffers.
+		 */
+		uint32_t w_mbs, h_mbs;
+
+		w_mbs = ALIGN(handle->width, 16) / 16;
+		h_mbs = ALIGN(handle->height, 16) / 16;
+		size += 64 * w_mbs * h_mbs;
+	}
 
 	if (handle->prime_fd >= 0) {
 		ret = drmPrimeFDToHandle(info->fd, handle->prime_fd,