summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stone <daniels@collabora.com>2017-08-03 13:42:15 +0100
committerJonas Ã…dahl <jadahl@gmail.com>2018-01-24 11:33:40 +0800
commitd670a1aa78ff67358b483e411528df6ec466727b (patch)
tree554209d316ecdafa698b8924c70a1e2f1ff17c0a
parent76b396846d987e7214d241fad04e59caa53ecbb7 (diff)
downloadmutter-d670a1aa78ff67358b483e411528df6ec466727b.tar.gz
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
-rw-r--r--configure.ac2
-rw-r--r--src/backends/native/meta-crtc-kms.c104
2 files changed, 104 insertions, 2 deletions
diff --git a/configure.ac b/configure.ac
index 44b84da78..42348146c 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 492734e30..8152991ee 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);
}