[mutter/wip/gbsneto/kms-transactions-on-steroids: 19/30] crtc/kms: Use MetaKmsPlane to check supported rotations and formats



commit f6276768786af3906a7fa9bdf062cb1e90eb6f3e
Author: Jonas Ã…dahl <jadahl gmail com>
Date:   Sat Mar 9 18:23:28 2019 +0100

    crtc/kms: Use MetaKmsPlane to check supported rotations and formats
    
    Instead of manually retrieving supported transforms and formats from the
    primary plane of the CRTC, use the MetaKmsPlane abstraction to find the
    primary plane of the CRTC and check compatibility using the
    MetaKmsPlane API. This removes the last user of direct KMS API usage
    except for applying configuration.
    
    https://gitlab.gnome.org/GNOME/mutter/issues/548
    https://gitlab.gnome.org/GNOME/mutter/merge_requests/525

 src/backends/native/meta-crtc-kms.c   | 306 +++++-----------------------------
 src/backends/native/meta-gpu-kms.c    |   6 +
 src/backends/native/meta-gpu-kms.h    |   2 +
 src/backends/native/meta-kms-device.c |  27 +++
 src/backends/native/meta-kms-device.h |   3 +
 src/backends/native/meta-kms-plane.c  | 184 +++++++++++++++++++-
 src/backends/native/meta-kms-plane.h  |  10 ++
 src/backends/native/meta-kms-types.h  |   1 +
 8 files changed, 275 insertions(+), 264 deletions(-)
---
diff --git a/src/backends/native/meta-crtc-kms.c b/src/backends/native/meta-crtc-kms.c
index 126621cc0..982a8176a 100644
--- a/src/backends/native/meta-crtc-kms.c
+++ b/src/backends/native/meta-crtc-kms.c
@@ -29,6 +29,8 @@
 
 #include "backends/meta-backend-private.h"
 #include "backends/native/meta-gpu-kms.h"
+#include "backends/native/meta-kms-device.h"
+#include "backends/native/meta-kms-plane.h"
 
 /* added in libdrm 2.4.95 */
 #ifndef DRM_FORMAT_INVALID
@@ -41,17 +43,10 @@ typedef struct _MetaCrtcKms
 {
   MetaKmsCrtc *kms_crtc;
 
-  uint32_t primary_plane_id;
   uint32_t rotation_prop_id;
   uint32_t rotation_map[META_MONITOR_N_TRANSFORMS];
-  uint32_t all_hw_transforms;
-
-  /*
-   * primary plane's supported formats and maybe modifiers
-   * key: GUINT_TO_POINTER (format)
-   * value: owned GArray* (uint64_t modifier), or NULL
-   */
-  GHashTable *formats_modifiers;
+
+  MetaKmsPlane *primary_plane;
 } MetaCrtcKms;
 
 /**
@@ -93,10 +88,11 @@ meta_crtc_kms_is_transform_handled (MetaCrtc             *crtc,
 {
   MetaCrtcKms *crtc_kms = crtc->driver_private;
 
-  if ((1 << transform) & crtc_kms->all_hw_transforms)
-    return TRUE;
-  else
+  if (!crtc_kms->primary_plane)
     return FALSE;
+
+  return meta_kms_plane_is_transform_handled (crtc_kms->primary_plane,
+                                              transform);
 }
 
 void
@@ -110,28 +106,18 @@ meta_crtc_kms_apply_transform (MetaCrtc *crtc)
 
   kms_fd = meta_gpu_kms_get_fd (gpu_kms);
 
-  if (crtc_kms->all_hw_transforms & (1 << crtc->transform))
-    hw_transform = crtc->transform;
-  else
+  hw_transform = crtc->transform;
+  if (!meta_crtc_kms_is_transform_handled (crtc, hw_transform))
     hw_transform = META_MONITOR_TRANSFORM_NORMAL;
-
-  if (!meta_crtc_kms_is_transform_handled (crtc, META_MONITOR_TRANSFORM_NORMAL))
+  if (!meta_crtc_kms_is_transform_handled (crtc, hw_transform))
     return;
 
   if (drmModeObjectSetProperty (kms_fd,
-                                crtc_kms->primary_plane_id,
+                                meta_kms_plane_get_id (crtc_kms->primary_plane),
                                 DRM_MODE_OBJECT_PLANE,
                                 crtc_kms->rotation_prop_id,
                                 crtc_kms->rotation_map[hw_transform]) != 0)
-    {
-      g_warning ("Failed to apply DRM plane transform %d: %m", hw_transform);
-
-      /*
-       * Blacklist this HW transform, we want to fallback to our
-       * fallbacks in this case.
-       */
-      crtc_kms->all_hw_transforms &= ~(1 << hw_transform);
-    }
+    g_warning ("Failed to apply DRM plane transform %d: %m", hw_transform);
 }
 
 static int
