[RFC xserver v3 08/14] modesetting: Get supported formats/modifiers for scanout

Louis-Francis Ratté-Boulianne lfrb at collabora.com
Wed Sep 27 05:19:07 UTC 2017


Retrieve IN_FORMATS property from the plane. It gives the
allowed formats and modifiers for BO allocation.

Signed-off-by: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
---
 configure.ac                                     |   4 +
 hw/xfree86/drivers/modesetting/drmmode_display.c | 114 ++++++++++++++++++++++-
 hw/xfree86/drivers/modesetting/drmmode_display.h |   9 ++
 include/dix-config.h.in                          |   3 +
 include/meson.build                              |   2 +
 5 files changed, 128 insertions(+), 4 deletions(-)

diff --git a/configure.ac b/configure.ac
index 3b6a1507e..00f1cc648 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2107,6 +2107,10 @@ if test "x$GLAMOR" = xyes; then
 	PKG_CHECK_EXISTS(libdrm >= 2.4.74,
 			 [AC_DEFINE(GLAMOR_HAS_DRM_NAME_FROM_FD_2, 1, [Have GLAMOR_HAS_DRM_NAME_FROM_FD_2])],
 			 [])
+
+	PKG_CHECK_EXISTS(libdrm >= 2.4.83,
+			 [AC_DEFINE(GLAMOR_HAS_DRM_MODIFIERS, 1, [Have GLAMOR_HAS_DRM_MODIFIERS])],
+			 [])
 fi
 AM_CONDITIONAL([GLAMOR_EGL], [test "x$GBM" = xyes])
 
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
index 0e9498a6b..0dbf4a686 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -56,6 +56,23 @@ static Bool drmmode_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height);
 static PixmapPtr drmmode_create_pixmap_header(ScreenPtr pScreen, int width, int height,
                                               int depth, int bitsPerPixel, int devKind,
                                               void *pPixData);
+
+#ifdef GLAMOR_HAS_DRM_MODIFIERS
+
+static inline uint32_t *
+formats_ptr(struct drm_format_modifier_blob *blob)
+{
+    return (uint32_t *)(((char *)blob) + blob->formats_offset);
+}
+
+static inline struct drm_format_modifier *
+modifiers_ptr(struct drm_format_modifier_blob *blob)
+{
+    return (struct drm_format_modifier *)(((char *)blob) + blob->modifiers_offset);
+}
+
+#endif
+
 static Bool
 drmmode_zaphod_string_matches(ScrnInfoPtr scrn, const char *s, char *output_name)
 {
@@ -1557,15 +1574,76 @@ is_plane_assigned(ScrnInfoPtr scrn, int plane_id)
     return FALSE;
 }
 
