drm_hwcomposer: platformhisi: Add support for importing DRM_FORMAT_YVU420 buffers

When trying to play fullscreen video, I started seeing import
errors, which were caused by us trying to call drmModeAddFB2()
with fmt DRM_FORMAT_YVU420 but only setting the a single set of
handle/pitch/offset values.

In the kernel, the framebuffer_check() function would then fail
with "no buffer object handle for plane 1" since we only passed
one plane in.

Thus this patch calculates and sets the pitch/offset values for
the separate planes in the single gem_handle buffer.

Many thanks to Stefan Schake and Rob Herring for helping me
understand some of the subtleties of image plans vs display
planes, etc.

Change-Id: I2d9bdfc66c504e6446a4f9c6287ab675201afa30
Signed-off-by: John Stultz <john.stultz@linaro.org>
diff --git a/platformhisi.cpp b/platformhisi.cpp
index f8b4412..d4428d0 100644
--- a/platformhisi.cpp
+++ b/platformhisi.cpp
@@ -31,6 +31,7 @@
 #include <hardware/gralloc.h>
 #include "gralloc_priv.h"
 
+#define MALI_ALIGN(value, base) (((value) + ((base)-1)) & ~((base)-1))
 
 namespace android {
 
@@ -84,17 +85,43 @@
 
   int32_t fmt = ConvertHalFormatToDrm(hnd->req_format);
   if (fmt < 0)
-	return fmt;
+    return fmt;
 
   memset(bo, 0, sizeof(hwc_drm_bo_t));
   bo->width = hnd->width;
   bo->height = hnd->height;
   bo->format = fmt;
   bo->usage = hnd->usage;
+
   bo->pitches[0] = hnd->byte_stride;
   bo->gem_handles[0] = gem_handle;
   bo->offsets[0] = 0;
 
+  switch (fmt) {
+    case DRM_FORMAT_YVU420: {
+      int align = 128;
+      if (hnd->usage &
+          (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK))
+        align = 16;
+      int adjusted_height = MALI_ALIGN(hnd->height, 2);
+      int y_size = adjusted_height * hnd->byte_stride;
+      int vu_stride = MALI_ALIGN(hnd->byte_stride / 2, align);
+      int v_size = vu_stride * (adjusted_height / 2);
+
+      /* V plane*/
+      bo->gem_handles[1] = gem_handle;
+      bo->pitches[1] = vu_stride;
+      bo->offsets[1] = y_size;
+      /* U plane */
+      bo->gem_handles[2] = gem_handle;
+      bo->pitches[2] = vu_stride;
+      bo->offsets[2] = y_size + v_size;
+      break;
+    }
+    default:
+      break;
+  }
+
   ret = drmModeAddFB2(drm_->fd(), bo->width, bo->height, bo->format,
                       bo->gem_handles, bo->pitches, bo->offsets, &bo->fb_id, 0);
   if (ret) {