@@ -194,8 +180,8 @@ meta_crtc_kms_get_modifiers (MetaCrtc *crtc,
 {
   MetaCrtcKms *crtc_kms = crtc->driver_private;
 
-  return g_hash_table_lookup (crtc_kms->formats_modifiers,
-                              GUINT_TO_POINTER (format));
+  return meta_kms_plane_get_modifiers_for_format (crtc_kms->primary_plane,
+                                                  format);
 }
 
 /**
@@ -210,24 +196,8 @@ GArray *
 meta_crtc_kms_copy_drm_format_list (MetaCrtc *crtc)
 {
   MetaCrtcKms *crtc_kms = crtc->driver_private;
-  GArray *formats;
-  GHashTableIter it;
-  gpointer key;
-  unsigned int n_formats_modifiers;
-
-  n_formats_modifiers = g_hash_table_size (crtc_kms->formats_modifiers);
-  formats = g_array_sized_new (FALSE,
-                               FALSE,
-                               sizeof (uint32_t),
-                               n_formats_modifiers);
-  g_hash_table_iter_init (&it, crtc_kms->formats_modifiers);
-  while (g_hash_table_iter_next (&it, &key, NULL))
-    {
-      uint32_t drm_format = GPOINTER_TO_UINT (key);
-      g_array_append_val (formats, drm_format);
-    }
 
-  return formats;
+  return meta_kms_plane_copy_drm_format_list (crtc_kms->primary_plane);
 }
 
 /**
@@ -243,124 +213,8 @@ meta_crtc_kms_supports_format (MetaCrtc *crtc,
 {
   MetaCrtcKms *crtc_kms = crtc->driver_private;
 
-  return g_hash_table_lookup_extended (crtc_kms->formats_modifiers,
-                                       GUINT_TO_POINTER (drm_format),
-                                       NULL,
-                                       NULL);
-}
-
-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
-free_modifier_array (GArray *array)
-{
-  if (!array)
-    return;
-
-  g_array_free (array, TRUE);
-}
-
-/*
- * In case the DRM driver does not expose a format list for the
- * primary plane (does not support universal planes nor
- * IN_FORMATS property), hardcode something that is probably supported.
- */
-static const uint32_t drm_default_formats[] =
-  {
-    DRM_FORMAT_XRGB8888 /* The format everything should always support by convention */,
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
-    DRM_FORMAT_XBGR8888 /* OpenGL GL_RGBA, GL_UNSIGNED_BYTE format, hopefully supported */
-#endif
-  };
-
-static void
-set_formats_from_array (MetaCrtc       *crtc,
-                        const uint32_t *formats,
-                        size_t          n_formats)
-{
-  MetaCrtcKms *crtc_kms = crtc->driver_private;
-  size_t i;
-
-  for (i = 0; i < n_formats; i++)
-    {
-      g_hash_table_insert (crtc_kms->formats_modifiers,
-                           GUINT_TO_POINTER (formats[i]), NULL);
-    }
-}
-
-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 fmt_i, mod_i;
-
-  g_return_if_fail (g_hash_table_size (crtc_kms->formats_modifiers) == 0);
-
-  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;
-
-  formats = formats_ptr (blob_fmt);
-  modifiers = modifiers_ptr (blob_fmt);
-
-  for (fmt_i = 0; fmt_i < blob_fmt->count_formats; fmt_i++)
-    {
-      GArray *mod_tmp = g_array_new (FALSE, FALSE, sizeof (uint64_t));
-
-      for (mod_i = 0; mod_i < blob_fmt->count_modifiers; mod_i++)
-        {
-          struct drm_format_modifier *modifier = &modifiers[mod_i];
-
-          /* The modifier advertisement blob is partitioned into groups of
-           * 64 formats. */
-          if (fmt_i < modifier->offset || fmt_i > modifier->offset + 63)
-            continue;
-
-          if (!(modifier->formats & (1 << (fmt_i - modifier->offset))))
-            continue;
-
-          g_array_append_val (mod_tmp, modifier->modifier);
-        }
-
-      if (mod_tmp->len == 0)
-        {
-          free_modifier_array (mod_tmp);
-          mod_tmp = NULL;
-        }
-
-      g_hash_table_insert (crtc_kms->formats_modifiers,
-                           GUINT_TO_POINTER (formats[fmt_i]), mod_tmp);
-    }
-
-  drmModeFreePropertyBlob (blob);
+  return meta_kms_plane_is_format_supported (crtc_kms->primary_plane,
+                                             drm_format);
 }
 
 static void
