[mutter] crtc/kms: Add parsing for IN_FORMATS property



commit d670a1aa78ff67358b483e411528df6ec466727b
Author: Daniel Stone <daniels collabora com>
Date:   Thu Aug 3 13:42:15 2017 +0100

    crtc/kms: Add parsing for IN_FORMATS property
    
    The KMS IN_FORMATS blob property contains a structure defining which
    format/modifier combinations are supported for each plane. Use this to
    extract a list of acceptable modifiers to use for the primary plane for
    XRGB8888, so we can ask EGL to allocate tiled/compressed buffers for
    scanout when available.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=785779

 configure.ac                        |    2 +-
 src/backends/native/meta-crtc-kms.c |  104 ++++++++++++++++++++++++++++++++++-
 2 files changed, 104 insertions(+), 2 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 44b84da..4234814 100644
--- a/configure.ac
+++ b/configure.ac
@@ -266,7 +266,7 @@ AC_SUBST(XWAYLAND_PATH)
 
 PKG_CHECK_MODULES(MUTTER, $MUTTER_PC_MODULES)
 
-MUTTER_NATIVE_BACKEND_MODULES="libdrm libsystemd libinput >= 1.4 gudev-1.0 gbm >= 10.3"
+MUTTER_NATIVE_BACKEND_MODULES="libdrm >= 2.4.83 libsystemd libinput >= 1.4 gudev-1.0 gbm >= 10.3"
 
 AC_ARG_ENABLE(native-backend,
   AS_HELP_STRING([--disable-native-backend], [disable mutter native (KMS) backend]),,
diff --git a/src/backends/native/meta-crtc-kms.c b/src/backends/native/meta-crtc-kms.c
index 492734e..8152991 100644
--- a/src/backends/native/meta-crtc-kms.c
+++ b/src/backends/native/meta-crtc-kms.c
@@ -23,6 +23,9 @@
 
 #include "backends/native/meta-crtc-kms.h"
 
+#include <drm_fourcc.h>
+#include <drm_mode.h>
+
 #include "backends/meta-backend-private.h"
 #include "backends/native/meta-gpu-kms.h"
 
@@ -36,9 +39,12 @@ typedef struct _MetaCrtcKms
   uint32_t underscan_hborder_prop_id;
   uint32_t underscan_vborder_prop_id;
   uint32_t primary_plane_id;
+  uint32_t formats_prop_id;
   uint32_t rotation_prop_id;
   uint32_t rotation_map[ALL_TRANSFORMS];
   uint32_t all_hw_transforms;
+
+  GArray *modifiers_xrgb8888;
 } MetaCrtcKms;
 
 gboolean
@@ -168,6 +174,89 @@ find_property_index (MetaGpu                    *gpu,
   return -1;
 }
 
+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);
+}
+
+static void
+parse_formats (MetaCrtc *crtc,
+               int       kms_fd,
+               uint32_t  blob_id)
+{
+  MetaCrtcKms *crtc_kms = crtc->driver_private;
+  drmModePropertyBlobPtr blob;
+  struct drm_format_modifier_blob *blob_fmt;
+  uint32_t *formats;
+  struct drm_format_modifier *modifiers;
+  unsigned int i;
+  unsigned int xrgb_idx = UINT_MAX;
+
+  if (blob_id == 0)
+    return;
+
+  blob = drmModeGetPropertyBlob (kms_fd, blob_id);
+  if (!blob)
+    return;
+
+  if (blob->length < sizeof (struct drm_format_modifier_blob))
+    {
+      drmModeFreePropertyBlob (blob);
+      return;
+    }
+
+  blob_fmt = blob->data;
+
+  /* Find the index of our XRGB8888 format. */
+  formats = formats_ptr (blob_fmt);
+  for (i = 0; i < blob_fmt->count_formats; i++)
+    {
+      if (formats[i] == DRM_FORMAT_XRGB8888)
+        {
+          xrgb_idx = i;
+          break;
+        }
+    }
+
+  if (xrgb_idx == UINT_MAX)
+    {
+      drmModeFreePropertyBlob (blob);
+      return;
+    }
+
+  modifiers = modifiers_ptr (blob_fmt);
+  crtc_kms->modifiers_xrgb8888 = g_array_new (FALSE, FALSE, sizeof (uint64_t));
+  for (i = 0; i < blob_fmt->count_modifiers; i++)
+    {
+      /* The modifier advertisement blob is partitioned into groups of
+       * 64 formats. */
+      if (xrgb_idx < modifiers[i].offset ||
+          xrgb_idx > modifiers[i].offset + 63)
+        continue;
+
+      if (!(modifiers[i].formats & (1 << (xrgb_idx - modifiers[i].offset))))
+        continue;
+
+      g_array_append_val (crtc_kms->modifiers_xrgb8888, modifiers[i].modifier);
+    }
+
+  if (crtc_kms->modifiers_xrgb8888->len == 0)
+    {
+      g_array_free (crtc_kms->modifiers_xrgb8888, TRUE);
+      crtc_kms->modifiers_xrgb8888 = NULL;
+    }
+
+  drmModeFreePropertyBlob (blob);
+}
+
 static void
 parse_transforms (MetaCrtc          *crtc,
                   drmModePropertyPtr prop)
@@ -246,7 +335,7 @@ init_crtc_rotations (MetaCrtc *crtc,
 
           if (props && is_primary_plane (gpu, props))
             {
-              int rotation_idx;
+              int rotation_idx, fmts_idx;
 
               crtc_kms->primary_plane_id = drm_plane->plane_id;
               rotation_idx = find_property_index (gpu, props,
@@ -257,6 +346,15 @@ init_crtc_rotations (MetaCrtc *crtc,
                   parse_transforms (crtc, prop);
                   drmModeFreeProperty (prop);
                 }
+
+              fmts_idx = find_property_index (gpu, props,
+                                              "IN_FORMATS", &prop);
+              if (fmts_idx >= 0)
+                {
+                  crtc_kms->formats_prop_id = props->props[fmts_idx];
+                  parse_formats (crtc, kms_fd, props->prop_values[fmts_idx]);
+                  drmModeFreeProperty (prop);
+                }
             }
 
           if (props)
@@ -311,6 +409,10 @@ find_crtc_properties (MetaCrtc   *crtc,
 static void
 meta_crtc_destroy_notify (MetaCrtc *crtc)
 {
+  MetaCrtcKms *crtc_kms = crtc->driver_private;
+
+  if (crtc_kms->modifiers_xrgb8888)
+    g_array_free (crtc_kms->modifiers_xrgb8888, TRUE);
   g_free (crtc->driver_private);
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]