+#ifdef GLAMOR_HAS_DRM_MODIFIERS
+/**
+ * Populates the formats array, and the modifiers of each format for a drm_plane.
+ */
+static Bool
+populate_format_modifiers(xf86CrtcPtr crtc, const drmModePlane *kplane,
+                          uint32_t blob_id)
+{
+    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+    drmmode_ptr drmmode = drmmode_crtc->drmmode;
+    unsigned i, j;
+    drmModePropertyBlobRes *blob;
+    struct drm_format_modifier_blob *fmt_mod_blob;
+    uint32_t *blob_formats;
+    struct drm_format_modifier *blob_modifiers;
+
+    blob = drmModeGetPropertyBlob(drmmode->fd, blob_id);
+    if (!blob)
+        return FALSE;
+
+    fmt_mod_blob = blob->data;
+    blob_formats = formats_ptr(fmt_mod_blob);
+    blob_modifiers = modifiers_ptr(fmt_mod_blob);
+
+    assert(drmmode_crtc->num_formats == fmt_mod_blob->count_formats);
+
+    for (i = 0; i < fmt_mod_blob->count_formats; i++) {
+        uint32_t num_modifiers = 0;
+        uint64_t *modifiers = NULL;
+        uint64_t *tmp;
+
+        for (j = 0; j < fmt_mod_blob->count_modifiers; j++) {
+            struct drm_format_modifier *mod = &blob_modifiers[j];
+
+            if ((i < mod->offset) || (i > mod->offset + 63))
+                continue;
+            if (!(mod->formats & (1 << (i - mod->offset))))
+                continue;
+
+            num_modifiers++;
+            tmp = realloc(modifiers, num_modifiers * sizeof(modifiers[0]));
+            if (!tmp) {
+                free(modifiers);
+                drmModeFreePropertyBlob(blob);
+                return FALSE;
+            }
+            modifiers = tmp;
+            modifiers[num_modifiers - 1] = mod->modifier;
+        }
+
+        drmmode_crtc->formats[i].format = blob_formats[i];
+        drmmode_crtc->formats[i].modifiers = modifiers;
+        drmmode_crtc->formats[i].num_modifiers = num_modifiers;
+    }
+
+    drmModeFreePropertyBlob(blob);
+
+    return TRUE;
+}
+#endif
+
 static void
 drmmode_crtc_create_planes(xf86CrtcPtr crtc, int num)
 {
     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
     drmmode_ptr drmmode = drmmode_crtc->drmmode;
     drmModePlaneRes *kplane_res;
-    drmModePlane *kplane;
+    drmModePlane *kplane, *best_kplane = NULL;
     drmModeObjectProperties *props;
-    uint32_t i, type;
+    uint32_t i, type, blob_id;
     int current_crtc, best_plane = 0;
 
     static drmmode_prop_enum_info_rec plane_type_enums[] = {
@@ -1587,6 +1665,7 @@ drmmode_crtc_create_planes(xf86CrtcPtr crtc, int num)
         },
         [DRMMODE_PLANE_FB_ID] = { .name = "FB_ID", },
         [DRMMODE_PLANE_CRTC_ID] = { .name = "CRTC_ID", },
+        [DRMMODE_PLANE_IN_FORMATS] = { .name = "IN_FORMATS", },
         [DRMMODE_PLANE_SRC_X] = { .name = "SRC_X", },
         [DRMMODE_PLANE_SRC_Y] = { .name = "SRC_Y", },
         [DRMMODE_PLANE_SRC_W] = { .name = "SRC_W", },
@@ -1625,13 +1704,13 @@ drmmode_crtc_create_planes(xf86CrtcPtr crtc, int num)
         }
 
         plane_id = kplane->plane_id;
-        drmModeFreePlane(kplane);
 
         props = drmModeObjectGetProperties(drmmode->fd, plane_id,
                                            DRM_MODE_OBJECT_PLANE);
         if (!props) {
             xf86DrvMsg(drmmode->scrn->scrnIndex, X_ERROR,
                     "couldn't get plane properties\n");
+            drmModeFreePlane(kplane);
             continue;
         }
 
@@ -1641,6 +1720,7 @@ drmmode_crtc_create_planes(xf86CrtcPtr crtc, int num)
         type = drmmode_prop_get_value(&tmp_props[DRMMODE_PLANE_TYPE],
                                       props, DRMMODE_PLANE_TYPE__COUNT);
         if (type != DRMMODE_PLANE_TYPE_PRIMARY) {
+            drmModeFreePlane(kplane);
             drmModeFreeObjectProperties(props);
             continue;
         }
@@ -1649,9 +1729,14 @@ drmmode_crtc_create_planes(xf86CrtcPtr crtc, int num)
         current_crtc = drmmode_prop_get_value(&tmp_props[DRMMODE_PLANE_CRTC_ID],
                                               props, 0);
         if (current_crtc == drmmode_crtc->mode_crtc->crtc_id) {
-            if (best_plane)
+            if (best_plane) {
+                drmModeFreePlane(best_kplane);
                 drmmode_prop_info_free(drmmode_crtc->props_plane, DRMMODE_PLANE__COUNT);
+            }
             best_plane = plane_id;
+            best_kplane = kplane;
+            blob_id = drmmode_prop_get_value(&tmp_props[DRMMODE_PLANE_IN_FORMATS],
+                                             props, 0);
             drmmode_prop_info_copy(drmmode_crtc->props_plane, tmp_props,
                                    DRMMODE_PLANE__COUNT, 1);
             drmModeFreeObjectProperties(props);
@@ -1660,14 +1745,35 @@ drmmode_crtc_create_planes(xf86CrtcPtr crtc, int num)
 
         if (!best_plane) {
             best_plane = plane_id;
+            best_kplane = kplane;
+            blob_id = drmmode_prop_get_value(&tmp_props[DRMMODE_PLANE_IN_FORMATS],
+                                             props, 0);
             drmmode_prop_info_copy(drmmode_crtc->props_plane, tmp_props,
                                    DRMMODE_PLANE__COUNT, 1);
+        } else {
+            drmModeFreePlane(kplane);
         }
 
         drmModeFreeObjectProperties(props);
     }
 
     drmmode_crtc->plane_id = best_plane;
