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 <dani...@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

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to