@@ -384,28 +238,10 @@ parse_transforms (MetaCrtc          *crtc,
         transform = META_MONITOR_TRANSFORM_270;
 
       if (transform != -1)
-        {
-          crtc_kms->all_hw_transforms |= 1 << transform;
-          crtc_kms->rotation_map[transform] = 1 << prop->enums[i].value;
-        }
+        crtc_kms->rotation_map[transform] = 1 << prop->enums[i].value;
     }
 }
 
-static gboolean
-is_primary_plane (MetaGpu                   *gpu,
-                  drmModeObjectPropertiesPtr props)
-{
-  drmModePropertyPtr prop;
-  int idx;
-
-  idx = find_property_index (gpu, props, "type", &prop);
-  if (idx < 0)
-    return FALSE;
-
-  drmModeFreeProperty (prop);
-  return props->prop_values[idx] == DRM_PLANE_TYPE_PRIMARY;
-}
-
 static void
 init_crtc_rotations (MetaCrtc *crtc,
                      MetaGpu  *gpu)
@@ -413,91 +249,35 @@ init_crtc_rotations (MetaCrtc *crtc,
   MetaCrtcKms *crtc_kms = crtc->driver_private;
   MetaGpuKms *gpu_kms = META_GPU_KMS (gpu);
   int kms_fd;
-  drmModeObjectPropertiesPtr props;
-  drmModePlaneRes *planes;
+  uint32_t primary_plane_id;
   drmModePlane *drm_plane;
-  unsigned int i;
-  int crtc_idx;
+  drmModeObjectPropertiesPtr props;
+  drmModePropertyPtr prop;
+  int rotation_idx;
 
   kms_fd = meta_gpu_kms_get_fd (gpu_kms);
-
-  planes = drmModeGetPlaneResources (kms_fd);
-  if (planes == NULL)
-    return;
-
-  crtc_idx = meta_kms_crtc_get_idx (crtc_kms->kms_crtc);
-  for (i = 0; i < planes->count_planes; i++)
+  primary_plane_id = meta_kms_plane_get_id (crtc_kms->primary_plane);
+  drm_plane = drmModeGetPlane (kms_fd, primary_plane_id);
+  props = drmModeObjectGetProperties (kms_fd,
+                                      primary_plane_id,
+                                      DRM_MODE_OBJECT_PLANE);
+
+  rotation_idx = find_property_index (gpu, props,
+                                      "rotation", &prop);
+  if (rotation_idx >= 0)
     {
-      drmModePropertyPtr prop;
-
-      drm_plane = drmModeGetPlane (kms_fd, planes->planes[i]);
-
-      if (!drm_plane)
-        continue;
-
-      if ((drm_plane->possible_crtcs & (1 << crtc_idx)))
-        {
-          props = drmModeObjectGetProperties (kms_fd,
-                                              drm_plane->plane_id,
-                                              DRM_MODE_OBJECT_PLANE);
-
-          if (props && is_primary_plane (gpu, props))
-            {
-              int rotation_idx, fmts_idx;
-
-              crtc_kms->primary_plane_id = drm_plane->plane_id;
-              rotation_idx = find_property_index (gpu, props,
-                                                  "rotation", &prop);
-              if (rotation_idx >= 0)
-                {
-                  crtc_kms->rotation_prop_id = props->props[rotation_idx];
-                  parse_transforms (crtc, prop);
-                  drmModeFreeProperty (prop);
-                }
-
-              fmts_idx = find_property_index (gpu, props,
-                                              "IN_FORMATS", &prop);
-              if (fmts_idx >= 0)
-                {
-                  parse_formats (crtc, kms_fd, props->prop_values[fmts_idx]);
-                  drmModeFreeProperty (prop);
-                }
-
-              /* fall back to universal plane formats without modifiers */
-              if (g_hash_table_size (crtc_kms->formats_modifiers) == 0)
-                {
-                  set_formats_from_array (crtc,
-                                          drm_plane->formats,
-                                          drm_plane->count_formats);
-                }
-            }
-
-          if (props)
-            drmModeFreeObjectProperties (props);
-        }
-
-      drmModeFreePlane (drm_plane);
+      crtc_kms->rotation_prop_id = props->props[rotation_idx];
+      parse_transforms (crtc, prop);
+      drmModeFreeProperty (prop);
     }
 
-  crtc->all_transforms |= crtc_kms->all_hw_transforms;
-
-  drmModeFreePlaneResources (planes);
-
-  /* final formats fallback to something hardcoded */
-  if (g_hash_table_size (crtc_kms->formats_modifiers) == 0)
-    {
-      set_formats_from_array (crtc,
-                              drm_default_formats,
-                              G_N_ELEMENTS (drm_default_formats));
-    }
+  drmModeFreeObjectProperties (props);
+  drmModeFreePlane (drm_plane);
 }
 
 static void
 meta_crtc_destroy_notify (MetaCrtc *crtc)
 {
-  MetaCrtcKms *crtc_kms = crtc->driver_private;
-
-  g_hash_table_destroy (crtc_kms->formats_modifiers);
   g_free (crtc->driver_private);
 }
 
