[PATCH weston v9 61/62] [XXX] compositor-drm: Support drmModeGetPlane2

Daniel Stone daniels at collabora.com
Fri Mar 3 23:06:12 UTC 2017


GetPlane2 adds information about format modifiers; we can use these to
both feed GBM with the set of modifiers we want to use for rendering,
and also as an early-out test when we're trying to see if a FB will go
on a particular plane.

XXX: Depends on krh/bwidawsk's unmerged kernel/libdrm patches.

Signed-off-by: Daniel Stone <daniels at collabora.com>
---
 configure.ac               |  4 +++
 libweston/compositor-drm.c | 78 ++++++++++++++++++++++++++++++++++++++++++----
 libweston/meson.build      |  5 +++
 3 files changed, 81 insertions(+), 6 deletions(-)

v9: New. Not proposing to merge.
    In order to merge the GETPLANE2 ioctl in the kernel, we need to
    demonstrate viable userspace, with some acks that it looks like a
    sane ABI for us to use with no pitfalls. So I would like an eye
    cast over it for that, but this must not be merged until it lands
    in finalised form.

diff --git a/configure.ac b/configure.ac
index 2937870..773f5ac 100644
--- a/configure.ac
+++ b/configure.ac
@@ -213,6 +213,10 @@ if test x$enable_drm_compositor = xyes; then
   PKG_CHECK_MODULES(DRM_COMPOSITOR_MODIFIERS, [libdrm >= 2.4.71],
 		    [AC_DEFINE([HAVE_DRM_ADDFB2_MODIFIERS], 1, [libdrm supports modifiers])],
 		    [AC_MSG_WARN([libdrm does not support AddFB2 with modifiers])])
+  # XXX: Will be 2.4.75 ... ?
+  PKG_CHECK_MODULES(DRM_COMPOSITOR_GETPLANE2, [libdrm >= 2.4.74],
+		    [AC_DEFINE([HAVE_DRM_GETPLANE2], 1, [libdrm supports GetPlane2])],
+		    [AC_MSG_WARN([libdrm does not support GetPlane2])])
 fi
 
 
diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c
index bf9571c..755f4f8 100644
--- a/libweston/compositor-drm.c
+++ b/libweston/compositor-drm.c
@@ -368,7 +368,11 @@ struct drm_plane {
 
 	struct wl_list link;
 
-	uint32_t formats[];
+	struct {
+		uint32_t format;
+		uint32_t count_modifiers;
+		uint64_t *modifiers;
+	} formats[];
 };
 
 struct drm_output {
@@ -2658,7 +2662,19 @@ drm_output_prepare_overlay_view(struct drm_output_state *output_state,
 
 		/* Check whether the format is supported */
 		for (i = 0; i < p->count_formats; i++) {
-			if (p->formats[i] == fb->format->format)
+			unsigned int j;
+
+			if (p->formats[i].format != fb->format->format)
+				continue;
+
+			if (!fb->modifier)
+				break;
+
+			for (j = 0; j < p->formats[i].count_modifiers; j++) {
+				if (p->formats[i].modifiers[j] == fb->modifier)
+					break;
+			}
+			if (j != p->formats[i].count_modifiers)
 				break;
 		}
 		if (i == p->count_formats)
@@ -3402,6 +3418,43 @@ init_pixman(struct drm_backend *b)
 }
 
 /**
+ * Populates the formats array for a drm_plane.
+ */
+#ifdef HAVE_DRM_GETPLANE2
+static bool
+populate_modifiers(struct drm_plane *plane, const drmModePlane *kplane,
+		   int fmt_idx)
+{
+	unsigned int j;
+	unsigned int k = 0;
+	uint64_t *modifiers = NULL;
+	unsigned int size_modifiers = 0;
+
+	for (j = 0; j < kplane->count_format_modifiers; j++) {
+		struct drm_format_modifier *mod;
+		mod = &kplane->format_modifiers[j];
+		if (!(mod->formats & (1 << fmt_idx)))
+			continue;
+
+		if (size_modifiers <= k) {
+			size_modifiers += 8;
+			modifiers = realloc(modifiers,
+					    size_modifiers *
+					      sizeof(modifiers[0]));
+			if (!modifiers)
+				return false;
+		}
+		modifiers[k++] = mod->modifier;
+	}
+
+	plane->formats[fmt_idx].modifiers = modifiers;
+	plane->formats[fmt_idx].count_modifiers = k;
+
+	return true;
+}
+#endif
+
+/**
  * Create a drm_plane for a hardware plane
  *
  * Creates one drm_plane structure for a hardware plane, and initialises its
@@ -3441,7 +3494,7 @@ drm_plane_create(struct drm_backend *b, const drmModePlane *kplane,
 		       (type == WDRM_PLANE_TYPE_OVERLAY || (output && format)));
 
 	plane = zalloc(sizeof(*plane) +
-		       (sizeof(uint32_t) * num_formats));
+		       (sizeof(plane->formats[0]) * num_formats));
 	if (!plane) {
 		weston_log("%s: out of memory\n", __func__);
 		return NULL;
@@ -3452,17 +3505,26 @@ drm_plane_create(struct drm_backend *b, const drmModePlane *kplane,
 	plane->state_cur->complete = true;
 
 	if (kplane) {
+		uint32_t i;
+
 		plane->possible_crtcs = kplane->possible_crtcs;
 		plane->plane_id = kplane->plane_id;
 		plane->count_formats = kplane->count_formats;
-		memcpy(plane->formats, kplane->formats,
-		       kplane->count_formats * sizeof(kplane->formats[0]));
+		for (i = 0; i < kplane->count_formats; i++) {
+			plane->formats[i].format = kplane->formats[i];
+#ifdef HAVE_DRM_GETPLANE2
+			if (!populate_modifiers(plane, kplane, i)) {
+				weston_log("%s: out of memory\n", __func__);
+				return NULL;
+			}
+#endif
+		}
 	}
 	else {
 		plane->possible_crtcs = (1 << output->pipe);
 		plane->plane_id = 0;
 		plane->count_formats = 1;
-		plane->formats[0] = format;
+		plane->formats[0].format = format;
 	}
 
 	props = drmModeObjectGetProperties(b->drm.fd, kplane->plane_id,
@@ -3621,7 +3683,11 @@ create_sprites(struct drm_backend *b)
 	}
 
 	for (i = 0; i < kplane_res->count_planes; i++) {
+#ifdef HAVE_DRM_GETPLANE2
+		kplane = drmModeGetPlane2(b->drm.fd, kplane_res->planes[i]);
+#else
 		kplane = drmModeGetPlane(b->drm.fd, kplane_res->planes[i]);
+#endif
 		if (!kplane)
 			continue;
 
diff --git a/libweston/meson.build b/libweston/meson.build
index 8127602..f139356 100644
--- a/libweston/meson.build
+++ b/libweston/meson.build
@@ -174,6 +174,11 @@ if get_option('backend_drm')
 		config_h.set('HAVE_DRM_ADDFB2_MODIFIERS', '1')
 	endif
 
+	# XXX: Will be 2.4.75 ... ?
+	if dep_drm.version().version_compare('>= 2.4.74')
+		config_h.set('HAVE_DRM_GETPLANE2', '1')
+	endif
+
 	plugin_drm = shared_library('drm-backend',
 		files_drm,
 		include_directories: include_directories('..', '../shared'),
-- 
2.9.3



More information about the wayland-devel mailing list