+    if (best_kplane) {
+        drmmode_crtc->num_formats = best_kplane->count_formats;
+        drmmode_crtc->formats = calloc(sizeof(drmmode_format_rec),
+                                       best_kplane->count_formats);
+#ifdef GLAMOR_HAS_DRM_MODIFIERS
+        if (blob_id) {
+            populate_format_modifiers(crtc, best_kplane, blob_id);
+        }
+        else
+#endif
+        {
+            for (i = 0; i < best_kplane->count_formats; i++)
+                drmmode_crtc->formats[i].format = best_kplane->formats[i];
+        }
+        drmModeFreePlane(best_kplane);
+    }
 
     drmmode_prop_info_free(tmp_props, DRMMODE_PLANE__COUNT);
     drmModeFreePlaneResources(kplane_res);
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.h b/hw/xfree86/drivers/modesetting/drmmode_display.h
index c369478bf..18e874ca9 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.h
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.h
@@ -39,6 +39,7 @@ struct gbm_device;
 enum drmmode_plane_property {
     DRMMODE_PLANE_TYPE = 0,
     DRMMODE_PLANE_FB_ID,
+    DRMMODE_PLANE_IN_FORMATS,
     DRMMODE_PLANE_CRTC_ID,
     DRMMODE_PLANE_SRC_X,
     DRMMODE_PLANE_SRC_Y,
@@ -143,6 +144,12 @@ typedef struct {
 } drmmode_mode_rec, *drmmode_mode_ptr;
 
 typedef struct {
+    uint32_t format;
+    uint32_t num_modifiers;
+    uint64_t *modifiers;
+} drmmode_format_rec, *drmmode_format_ptr;
+
+typedef struct {
     drmmode_ptr drmmode;
     drmModeCrtcPtr mode_crtc;
     uint32_t vblank_pipe;
@@ -155,6 +162,8 @@ typedef struct {
     drmmode_prop_info_rec props_plane[DRMMODE_PLANE__COUNT];
     uint32_t plane_id;
     drmmode_mode_ptr current_mode;
+    uint32_t num_formats;
+    drmmode_format_rec *formats;
 
     drmmode_bo rotate_bo;
     unsigned rotate_fb_id;
diff --git a/include/dix-config.h.in b/include/dix-config.h.in
index 9c65bd3f3..08f2ac0be 100644
--- a/include/dix-config.h.in
+++ b/include/dix-config.h.in
@@ -503,6 +503,9 @@
 /* Glamor should use atomic DRM API */
 #undef GLAMOR_HAS_DRM_ATOMIC
 
+/* Glamor can retrieve supported DRM formats/modifiers */
+#undef GLAMOR_HAS_DRM_MODIFIERS
+
 /* byte order */
 #undef X_BYTE_ORDER
 
diff --git a/include/meson.build b/include/meson.build
index 4b5a2b86e..2f2b2b3d5 100644
--- a/include/meson.build
+++ b/include/meson.build
@@ -75,6 +75,8 @@ conf_data.set('GLAMOR_HAS_DRM_ATOMIC',
               libdrm_dep.found() and libdrm_dep.version().version_compare('>= 2.4.62'))
 conf_data.set('GLAMOR_HAS_DRM_NAME_FROM_FD_2',
               libdrm_dep.found() and libdrm_dep.version().version_compare('>= 2.4.74'))
+conf_data.set('GLAMOR_HAS_DRM_MODIFIERS',
+              libdrm_dep.found() and libdrm_dep.version().version_compare('>= 2.4.83'))
 conf_data.set('GLXEXT', build_glx)
 conf_data.set('GLAMOR', build_glamor)
 conf_data.set('GLAMOR_HAS_GBM', gbm_dep.found())
-- 
2.13.0



More information about the xorg-devel mailing list