compositor-drm: support get drm fb from dmabuf

directly use gem object to improt dmabuf

Upstream-Status: Inappropriate [i.MX-specific]

Signed-off-by: Haihua Hu <jared.hu@nxp.com>
diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c
index 4db5d9f..c4ad8f7 100644
--- a/libweston/compositor-drm.c
+++ b/libweston/compositor-drm.c
@@ -93,6 +93,8 @@
 #define DRM_MODE_FLAG_PIC_AR_MASK (0xF << DRM_MODE_FLAG_PIC_AR_BITS_POS)
 #endif
 
+#define ALIGNTO(a, b) ((a + (b-1)) & (~(b-1)))
+
 /**
  * Represents the values of an enum-type KMS property
  */
@@ -930,6 +932,7 @@
 	int ret = -EINVAL;
 #ifdef HAVE_DRM_ADDFB2_MODIFIERS
 	uint64_t mods[4] = { };
+	int width, height;
 	size_t i;
 #endif
 
@@ -941,7 +944,14 @@
 #ifdef HAVE_DRM_ADDFB2_MODIFIERS
 		for (i = 0; i < ARRAY_LENGTH(mods) && fb->handles[i]; i++)
 			mods[i] = fb->modifier;
-		ret = drmModeAddFB2WithModifiers(fb->fd, fb->width, fb->height,
+		if (fb->modifier == DRM_FORMAT_MOD_AMPHION_TILED) {
+			width = ALIGNTO (fb->width, 8);
+			height = ALIGNTO (fb->height, 256);
+		} else {
+			width = fb->width;
+			height = fb->height;
+		}
+		ret = drmModeAddFB2WithModifiers(fb->fd, width, height,
 						 fb->format->format,
 						 fb->handles, fb->strides,
 						 fb->offsets, mods, &fb->fb_id,
@@ -1085,6 +1095,7 @@
 		.modifier = dmabuf->attributes.modifier[0],
 	};
 	int i;
+	uint32_t gem_handle[MAX_DMABUF_PLANES] = {0};
 
 	/* XXX: TODO:
 	 *
@@ -1104,6 +1115,55 @@
 
 	fb->refcnt = 1;
 	fb->type = BUFFER_DMABUF;
+	fb->width = dmabuf->attributes.width;
+	fb->height = dmabuf->attributes.height;
+	fb->modifier = dmabuf->attributes.modifier[0];
+	fb->size = 0;
+	fb->fd = backend->drm.fd;
+
+	static_assert(ARRAY_LENGTH(fb->strides) ==
+		      ARRAY_LENGTH(dmabuf->attributes.stride),
+		      "drm_fb and dmabuf stride size must match");
+	static_assert(sizeof(fb->strides) == sizeof(dmabuf->attributes.stride),
+		      "drm_fb and dmabuf stride size must match");
+	memcpy(fb->strides, dmabuf->attributes.stride, sizeof(fb->strides));
+	static_assert(ARRAY_LENGTH(fb->offsets) ==
+		      ARRAY_LENGTH(dmabuf->attributes.offset),
+		      "drm_fb and dmabuf offset size must match");
+	static_assert(sizeof(fb->offsets) == sizeof(dmabuf->attributes.offset),
+		      "drm_fb and dmabuf offset size must match");
+	memcpy(fb->offsets, dmabuf->attributes.offset, sizeof(fb->offsets));
+
+	fb->format = pixel_format_get_info(dmabuf->attributes.format);
+	if (!fb->format) {
+		weston_log("couldn't look up format info for 0x%lx\n",
+			   (unsigned long) dmabuf->attributes.format);
+		goto err_free;
+	}
+
+	if (is_opaque)
+		fb->format = pixel_format_get_opaque_substitute(fb->format);
+
+	if (backend->min_width > fb->width ||
+	    fb->width > backend->max_width ||
+	    backend->min_height > fb->height ||
+	    fb->height > backend->max_height) {
+		weston_log("bo geometry out of bounds\n");
+		goto err_free;
+	}
+
+	for (i = 0; i < dmabuf->attributes.n_planes; i++) {
+		int ret;
+		ret = drmPrimeFDToHandle (fb->fd, dmabuf->attributes.fd[i], &gem_handle[i]);
+		if (ret) {
+			weston_log ("got gem_handle %x\n", gem_handle[i]);
+			goto err_free;
+		}
+		fb->handles[i] = gem_handle[i];
+	}
+
+	if (gem_handle[0] != 0)
+		goto add_fb;
 
 	static_assert(ARRAY_LENGTH(import_mod.fds) ==
 		      ARRAY_LENGTH(dmabuf->attributes.fd),
@@ -1147,52 +1207,23 @@
 	if (!fb->bo)
 		goto err_free;
 
-	fb->width = dmabuf->attributes.width;
-	fb->height = dmabuf->attributes.height;
-	fb->modifier = dmabuf->attributes.modifier[0];
-	fb->size = 0;
-	fb->fd = backend->drm.fd;
-
-	static_assert(ARRAY_LENGTH(fb->strides) ==
-		      ARRAY_LENGTH(dmabuf->attributes.stride),
-		      "drm_fb and dmabuf stride size must match");
-	static_assert(sizeof(fb->strides) == sizeof(dmabuf->attributes.stride),
-		      "drm_fb and dmabuf stride size must match");
-	memcpy(fb->strides, dmabuf->attributes.stride, sizeof(fb->strides));
-	static_assert(ARRAY_LENGTH(fb->offsets) ==
-		      ARRAY_LENGTH(dmabuf->attributes.offset),
-		      "drm_fb and dmabuf offset size must match");
-	static_assert(sizeof(fb->offsets) == sizeof(dmabuf->attributes.offset),
-		      "drm_fb and dmabuf offset size must match");
-	memcpy(fb->offsets, dmabuf->attributes.offset, sizeof(fb->offsets));
-
-	fb->format = pixel_format_get_info(dmabuf->attributes.format);
-	if (!fb->format) {
-		weston_log("couldn't look up format info for 0x%lx\n",
-			   (unsigned long) dmabuf->attributes.format);
-		goto err_free;
-	}
-
-	if (is_opaque)
-		fb->format = pixel_format_get_opaque_substitute(fb->format);
-
-	if (backend->min_width > fb->width ||
-	    fb->width > backend->max_width ||
-	    backend->min_height > fb->height ||
-	    fb->height > backend->max_height) {
-		weston_log("bo geometry out of bounds\n");
-		goto err_free;
-	}
-
 	for (i = 0; i < dmabuf->attributes.n_planes; i++) {
 		fb->handles[i] = gbm_bo_get_handle_for_plane(fb->bo, i).u32;
 		if (!fb->handles[i])
 			goto err_free;
 	}
 
+add_fb:
 	if (drm_fb_addfb(fb) != 0)
 		goto err_free;
 
+	if (gem_handle[0] != 0) {
+		for (i = 0; i < dmabuf->attributes.n_planes; i++) {
+			struct drm_gem_close arg = { gem_handle[i], };
+			drmIoctl (fb->fd, DRM_IOCTL_GEM_CLOSE, &arg);
+		}
+	}
+
 	return fb;
 
 err_free: