From 5c73d6a5f1e4fd58eef2135e7d928be1155a625c Mon Sep 17 00:00:00 2001
From: Devarsh Thakkar <devarsht@xilinx.com>
Date: Thu, 5 Jan 2017 01:42:32 -0800
Subject: [PATCH 8/9] kmssink : Allocate dumb buffers with bpp as per video
 format

- The kmssink uses libkms API kms_bo_create to create
  buffer object. Now since kms_bo_create uses hardcoded bits-per-pixel
  value set to 32, overallocation is happening and wrong bpp are getting
  passed to xilinx dpdma driver, due to which xilinx dpdma driver is
  returning incorrect pitch value.

- Fix this by calculating bpp as per the video format and use drm IOCTL
  directly instead of using libkms API.

Reference :
https://lists.freedesktop.org/archives/dri-devel/2014-December/073686.html

Signed-off-by: Devarsh Thakkar <devarsht@xilinx.com>
Upstream Status: Backport
---
 sys/kms/gstkmsallocator.c | 109 +++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 94 insertions(+), 15 deletions(-)

diff --git a/sys/kms/gstkmsallocator.c b/sys/kms/gstkmsallocator.c
index d368397..6ddf357 100644
--- a/sys/kms/gstkmsallocator.c
+++ b/sys/kms/gstkmsallocator.c
@@ -46,6 +46,23 @@ struct _GstKMSAllocatorPrivate
   struct kms_driver *driver;
 };
 
+struct kms_bo
+{
+	struct kms_driver *kms;
+	void *ptr;
+	size_t size;
+	size_t offset;
+	size_t pitch;
+	unsigned handle;
+};
+
+
+struct dumb_bo
+{
+	struct kms_bo base;
+	unsigned map_count;
+};
+
 #define parent_class gst_kms_allocator_parent_class
 G_DEFINE_TYPE_WITH_CODE (GstKMSAllocator, gst_kms_allocator, GST_TYPE_ALLOCATOR,
     G_ADD_PRIVATE (GstKMSAllocator);
@@ -120,17 +137,9 @@ static gboolean
 gst_kms_allocator_memory_create (GstKMSAllocator * allocator,
     GstKMSMemory * kmsmem, GstVideoInfo * vinfo)
 {
-  gint ret;
-  guint attrs[] = {
-    KMS_WIDTH, GST_VIDEO_INFO_WIDTH (vinfo),
-    KMS_HEIGHT, GST_VIDEO_INFO_HEIGHT (vinfo),
-    KMS_TERMINATE_PROP_LIST,
-  };
-  guint i, virt_height = 0;
-
-  for (i = 0; i < vinfo->finfo->n_planes; i++)
-    virt_height += GST_VIDEO_INFO_HEIGHT (vinfo) >> vinfo->finfo->h_sub[i];
-  attrs[3] = virt_height;
+  gint ret, bpp, virtual_height;
+  struct drm_mode_create_dumb arg;
+  struct dumb_bo *bo;
 
   if (kmsmem->bo)
     return TRUE;
@@ -138,13 +147,83 @@ gst_kms_allocator_memory_create (GstKMSAllocator * allocator,
   if (!ensure_kms_driver (allocator))
     return FALSE;
 
-  ret = kms_bo_create (allocator->priv->driver, attrs, &kmsmem->bo);
+  switch (GST_VIDEO_INFO_FORMAT (vinfo)) {
+	  case GST_VIDEO_FORMAT_NV12:
+	  case GST_VIDEO_FORMAT_NV21:
+	  case GST_VIDEO_FORMAT_NV16:
+	  case GST_VIDEO_FORMAT_NV61:
+	  case GST_VIDEO_FORMAT_I420:
+	  case GST_VIDEO_FORMAT_YV12:
+		  bpp = 8;
+		  break;
+
+	  case GST_VIDEO_FORMAT_UYVY:
+	  case GST_VIDEO_FORMAT_YVYU:
+	  case GST_VIDEO_FORMAT_YUY2:
+		  bpp = 16;
+		  break;
+
+	  case GST_VIDEO_FORMAT_BGR:
+	  case GST_VIDEO_FORMAT_RGB:
+		  bpp = 24;
+		  break;
+
+	  case GST_VIDEO_FORMAT_ARGB:
+	  case GST_VIDEO_FORMAT_xRGB:
+	  case GST_VIDEO_FORMAT_ABGR:
+	  case GST_VIDEO_FORMAT_xBGR:
+	  case GST_VIDEO_FORMAT_RGBA:
+	  case GST_VIDEO_FORMAT_RGBx:
+	  case GST_VIDEO_FORMAT_BGRA:
+	  case GST_VIDEO_FORMAT_BGRx:
+		  bpp = 32;
+		  break;
+
+	  default:
+		  GST_ERROR_OBJECT (allocator, "Unsupported format 0x%08x\n", GST_VIDEO_INFO_FORMAT (vinfo));
+
+		  return NULL;
+  }
+
+  switch (GST_VIDEO_INFO_FORMAT (vinfo)) {
+	  case GST_VIDEO_FORMAT_NV12:
+	  case GST_VIDEO_FORMAT_NV21:
+		  virtual_height = GST_VIDEO_INFO_HEIGHT (vinfo) * 3 / 2;
+		  break;
+
+	  case GST_VIDEO_FORMAT_NV16:
+	  case GST_VIDEO_FORMAT_NV61:
+		  virtual_height = GST_VIDEO_INFO_HEIGHT (vinfo) * 2;
+		  break;
+
+	  default:
+		  virtual_height = GST_VIDEO_INFO_HEIGHT (vinfo);
+		  break;
+  }
+
+  bo = calloc(1, sizeof(*bo));
+  if (!bo)
+	  return -ENOMEM;
+
+  memset(&arg, 0, sizeof(arg));
+  arg.bpp = bpp;
+  arg.width = GST_VIDEO_INFO_WIDTH (vinfo);
+  arg.height = virtual_height;
+
+  ret = drmIoctl(allocator->priv->fd, DRM_IOCTL_MODE_CREATE_DUMB, &arg);
   if (ret) {
-    GST_ERROR_OBJECT (allocator, "Failed to create buffer object: %s (%d)",
-        strerror (-ret), ret);
-    return FALSE;
+	  GST_ERROR_OBJECT (allocator, "Failed to create buffer object: %s (%d)",
+			  strerror (-ret), ret);
+	  return FALSE;
   }
 
+  bo->base.kms = allocator->priv->driver;
+  bo->base.handle = arg.handle;
+  bo->base.size = arg.size;
+  bo->base.pitch = arg.pitch;
+
+  kmsmem->bo = &bo->base;
+
   return TRUE;
 }
 
-- 
2.7.4