@@ -506,10 +286,15 @@ meta_create_kms_crtc (MetaGpuKms  *gpu_kms,
                       MetaKmsCrtc *kms_crtc)
 {
   MetaGpu *gpu = META_GPU (gpu_kms);
+  MetaKmsDevice *kms_device;
   MetaCrtc *crtc;
   MetaCrtcKms *crtc_kms;
+  MetaKmsPlane *primary_plane;
   const MetaKmsCrtcState *crtc_state;
 
+  kms_device = meta_gpu_kms_get_kms_device (gpu_kms);
+  primary_plane = meta_kms_device_get_primary_plane_for (kms_device,
+                                                         kms_crtc);
   crtc_state = meta_kms_crtc_get_current_state (kms_crtc);
 
   crtc = g_object_new (META_TYPE_CRTC, NULL);
@@ -538,12 +323,7 @@ meta_create_kms_crtc (MetaGpuKms  *gpu_kms,
 
   crtc_kms = g_new0 (MetaCrtcKms, 1);
   crtc_kms->kms_crtc = kms_crtc;
-
-  crtc_kms->formats_modifiers =
-    g_hash_table_new_full (g_direct_hash,
-                           g_direct_equal,
-                           NULL,
-                           (GDestroyNotify) free_modifier_array);
+  crtc_kms->primary_plane = primary_plane;
 
   crtc->driver_private = crtc_kms;
   crtc->driver_notify = (GDestroyNotify) meta_crtc_destroy_notify;
diff --git a/src/backends/native/meta-gpu-kms.c b/src/backends/native/meta-gpu-kms.c
index 93f98430b..8822251fa 100644
--- a/src/backends/native/meta-gpu-kms.c
+++ b/src/backends/native/meta-gpu-kms.c
@@ -381,6 +381,12 @@ meta_gpu_kms_wait_for_flip (MetaGpuKms *gpu_kms,
   return TRUE;
 }
 
+MetaKmsDevice *
+meta_gpu_kms_get_kms_device (MetaGpuKms *gpu_kms)
+{
+  return gpu_kms->kms_device;
+}
+
 int
 meta_gpu_kms_get_fd (MetaGpuKms *gpu_kms)
 {
diff --git a/src/backends/native/meta-gpu-kms.h b/src/backends/native/meta-gpu-kms.h
index b03596076..42715004f 100644
--- a/src/backends/native/meta-gpu-kms.h
+++ b/src/backends/native/meta-gpu-kms.h
@@ -64,6 +64,8 @@ gboolean meta_gpu_kms_flip_crtc (MetaGpuKms  *gpu_kms,
 gboolean meta_gpu_kms_wait_for_flip (MetaGpuKms *gpu_kms,
                                      GError    **error);
 
+MetaKmsDevice * meta_gpu_kms_get_kms_device (MetaGpuKms *gpu_kms);
+
 int meta_gpu_kms_get_fd (MetaGpuKms *gpu_kms);
 
 uint32_t meta_gpu_kms_get_id (MetaGpuKms *gpu_kms);
diff --git a/src/backends/native/meta-kms-device.c b/src/backends/native/meta-kms-device.c
index 6f5caf02d..a4dd0006d 100644
--- a/src/backends/native/meta-kms-device.c
+++ b/src/backends/native/meta-kms-device.c
@@ -25,6 +25,7 @@
 #include "backends/native/meta-backend-native.h"
 #include "backends/native/meta-kms-impl-device.h"
 #include "backends/native/meta-kms-impl.h"
+#include "backends/native/meta-kms-plane.h"
 #include "backends/native/meta-kms-private.h"
 
 struct _MetaKmsDevice
@@ -81,6 +82,32 @@ meta_kms_device_get_crtcs (MetaKmsDevice *device)
   return device->crtcs;
 }
 
+static GList *
+meta_kms_device_get_planes (MetaKmsDevice *device)
+{
+  return device->planes;
+}
+
+MetaKmsPlane *
+meta_kms_device_get_primary_plane_for (MetaKmsDevice *device,
+                                       MetaKmsCrtc   *crtc)
+{
+  GList *l;
+
+  for (l = meta_kms_device_get_planes (device); l; l = l->next)
+    {
+      MetaKmsPlane *plane = l->data;
+
+      if (meta_kms_plane_get_plane_type (plane) != META_KMS_PLANE_TYPE_PRIMARY)
+        continue;
+
+      if (meta_kms_plane_is_usable_with (plane, crtc))
+        return plane;
+    }
+
+  return NULL;
+}
+
 typedef struct _CreateImplDeviceData
 {
   MetaKmsDevice *device;
diff --git a/src/backends/native/meta-kms-device.h b/src/backends/native/meta-kms-device.h
index 77037f237..c4ec034c3 100644
--- a/src/backends/native/meta-kms-device.h
+++ b/src/backends/native/meta-kms-device.h
@@ -39,6 +39,9 @@ GList * meta_kms_device_get_connectors (MetaKmsDevice *device);
 
 GList * meta_kms_device_get_crtcs (MetaKmsDevice *device);
 
+MetaKmsPlane * meta_kms_device_get_primary_plane_for (MetaKmsDevice *device,
+                                                      MetaKmsCrtc   *crtc);
+
 MetaKmsDevice * meta_kms_device_new (MetaKms            *kms,
                                      const char         *path,
                                      MetaKmsDeviceFlag   flags,
diff --git a/src/backends/native/meta-kms-plane.c b/src/backends/native/meta-kms-plane.c
index d4073d672..94a407bd8 100644
--- a/src/backends/native/meta-kms-plane.c
+++ b/src/backends/native/meta-kms-plane.c
@@ -41,11 +41,24 @@ struct _MetaKmsPlane
   uint32_t rotation_map[META_MONITOR_N_TRANSFORMS];
   uint32_t all_hw_transforms;
 
+  /*
+   * primary plane's supported formats and maybe modifiers
+   * key: GUINT_TO_POINTER (format)
+   * value: owned GArray* (uint64_t modifier), or NULL
+   */
+  GHashTable *formats_modifiers;
+
   MetaKmsDevice *device;
 };
 
 G_DEFINE_TYPE (MetaKmsPlane, meta_kms_plane, G_TYPE_OBJECT)
 
+uint32_t
+meta_kms_plane_get_id (MetaKmsPlane *plane)
+{
+  return plane->id;
+}
+
 MetaKmsPlaneType
 meta_kms_plane_get_plane_type (MetaKmsPlane *plane)
 {
@@ -75,10 +88,49 @@ meta_kms_plane_is_transform_handled (MetaKmsPlane         *plane,
        */
       return FALSE;
     }
-
   return plane->all_hw_transforms & (1 << transform);
 }
 
+GArray *
+meta_kms_plane_get_modifiers_for_format (MetaKmsPlane *plane,
+                                         uint32_t      format)
+{
+  return g_hash_table_lookup (plane->formats_modifiers,
+                              GUINT_TO_POINTER (format));
+}
+
+GArray *
+meta_kms_plane_copy_drm_format_list (MetaKmsPlane *plane)
+{
+  GArray *formats;
+  GHashTableIter it;
+  gpointer key;
+  unsigned int n_formats_modifiers;
+
+  n_formats_modifiers = g_hash_table_size (plane->formats_modifiers);
+  formats = g_array_sized_new (FALSE, FALSE,
+                               sizeof (uint32_t),
+                               n_formats_modifiers);
+  g_hash_table_iter_init (&it, plane->formats_modifiers);
+  while (g_hash_table_iter_next (&it, &key, NULL))
+    {
+      uint32_t drm_format = GPOINTER_TO_UINT (key);
+
+      g_array_append_val (formats, drm_format);
+    }
+
+  return formats;
+}
+
+gboolean
+meta_kms_plane_is_format_supported (MetaKmsPlane *plane,
+                                    uint32_t      drm_format)
+{
+  return g_hash_table_lookup_extended (plane->formats_modifiers,
+                                       GUINT_TO_POINTER (drm_format),
+                                       NULL, NULL);
+}
+
 gboolean
 meta_kms_plane_is_usable_with (MetaKmsPlane *plane,
                                MetaKmsCrtc  *crtc)
@@ -132,6 +184,122 @@ init_rotations (MetaKmsPlane            *plane,
     }
 }
 
+static inline uint32_t *
+drm_formats_ptr (struct drm_format_modifier_blob *blob)
+{
+  return (uint32_t *) (((char *) blob) + blob->formats_offset);
+}
+
+static inline struct drm_format_modifier *
+drm_modifiers_ptr (struct drm_format_modifier_blob *blob)
+{
+  return (struct drm_format_modifier *) (((char *) blob) +
+                                         blob->modifiers_offset);
+}
+
+static void
+free_modifier_array (GArray *array)
+{
+  if (!array)
+    return;
+
+  g_array_free (array, TRUE);
+}
+
+static void
+parse_formats (MetaKmsPlane      *plane,
+               MetaKmsImplDevice *impl_device,
+               uint32_t           blob_id)
+{
+  int fd;
+  drmModePropertyBlobPtr blob;
+  struct drm_format_modifier_blob *blob_fmt;
+  uint32_t *formats;
+  struct drm_format_modifier *drm_modifiers;
+  unsigned int fmt_i, mod_i;
+
+  g_return_if_fail (g_hash_table_size (plane->formats_modifiers) == 0);
+
+  if (blob_id == 0)
+    return;
+
+  fd = meta_kms_impl_device_get_fd (impl_device);
+  blob = drmModeGetPropertyBlob (fd, blob_id);
+  if (!blob)
+    return;
+
+  if (blob->length < sizeof (struct drm_format_modifier_blob))
+    {
+      drmModeFreePropertyBlob (blob);
+      return;
+    }
+
+  blob_fmt = blob->data;
+
+  formats = drm_formats_ptr (blob_fmt);
+  drm_modifiers = drm_modifiers_ptr (blob_fmt);
+
+  for (fmt_i = 0; fmt_i < blob_fmt->count_formats; fmt_i++)
+    {
+      GArray *modifiers = g_array_new (FALSE, FALSE, sizeof (uint64_t));
+
+      for (mod_i = 0; mod_i < blob_fmt->count_modifiers; mod_i++)
+        {
+          struct drm_format_modifier *drm_modifier = &drm_modifiers[mod_i];
+
+          /*
+           * The modifier advertisement blob is partitioned into groups of
+           * 64 formats.
+           */
+          if (fmt_i < drm_modifier->offset || fmt_i > drm_modifier->offset + 63)
+            continue;
+
+          if (!(drm_modifier->formats & (1 << (fmt_i - drm_modifier->offset))))
+            continue;
+
+          g_array_append_val (modifiers, drm_modifier->modifier);
+        }
+
+      if (modifiers->len == 0)
+        {
+          free_modifier_array (modifiers);
+          modifiers = NULL;
+        }
+
+      g_hash_table_insert (plane->formats_modifiers,
+                           GUINT_TO_POINTER (formats[fmt_i]),
+                           modifiers);
+    }
+
+  drmModeFreePropertyBlob (blob);
+}
+
+static void
+init_formats (MetaKmsPlane            *plane,
+              MetaKmsImplDevice       *impl_device,
+              drmModeObjectProperties *drm_plane_props)
+{
+  drmModePropertyPtr prop;
+  int idx;
+
+  plane->formats_modifiers =
+    g_hash_table_new_full (g_direct_hash,
+                           g_direct_equal,
+                           NULL,
+                           (GDestroyNotify) free_modifier_array);
+
+  prop = meta_kms_impl_device_find_property (impl_device, drm_plane_props,
+                                             "IN_FORMATS", &idx);
+  if (prop)
+    {
+      uint32_t blob_id;
+
+      blob_id = drm_plane_props->prop_values[idx];
+      parse_formats (plane, impl_device, blob_id);
+      drmModeFreeProperty (prop);
+    }
+}
+
 MetaKmsPlane *
 meta_kms_plane_new (MetaKmsPlaneType         type,
                     MetaKmsImplDevice       *impl_device,
@@ -147,10 +315,21 @@ meta_kms_plane_new (MetaKmsPlaneType         type,
   plane->device = meta_kms_impl_device_get_device (impl_device);
 
   init_rotations (plane, impl_device, drm_plane_props);
+  init_formats (plane, impl_device, drm_plane_props);
 
   return plane;
 }
 
+static void
+meta_kms_plane_finalize (GObject *object)
+{
+  MetaKmsPlane *plane = META_KMS_PLANE (object);
+
+  g_hash_table_destroy (plane->formats_modifiers);
+
+  G_OBJECT_CLASS (meta_kms_plane_parent_class)->finalize (object);
+}
+
 static void
 meta_kms_plane_init (MetaKmsPlane *plane)
 {
@@ -159,4 +338,7 @@ meta_kms_plane_init (MetaKmsPlane *plane)
 static void
 meta_kms_plane_class_init (MetaKmsPlaneClass *klass)
 {
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = meta_kms_plane_finalize;
 }
diff --git a/src/backends/native/meta-kms-plane.h b/src/backends/native/meta-kms-plane.h
index 76020d8d9..11cb3ad2f 100644
--- a/src/backends/native/meta-kms-plane.h
+++ b/src/backends/native/meta-kms-plane.h
@@ -43,11 +43,21 @@ MetaKmsPlane * meta_kms_plane_new (MetaKmsPlaneType         type,
                                    drmModePlane            *drm_plane,
                                    drmModeObjectProperties *drm_plane_props);
 
+uint32_t meta_kms_plane_get_id (MetaKmsPlane *plane);
+
 MetaKmsPlaneType meta_kms_plane_get_plane_type (MetaKmsPlane *plane);
 
 gboolean meta_kms_plane_is_transform_handled (MetaKmsPlane         *plane,
                                               MetaMonitorTransform  transform);
 
+GArray * meta_kms_plane_get_modifiers_for_format (MetaKmsPlane *plane,
+                                                  uint32_t      format);
+
+GArray * meta_kms_plane_copy_drm_format_list (MetaKmsPlane *plane);
+
+gboolean meta_kms_plane_is_format_supported (MetaKmsPlane *plane,
+                                             uint32_t      format);
+
 gboolean meta_kms_plane_is_usable_with (MetaKmsPlane *plane,
                                         MetaKmsCrtc  *crtc);
 
diff --git a/src/backends/native/meta-kms-types.h b/src/backends/native/meta-kms-types.h
index d8d099626..7a9264934 100644
--- a/src/backends/native/meta-kms-types.h
+++ b/src/backends/native/meta-kms-types.h
@@ -23,6 +23,7 @@
 typedef struct _MetaKms MetaKms;
 typedef struct _MetaKmsDevice MetaKmsDevice;
 
+typedef struct _MetaKmsPlane MetaKmsPlane;
 typedef struct _MetaKmsCrtc MetaKmsCrtc;
 typedef struct _MetaKmsConnector MetaKmsConnector;
 


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