Backport linux-dmabuf v4 support

Resolves: https://issues.redhat.com/browse/RHEL-129832
This commit is contained in:
Olivier Fourdan 2025-11-20 17:34:53 +01:00
parent 514647f182
commit b8d17ac25e
19 changed files with 2691 additions and 2 deletions

View File

@ -0,0 +1,80 @@
From 0e6889f3ad3e417b29c5ea29fe6dfe485e5f6218 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Wed, 4 Aug 2021 09:59:50 +0200
Subject: [PATCH 01/18] egl: Add eglQueryDisplayAttribEXT() helper
To be used to fetch the EGLDevice used for an EGL display.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1959>
(cherry picked from commit 7ce481bf6996b2d99314311bf68afc6bd703c480)
---
src/backends/meta-egl.c | 23 +++++++++++++++++++++++
src/backends/meta-egl.h | 6 ++++++
2 files changed, 29 insertions(+)
diff --git a/src/backends/meta-egl.c b/src/backends/meta-egl.c
index fdeff4f779..c2777271ff 100644
--- a/src/backends/meta-egl.c
+++ b/src/backends/meta-egl.c
@@ -71,6 +71,8 @@ struct _MetaEgl
PFNEGLQUERYDMABUFFORMATSEXTPROC eglQueryDmaBufFormatsEXT;
PFNEGLQUERYDMABUFMODIFIERSEXTPROC eglQueryDmaBufModifiersEXT;
+
+ PFNEGLQUERYDISPLAYATTRIBEXTPROC eglQueryDisplayAttribEXT;
};
G_DEFINE_TYPE (MetaEgl, meta_egl, G_TYPE_OBJECT)
@@ -1064,6 +1066,25 @@ meta_egl_query_dma_buf_modifiers (MetaEgl *egl,
return TRUE;
}
+gboolean
+meta_egl_query_display_attrib (MetaEgl *egl,
+ EGLDisplay display,
+ EGLint attribute,
+ EGLAttrib *value,
+ GError **error)
+{
+ if (!is_egl_proc_valid (egl->eglQueryDisplayAttribEXT, error))
+ return FALSE;
+
+ if (!egl->eglQueryDisplayAttribEXT (display, attribute, value))
+ {
+ set_egl_error (error);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
#define GET_EGL_PROC_ADDR(proc) \
egl->proc = (void *) eglGetProcAddress (#proc);
@@ -1102,6 +1123,8 @@ meta_egl_constructed (GObject *object)
GET_EGL_PROC_ADDR (eglQueryDmaBufFormatsEXT);
GET_EGL_PROC_ADDR (eglQueryDmaBufModifiersEXT);
+
+ GET_EGL_PROC_ADDR (eglQueryDisplayAttribEXT);
}
#undef GET_EGL_PROC_ADDR
diff --git a/src/backends/meta-egl.h b/src/backends/meta-egl.h
index 4591e7d853..5c0aacd520 100644
--- a/src/backends/meta-egl.h
+++ b/src/backends/meta-egl.h
@@ -260,4 +260,10 @@ gboolean meta_egl_query_dma_buf_modifiers (MetaEgl *egl,
EGLint *num_formats,
GError **error);
+gboolean meta_egl_query_display_attrib (MetaEgl *egl,
+ EGLDisplay display,
+ EGLint attribute,
+ EGLAttrib *value,
+ GError **error);
+
#endif /* META_EGL_H */
--
2.51.1

View File

@ -0,0 +1,217 @@
From bc73828642ed3ba6e7bee5ee8e8c83f8f15b1e14 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Wed, 4 Aug 2021 10:12:33 +0200
Subject: [PATCH 02/18] wayland/dma-buf: Add manager struct
It'll be used to store state related to DMA buffer Wayland support.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1959>
(cherry picked from commit 51308a9d78ba712a9a25438e257c430d517f35ac)
---
src/wayland/meta-wayland-dma-buf.c | 49 ++++++++++++++++++++++--------
src/wayland/meta-wayland-dma-buf.h | 5 ++-
src/wayland/meta-wayland-private.h | 1 +
src/wayland/meta-wayland-types.h | 2 ++
src/wayland/meta-wayland.c | 28 ++++++++++++++++-
5 files changed, 71 insertions(+), 14 deletions(-)
diff --git a/src/wayland/meta-wayland-dma-buf.c b/src/wayland/meta-wayland-dma-buf.c
index 230b13bc8a..0803a942db 100644
--- a/src/wayland/meta-wayland-dma-buf.c
+++ b/src/wayland/meta-wayland-dma-buf.c
@@ -66,6 +66,11 @@
#define META_WAYLAND_DMA_BUF_MAX_FDS 4
+struct _MetaWaylandDmaBufManager
+{
+ MetaWaylandCompositor *compositor;
+};
+
struct _MetaWaylandDmaBufBuffer
{
GObject parent;
@@ -696,17 +701,17 @@ send_modifiers (struct wl_resource *resource,
static void
dma_buf_bind (struct wl_client *client,
- void *data,
+ void *user_data,
uint32_t version,
uint32_t id)
{
- MetaWaylandCompositor *compositor = data;
+ MetaWaylandDmaBufManager *dma_buf_manager = user_data;
struct wl_resource *resource;
resource = wl_resource_create (client, &zwp_linux_dmabuf_v1_interface,
version, id);
wl_resource_set_implementation (resource, &dma_buf_implementation,
- compositor, NULL);
+ dma_buf_manager, NULL);
send_modifiers (resource, DRM_FORMAT_ARGB8888);
send_modifiers (resource, DRM_FORMAT_ABGR8888);
send_modifiers (resource, DRM_FORMAT_XRGB8888);
@@ -722,38 +727,58 @@ dma_buf_bind (struct wl_client *client,
}
/**
- * meta_wayland_dma_buf_init:
+ * meta_wayland_dma_buf_manager_new:
* @compositor: The #MetaWaylandCompositor
*
* Creates the global Wayland object that exposes the linux-dmabuf protocol.
*
- * Returns: Whether the initialization was successful. If this is %FALSE,
- * clients won't be able to use the linux-dmabuf protocol to pass buffers.
+ * Returns: (transfer full): The MetaWaylandDmaBufManager instance.
*/
-gboolean
-meta_wayland_dma_buf_init (MetaWaylandCompositor *compositor)
+MetaWaylandDmaBufManager *
+meta_wayland_dma_buf_manager_new (MetaWaylandCompositor *compositor,
+ GError **error)
{
MetaBackend *backend = meta_get_backend ();
MetaEgl *egl = meta_backend_get_egl (backend);
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context);
+ g_autoptr (GError) local_error = NULL;
+ g_autofree MetaWaylandDmaBufManager *dma_buf_manager = NULL;
g_assert (backend && egl && clutter_backend && cogl_context && egl_display);
if (!meta_egl_has_extensions (egl, egl_display, NULL,
"EGL_EXT_image_dma_buf_import_modifiers",
NULL))
- return FALSE;
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ "Missing 'EGL_EXT_image_dma_buf_import_modifiers'");
+ return NULL;
+ }
+
+ dma_buf_manager = g_new0 (MetaWaylandDmaBufManager, 1);
if (!wl_global_create (compositor->wayland_display,
&zwp_linux_dmabuf_v1_interface,
META_ZWP_LINUX_DMABUF_V1_VERSION,
- compositor,
+ dma_buf_manager,
dma_buf_bind))
- return FALSE;
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Failed to create zwp_linux_dmabuf_v1 global");
+ return NULL;
+ }
- return TRUE;
+ dma_buf_manager->compositor = compositor;
+
+ return g_steal_pointer (&dma_buf_manager);
+}
+
+void
+meta_wayland_dma_buf_manager_free (MetaWaylandDmaBufManager *dma_buf_manager)
+{
+ g_free (dma_buf_manager);
}
static void
diff --git a/src/wayland/meta-wayland-dma-buf.h b/src/wayland/meta-wayland-dma-buf.h
index cdc65aeb5b..72fd0b16a0 100644
--- a/src/wayland/meta-wayland-dma-buf.h
+++ b/src/wayland/meta-wayland-dma-buf.h
@@ -39,7 +39,10 @@ G_DECLARE_FINAL_TYPE (MetaWaylandDmaBufBuffer, meta_wayland_dma_buf_buffer,
typedef struct _MetaWaylandDmaBufBuffer MetaWaylandDmaBufBuffer;
-gboolean meta_wayland_dma_buf_init (MetaWaylandCompositor *compositor);
+MetaWaylandDmaBufManager * meta_wayland_dma_buf_manager_new (MetaWaylandCompositor *compositor,
+ GError **error);
+
+void meta_wayland_dma_buf_manager_free (MetaWaylandDmaBufManager *dma_buf_manager);
gboolean
meta_wayland_dma_buf_buffer_attach (MetaWaylandBuffer *buffer,
diff --git a/src/wayland/meta-wayland-private.h b/src/wayland/meta-wayland-private.h
index 3306c192c9..3a2724256f 100644
--- a/src/wayland/meta-wayland-private.h
+++ b/src/wayland/meta-wayland-private.h
@@ -97,6 +97,7 @@ struct _MetaWaylandCompositor
GHashTable *scheduled_surface_associations;
MetaWaylandPresentationTime presentation_time;
+ MetaWaylandDmaBufManager *dma_buf_manager;
};
#define META_TYPE_WAYLAND_COMPOSITOR (meta_wayland_compositor_get_type ())
diff --git a/src/wayland/meta-wayland-types.h b/src/wayland/meta-wayland-types.h
index 00712ad1f1..8ad9084827 100644
--- a/src/wayland/meta-wayland-types.h
+++ b/src/wayland/meta-wayland-types.h
@@ -61,4 +61,6 @@ typedef struct _MetaWaylandWindowConfiguration MetaWaylandWindowConfiguration;
typedef struct _MetaWaylandPointerClient MetaWaylandPointerClient;
+typedef struct _MetaWaylandDmaBufManager MetaWaylandDmaBufManager;
+
#endif
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index 8f16aa429d..a566a35449 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -454,6 +454,29 @@ meta_wayland_get_xwayland_auth_file (MetaWaylandCompositor *compositor)
return compositor->xwayland_manager.auth_file;
}
+static void
+init_dma_buf_support (MetaWaylandCompositor *compositor)
+{
+ g_autoptr (GError) error = NULL;
+
+ compositor->dma_buf_manager = meta_wayland_dma_buf_manager_new (compositor,
+ &error);
+ if (!compositor->dma_buf_manager)
+ {
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
+ {
+ meta_topic (META_DEBUG_WAYLAND,
+ "Wayland DMA buffer protocol support not enabled: %s",
+ error->message);
+ }
+ else
+ {
+ g_warning ("Wayland DMA buffer protocol support not enabled: %s",
+ error->message);
+ }
+ }
+}
+
MetaWaylandCompositor *
meta_wayland_compositor_new (MetaBackend *backend)
{
@@ -507,7 +530,7 @@ meta_wayland_compositor_setup (MetaWaylandCompositor *compositor)
meta_wayland_relative_pointer_init (compositor);
meta_wayland_pointer_constraints_init (compositor);
meta_wayland_xdg_foreign_init (compositor);
- meta_wayland_dma_buf_init (compositor);
+ init_dma_buf_support (compositor);
meta_wayland_keyboard_shortcuts_inhibit_init (compositor);
meta_wayland_surface_inhibit_shortcuts_dialog_init ();
meta_wayland_text_input_init (compositor);
@@ -595,6 +618,9 @@ meta_wayland_finalize (void)
if (compositor->wayland_display)
wl_display_destroy_clients (compositor->wayland_display);
+ g_clear_pointer (&compositor->dma_buf_manager,
+ meta_wayland_dma_buf_manager_free);
+
g_clear_pointer (&compositor->seat, meta_wayland_seat_free);
g_clear_pointer (&compositor->display_name, g_free);
--
2.51.1

View File

@ -0,0 +1,261 @@
From cf495636abdee738c59aa854cd16c172048bbf72 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Wed, 4 Aug 2021 10:17:15 +0200
Subject: [PATCH 03/18] wayland/dma-buf: Prepare format/modifier map up front
As the format table is setup up front, it doesn't change when this
experimental feature setting change. Make the settings documentation
reflect that.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1959>
(cherry picked from commit 1978e93f285222e10ac6d5a25de5f90d061ec228)
---
data/org.gnome.mutter.gschema.xml.in | 5 +
src/wayland/meta-wayland-dma-buf.c | 166 ++++++++++++++++-----------
2 files changed, 106 insertions(+), 65 deletions(-)
diff --git a/data/org.gnome.mutter.gschema.xml.in b/data/org.gnome.mutter.gschema.xml.in
index 23fa9f3ad3..4955f8d383 100644
--- a/data/org.gnome.mutter.gschema.xml.in
+++ b/data/org.gnome.mutter.gschema.xml.in
@@ -121,6 +121,11 @@
to manage HiDPI monitors. Does not
require a restart.
+ • “kms-modifiers” — makes mutter always advertise valid
+ buffer modifiers on Wayland. This is
+ currently not the case when using the
+ i915 driver. Requires a restart.
+
• “rt-scheduler” — makes mutter request a low priority
real-time scheduling. The executable
or user must have CAP_SYS_NICE.
diff --git a/src/wayland/meta-wayland-dma-buf.c b/src/wayland/meta-wayland-dma-buf.c
index 0803a942db..d9338ae474 100644
--- a/src/wayland/meta-wayland-dma-buf.c
+++ b/src/wayland/meta-wayland-dma-buf.c
@@ -66,9 +66,17 @@
#define META_WAYLAND_DMA_BUF_MAX_FDS 4
+typedef struct _MetaWaylandDmaBufFormat
+{
+ uint32_t drm_format;
+ uint64_t drm_modifier;
+} MetaWaylandDmaBufFormat;
+
struct _MetaWaylandDmaBufManager
{
MetaWaylandCompositor *compositor;
+
+ GArray *formats;
};
struct _MetaWaylandDmaBufBuffer
@@ -633,97 +641,122 @@ should_send_modifiers (MetaBackend *backend)
}
static void
-send_modifiers (struct wl_resource *resource,
- uint32_t format)
+send_modifiers (struct wl_resource *resource,
+ MetaWaylandDmaBufFormat *format)
+{
+ zwp_linux_dmabuf_v1_send_format (resource, format->drm_format);
+
+ if (wl_resource_get_version (resource) <
+ ZWP_LINUX_DMABUF_V1_MODIFIER_SINCE_VERSION)
+ return;
+
+ zwp_linux_dmabuf_v1_send_modifier (resource,
+ format->drm_format,
+ format->drm_modifier >> 32,
+ format->drm_modifier & 0xffffffff);
+}
+
+static void
+dma_buf_bind (struct wl_client *client,
+ void *user_data,
+ uint32_t version,
+ uint32_t id)
+{
+ MetaWaylandDmaBufManager *dma_buf_manager = user_data;
+ struct wl_resource *resource;
+ unsigned int i;
+
+ resource = wl_resource_create (client, &zwp_linux_dmabuf_v1_interface,
+ version, id);
+ wl_resource_set_implementation (resource, &dma_buf_implementation,
+ dma_buf_manager, NULL);
+
+
+ for (i = 0; i < dma_buf_manager->formats->len; i++)
+ {
+ MetaWaylandDmaBufFormat *format =
+ &g_array_index (dma_buf_manager->formats,
+ MetaWaylandDmaBufFormat,
+ i);
+
+ send_modifiers (resource, format);
+ }
+}
+
+static void
+add_format (MetaWaylandDmaBufManager *dma_buf_manager,
+ EGLDisplay egl_display,
+ uint32_t drm_format)
{
MetaBackend *backend = meta_get_backend ();
MetaEgl *egl = meta_backend_get_egl (backend);
- ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
- CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
- EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context);
EGLint num_modifiers;
- EGLuint64KHR *modifiers;
- GError *error = NULL;
- gboolean ret;
+ g_autofree EGLuint64KHR *modifiers = NULL;
+ g_autoptr (GError) error = NULL;
int i;
-
- zwp_linux_dmabuf_v1_send_format (resource, format);
-
- /* The modifier event was only added in v3; v1 and v2 only have the format
- * event. */
- if (wl_resource_get_version (resource) < ZWP_LINUX_DMABUF_V1_MODIFIER_SINCE_VERSION)
- return;
+ MetaWaylandDmaBufFormat format;
if (!should_send_modifiers (backend))
- {
- zwp_linux_dmabuf_v1_send_modifier (resource, format,
- DRM_FORMAT_MOD_INVALID >> 32,
- DRM_FORMAT_MOD_INVALID & 0xffffffff);
- return;
- }
+ goto add_fallback;
/* First query the number of available modifiers, then allocate an array,
* then fill the array. */
- ret = meta_egl_query_dma_buf_modifiers (egl, egl_display, format, 0, NULL,
- NULL, &num_modifiers, NULL);
- if (!ret)
- return;
+ if (!meta_egl_query_dma_buf_modifiers (egl, egl_display, drm_format, 0, NULL,
+ NULL, &num_modifiers, NULL))
+ goto add_fallback;
if (num_modifiers == 0)
- {
- zwp_linux_dmabuf_v1_send_modifier (resource, format,
- DRM_FORMAT_MOD_INVALID >> 32,
- DRM_FORMAT_MOD_INVALID & 0xffffffff);
- return;
- }
+ goto add_fallback;
modifiers = g_new0 (uint64_t, num_modifiers);
- ret = meta_egl_query_dma_buf_modifiers (egl, egl_display, format,
- num_modifiers, modifiers, NULL,
- &num_modifiers, &error);
- if (!ret)
+ if (!meta_egl_query_dma_buf_modifiers (egl, egl_display, drm_format,
+ num_modifiers, modifiers, NULL,
+ &num_modifiers, &error))
{
g_warning ("Failed to query modifiers for format 0x%" PRIu32 ": %s",
- format, error ? error->message : "unknown error");
- g_free (modifiers);
- return;
+ drm_format, error ? error->message : "unknown error");
+ goto add_fallback;
}
for (i = 0; i < num_modifiers; i++)
{
- zwp_linux_dmabuf_v1_send_modifier (resource, format,
- modifiers[i] >> 32,
- modifiers[i] & 0xffffffff);
+ format = (MetaWaylandDmaBufFormat) {
+ .drm_format = drm_format,
+ .drm_modifier = modifiers[i],
+ };
+ g_array_append_val (dma_buf_manager->formats, format);
}
- g_free (modifiers);
+ return;
+
+add_fallback:
+ format = (MetaWaylandDmaBufFormat) {
+ .drm_format = drm_format,
+ .drm_modifier = DRM_FORMAT_MOD_INVALID,
+ };
+ g_array_append_val (dma_buf_manager->formats, format);
}
static void
-dma_buf_bind (struct wl_client *client,
- void *user_data,
- uint32_t version,
- uint32_t id)
+init_formats (MetaWaylandDmaBufManager *dma_buf_manager,
+ EGLDisplay egl_display)
{
- MetaWaylandDmaBufManager *dma_buf_manager = user_data;
- struct wl_resource *resource;
-
- resource = wl_resource_create (client, &zwp_linux_dmabuf_v1_interface,
- version, id);
- wl_resource_set_implementation (resource, &dma_buf_implementation,
- dma_buf_manager, NULL);
- send_modifiers (resource, DRM_FORMAT_ARGB8888);
- send_modifiers (resource, DRM_FORMAT_ABGR8888);
- send_modifiers (resource, DRM_FORMAT_XRGB8888);
- send_modifiers (resource, DRM_FORMAT_XBGR8888);
- send_modifiers (resource, DRM_FORMAT_ARGB2101010);
- send_modifiers (resource, DRM_FORMAT_ABGR2101010);
- send_modifiers (resource, DRM_FORMAT_XRGB2101010);
- send_modifiers (resource, DRM_FORMAT_RGB565);
- send_modifiers (resource, DRM_FORMAT_ABGR16161616F);
- send_modifiers (resource, DRM_FORMAT_XBGR16161616F);
- send_modifiers (resource, DRM_FORMAT_XRGB16161616F);
- send_modifiers (resource, DRM_FORMAT_ARGB16161616F);
+ dma_buf_manager->formats = g_array_new (FALSE, FALSE,
+ sizeof (MetaWaylandDmaBufFormat));
+
+ add_format (dma_buf_manager, egl_display, DRM_FORMAT_ARGB8888);
+ add_format (dma_buf_manager, egl_display, DRM_FORMAT_ABGR8888);
+ add_format (dma_buf_manager, egl_display, DRM_FORMAT_XRGB8888);
+ add_format (dma_buf_manager, egl_display, DRM_FORMAT_XBGR8888);
+ add_format (dma_buf_manager, egl_display, DRM_FORMAT_ARGB2101010);
+ add_format (dma_buf_manager, egl_display, DRM_FORMAT_ABGR2101010);
+ add_format (dma_buf_manager, egl_display, DRM_FORMAT_XRGB2101010);
+ add_format (dma_buf_manager, egl_display, DRM_FORMAT_XBGR2101010);
+ add_format (dma_buf_manager, egl_display, DRM_FORMAT_RGB565);
+ add_format (dma_buf_manager, egl_display, DRM_FORMAT_ABGR16161616F);
+ add_format (dma_buf_manager, egl_display, DRM_FORMAT_XBGR16161616F);
+ add_format (dma_buf_manager, egl_display, DRM_FORMAT_XRGB16161616F);
+ add_format (dma_buf_manager, egl_display, DRM_FORMAT_ARGB16161616F);
}
/**
@@ -772,12 +805,15 @@ meta_wayland_dma_buf_manager_new (MetaWaylandCompositor *compositor,
dma_buf_manager->compositor = compositor;
+ init_formats (dma_buf_manager, egl_display);
+
return g_steal_pointer (&dma_buf_manager);
}
void
meta_wayland_dma_buf_manager_free (MetaWaylandDmaBufManager *dma_buf_manager)
{
+ g_clear_pointer (&dma_buf_manager->formats, g_array_unref);
g_free (dma_buf_manager);
}
--
2.51.1

View File

@ -0,0 +1,545 @@
From ed3c27feeb3b745d04ec462e82d8ae58e041338e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Thu, 5 Aug 2021 15:10:47 +0200
Subject: [PATCH 04/18] wayland/dma-buf: Add basic support for DMA buffer
feedback
This includes sending the default tranche, but so far only sends the
same for every surface feedback requested. Scanout tranche will be added
later.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1959>
(cherry picked from commit 7acecb1c7233dad0b9b314f59121882a518901d7)
---
meson.build | 2 +-
src/wayland/meta-wayland-dma-buf.c | 368 +++++++++++++++++++++++++++-
src/wayland/meta-wayland-versions.h | 1 -
3 files changed, 360 insertions(+), 11 deletions(-)
diff --git a/meson.build b/meson.build
index f6f3872394..2dbee750c3 100644
--- a/meson.build
+++ b/meson.build
@@ -41,7 +41,7 @@ gudev_req = '>= 232'
# wayland version requirements
wayland_server_req = '>= 1.18'
-wayland_protocols_req = '>= 1.19'
+wayland_protocols_req = '>= 1.24'
# native backend version requirements
libinput_req = '>= 1.15.0'
diff --git a/src/wayland/meta-wayland-dma-buf.c b/src/wayland/meta-wayland-dma-buf.c
index d9338ae474..7155d07dcf 100644
--- a/src/wayland/meta-wayland-dma-buf.c
+++ b/src/wayland/meta-wayland-dma-buf.c
@@ -40,6 +40,9 @@
#include "wayland/meta-wayland-dma-buf.h"
#include <drm_fourcc.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
#include "backends/meta-backend-private.h"
#include "backends/meta-egl-ext.h"
@@ -66,17 +69,41 @@
#define META_WAYLAND_DMA_BUF_MAX_FDS 4
+/* Compatible with zwp_linux_dmabuf_feedback_v1.tranche_flags */
+typedef enum _MetaWaylandDmaBufTrancheFlags
+{
+ META_WAYLAND_DMA_BUF_TRANCHE_FLAG_NONE = 0,
+ META_WAYLAND_DMA_BUF_TRANCHE_FLAG_SCANOUT = 1,
+} MetaWaylandDmaBufTrancheFlags;
+
typedef struct _MetaWaylandDmaBufFormat
{
uint32_t drm_format;
uint64_t drm_modifier;
+ uint16_t table_index;
} MetaWaylandDmaBufFormat;
+typedef struct _MetaWaylandDmaBufTranche
+{
+ dev_t target_device_id;
+ GArray *formats;
+ MetaWaylandDmaBufTrancheFlags flags;
+} MetaWaylandDmaBufTranche;
+
+typedef struct _MetaWaylandDmaBufFeedback
+{
+ dev_t main_device_id;
+ GList *tranches;
+} MetaWaylandDmaBufFeedback;
+
struct _MetaWaylandDmaBufManager
{
MetaWaylandCompositor *compositor;
+ dev_t main_device_id;
GArray *formats;
+ MetaAnonymousFile *format_table_file;
+ MetaWaylandDmaBufFeedback *default_feedback;
};
struct _MetaWaylandDmaBufBuffer
@@ -95,6 +122,118 @@ struct _MetaWaylandDmaBufBuffer
G_DEFINE_TYPE (MetaWaylandDmaBufBuffer, meta_wayland_dma_buf_buffer, G_TYPE_OBJECT);
+static MetaWaylandDmaBufTranche *
+meta_wayland_dma_buf_tranche_new (dev_t device_id,
+ GArray *formats,
+ MetaWaylandDmaBufTrancheFlags flags)
+{
+ MetaWaylandDmaBufTranche *tranche;
+
+ tranche = g_new0 (MetaWaylandDmaBufTranche, 1);
+ tranche->target_device_id = device_id;
+ tranche->formats = g_array_copy (formats);
+ tranche->flags = flags;
+
+ return tranche;
+}
+
+static void
+meta_wayland_dma_buf_tranche_free (MetaWaylandDmaBufTranche *tranche)
+{
+ g_clear_pointer (&tranche->formats, g_array_unref);
+ g_free (tranche);
+}
+
+static void
+meta_wayland_dma_buf_tranche_send (MetaWaylandDmaBufTranche *tranche,
+ struct wl_resource *resource)
+{
+ struct wl_array target_device_buf;
+ dev_t *device_id_ptr;
+ struct wl_array formats_array;
+ unsigned int i;
+
+ wl_array_init (&target_device_buf);
+ device_id_ptr = wl_array_add (&target_device_buf, sizeof (*device_id_ptr));
+ *device_id_ptr = tranche->target_device_id;
+ zwp_linux_dmabuf_feedback_v1_send_tranche_target_device (resource,
+ &target_device_buf);
+ wl_array_release (&target_device_buf);
+ zwp_linux_dmabuf_feedback_v1_send_tranche_flags (resource, tranche->flags);
+
+ wl_array_init (&formats_array);
+ for (i = 0; i < tranche->formats->len; i++)
+ {
+ MetaWaylandDmaBufFormat *format =
+ &g_array_index (tranche->formats,
+ MetaWaylandDmaBufFormat,
+ i);
+ uint16_t *format_index_ptr;
+
+ format_index_ptr = wl_array_add (&formats_array,
+ sizeof (*format_index_ptr));
+ *format_index_ptr = format->table_index;
+ }
+ zwp_linux_dmabuf_feedback_v1_send_tranche_formats (resource, &formats_array);
+ wl_array_release (&formats_array);
+
+ zwp_linux_dmabuf_feedback_v1_send_tranche_done (resource);
+}
+
+static void
+meta_wayland_dma_buf_feedback_send (MetaWaylandDmaBufFeedback *feedback,
+ MetaWaylandDmaBufManager *dma_buf_manager,
+ struct wl_resource *resource)
+{
+ size_t size;
+ int fd;
+ struct wl_array main_device_buf;
+ dev_t *device_id_ptr;
+
+ fd = meta_anonymous_file_open_fd (dma_buf_manager->format_table_file,
+ META_ANONYMOUS_FILE_MAPMODE_PRIVATE);
+ size = meta_anonymous_file_size (dma_buf_manager->format_table_file);
+ zwp_linux_dmabuf_feedback_v1_send_format_table (resource, fd, size);
+ meta_anonymous_file_close_fd (fd);
+
+ wl_array_init (&main_device_buf);
+ device_id_ptr = wl_array_add (&main_device_buf, sizeof (*device_id_ptr));
+ *device_id_ptr = feedback->main_device_id;
+ zwp_linux_dmabuf_feedback_v1_send_main_device (resource, &main_device_buf);
+
+ g_list_foreach (feedback->tranches,
+ (GFunc) meta_wayland_dma_buf_tranche_send,
+ resource);
+
+ zwp_linux_dmabuf_feedback_v1_send_done (resource);
+}
+
+static void
+meta_wayland_dma_buf_feedback_add_tranche (MetaWaylandDmaBufFeedback *feedback,
+ MetaWaylandDmaBufTranche *tranche)
+{
+ feedback->tranches = g_list_append (feedback->tranches, tranche);
+}
+
+static MetaWaylandDmaBufFeedback *
+meta_wayland_dma_buf_feedback_new (dev_t device_id)
+{
+ MetaWaylandDmaBufFeedback *feedback;
+
+ feedback = g_new0 (MetaWaylandDmaBufFeedback, 1);
+ feedback->main_device_id = device_id;
+
+ return feedback;
+}
+
+static void
+meta_wayland_dma_buf_feedback_free (MetaWaylandDmaBufFeedback *feedback)
+{
+ g_clear_list (&feedback->tranches,
+ (GDestroyNotify) meta_wayland_dma_buf_tranche_free);
+ g_free (feedback);
+}
+
static gboolean
meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer,
GError **error)
@@ -616,10 +755,80 @@ dma_buf_handle_create_buffer_params (struct wl_client *client,
buffer_params_destructor);
}
+static void
+feedback_destroy (struct wl_client *client,
+ struct wl_resource *resource)
+{
+ wl_resource_destroy (resource);
+}
+
+static const struct zwp_linux_dmabuf_feedback_v1_interface feedback_implementation =
+{
+ feedback_destroy,
+};
+
+static void
+feedback_destructor (struct wl_resource *resource)
+{
+}
+
+static void
+dma_buf_handle_get_default_feedback (struct wl_client *client,
+ struct wl_resource *dma_buf_resource,
+ uint32_t feedback_id)
+{
+ MetaWaylandDmaBufManager *dma_buf_manager =
+ wl_resource_get_user_data (dma_buf_resource);
+ struct wl_resource *feedback_resource;
+
+ feedback_resource =
+ wl_resource_create (client,
+ &zwp_linux_dmabuf_feedback_v1_interface,
+ wl_resource_get_version (dma_buf_resource),
+ feedback_id);
+
+ wl_resource_set_implementation (feedback_resource,
+ &feedback_implementation,
+ NULL,
+ feedback_destructor);
+
+ meta_wayland_dma_buf_feedback_send (dma_buf_manager->default_feedback,
+ dma_buf_manager,
+ feedback_resource);
+}
+
+static void
+dma_buf_handle_get_surface_feedback (struct wl_client *client,
+ struct wl_resource *dma_buf_resource,
+ uint32_t feedback_id,
+ struct wl_resource *surface_resource)
+{
+ MetaWaylandDmaBufManager *dma_buf_manager =
+ wl_resource_get_user_data (dma_buf_resource);
+ struct wl_resource *feedback_resource;
+
+ feedback_resource =
+ wl_resource_create (client,
+ &zwp_linux_dmabuf_feedback_v1_interface,
+ wl_resource_get_version (dma_buf_resource),
+ feedback_id);
+
+ wl_resource_set_implementation (feedback_resource,
+ &feedback_implementation,
+ NULL,
+ feedback_destructor);
+
+ meta_wayland_dma_buf_feedback_send (dma_buf_manager->default_feedback,
+ dma_buf_manager,
+ feedback_resource);
+}
+
static const struct zwp_linux_dmabuf_v1_interface dma_buf_implementation =
{
dma_buf_handle_destroy,
dma_buf_handle_create_buffer_params,
+ dma_buf_handle_get_default_feedback,
+ dma_buf_handle_get_surface_feedback,
};
static gboolean
@@ -644,6 +853,9 @@ static void
send_modifiers (struct wl_resource *resource,
MetaWaylandDmaBufFormat *format)
{
+ g_assert (wl_resource_get_version (resource) <
+ ZWP_LINUX_DMABUF_V1_GET_DEFAULT_FEEDBACK_SINCE_VERSION);
+
zwp_linux_dmabuf_v1_send_format (resource, format->drm_format);
if (wl_resource_get_version (resource) <
@@ -664,22 +876,25 @@ dma_buf_bind (struct wl_client *client,
{
MetaWaylandDmaBufManager *dma_buf_manager = user_data;
struct wl_resource *resource;
- unsigned int i;
resource = wl_resource_create (client, &zwp_linux_dmabuf_v1_interface,
version, id);
wl_resource_set_implementation (resource, &dma_buf_implementation,
dma_buf_manager, NULL);
-
- for (i = 0; i < dma_buf_manager->formats->len; i++)
+ if (version < ZWP_LINUX_DMABUF_V1_GET_DEFAULT_FEEDBACK_SINCE_VERSION)
{
- MetaWaylandDmaBufFormat *format =
- &g_array_index (dma_buf_manager->formats,
- MetaWaylandDmaBufFormat,
- i);
+ unsigned int i;
+
+ for (i = 0; i < dma_buf_manager->formats->len; i++)
+ {
+ MetaWaylandDmaBufFormat *format =
+ &g_array_index (dma_buf_manager->formats,
+ MetaWaylandDmaBufFormat,
+ i);
- send_modifiers (resource, format);
+ send_modifiers (resource, format);
+ }
}
}
@@ -723,6 +938,7 @@ add_format (MetaWaylandDmaBufManager *dma_buf_manager,
format = (MetaWaylandDmaBufFormat) {
.drm_format = drm_format,
.drm_modifier = modifiers[i],
+ .table_index = dma_buf_manager->formats->len,
};
g_array_append_val (dma_buf_manager->formats, format);
}
@@ -733,10 +949,53 @@ add_fallback:
format = (MetaWaylandDmaBufFormat) {
.drm_format = drm_format,
.drm_modifier = DRM_FORMAT_MOD_INVALID,
+ .table_index = dma_buf_manager->formats->len,
};
g_array_append_val (dma_buf_manager->formats, format);
}
+/*
+ * This is the structure the data is expected to have in the shared memory file
+ * shared with clients, according to the Wayland Linux DMA buffer protocol.
+ * It's structured as 16 bytes (128 bits) per entry, where each entry consists
+ * of the following:
+ *
+ * [ 32 bit format ][ 32 bit padding ][ 64 bit modifier ]
+ */
+typedef struct _MetaMetaWaylanDmaBdufFormatEntry
+{
+ uint32_t drm_format;
+ uint32_t unused_padding;
+ uint64_t drm_modifier;
+} MetaWaylandDmaBufFormatEntry;
+
+G_STATIC_ASSERT (sizeof (MetaWaylandDmaBufFormatEntry) == 16);
+G_STATIC_ASSERT (offsetof (MetaWaylandDmaBufFormatEntry, drm_format) == 0);
+G_STATIC_ASSERT (offsetof (MetaWaylandDmaBufFormatEntry, drm_modifier) == 8);
+
+static void
+init_format_table (MetaWaylandDmaBufManager *dma_buf_manager)
+{
+ g_autofree MetaWaylandDmaBufFormatEntry *format_table = NULL;
+ size_t size;
+ int i;
+
+ size = sizeof (MetaWaylandDmaBufFormatEntry) * dma_buf_manager->formats->len;
+ format_table = g_malloc0 (size);
+
+ for (i = 0; i < dma_buf_manager->formats->len; i++)
+ {
+ MetaWaylandDmaBufFormat *format =
+ &g_array_index (dma_buf_manager->formats, MetaWaylandDmaBufFormat, i);
+
+ format_table[i].drm_format = format->drm_format;
+ format_table[i].drm_modifier = format->drm_modifier;
+ }
+
+ dma_buf_manager->format_table_file =
+ meta_anonymous_file_new (size, (uint8_t *) format_table);
+}
+
static void
init_formats (MetaWaylandDmaBufManager *dma_buf_manager,
EGLDisplay egl_display)
@@ -757,6 +1016,25 @@ init_formats (MetaWaylandDmaBufManager *dma_buf_manager,
add_format (dma_buf_manager, egl_display, DRM_FORMAT_XBGR16161616F);
add_format (dma_buf_manager, egl_display, DRM_FORMAT_XRGB16161616F);
add_format (dma_buf_manager, egl_display, DRM_FORMAT_ARGB16161616F);
+
+ init_format_table (dma_buf_manager);
+}
+
+static void
+init_default_feedback (MetaWaylandDmaBufManager *dma_buf_manager)
+{
+ MetaWaylandDmaBufTrancheFlags flags;
+ MetaWaylandDmaBufTranche *tranche;
+
+ dma_buf_manager->default_feedback =
+ meta_wayland_dma_buf_feedback_new (dma_buf_manager->main_device_id);
+
+ flags = META_WAYLAND_DMA_BUF_TRANCHE_FLAG_NONE;
+ tranche = meta_wayland_dma_buf_tranche_new (dma_buf_manager->main_device_id,
+ dma_buf_manager->formats,
+ flags);
+ meta_wayland_dma_buf_feedback_add_tranche (dma_buf_manager->default_feedback,
+ tranche);
}
/**
@@ -776,8 +1054,14 @@ meta_wayland_dma_buf_manager_new (MetaWaylandCompositor *compositor,
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context);
+ dev_t device_id = 0;
+ int protocol_version;
+ EGLDeviceEXT egl_device;
+ EGLAttrib attrib;
g_autoptr (GError) local_error = NULL;
g_autofree MetaWaylandDmaBufManager *dma_buf_manager = NULL;
+ const char *device_path = NULL;
+ struct stat device_stat;
g_assert (backend && egl && clutter_backend && cogl_context && egl_display);
@@ -790,11 +1074,71 @@ meta_wayland_dma_buf_manager_new (MetaWaylandCompositor *compositor,
return NULL;
}
+ if (!meta_egl_query_display_attrib (egl, egl_display,
+ EGL_DEVICE_EXT, &attrib,
+ &local_error))
+ {
+ g_warning ("Failed to query EGL device from primary EGL display: %s",
+ local_error->message);
+ protocol_version = 3;
+ goto initialize;
+ }
+ egl_device = (EGLDeviceEXT) attrib;
+
+ if (meta_egl_egl_device_has_extensions (egl, egl_device, NULL,
+ "EGL_EXT_device_drm_render_node",
+ NULL))
+ {
+ device_path = meta_egl_query_device_string (egl, egl_device,
+ EGL_DRM_RENDER_NODE_FILE_EXT,
+ &local_error);
+ }
+ else if (meta_egl_egl_device_has_extensions (egl, egl_device, NULL,
+ "EGL_EXT_device_drm",
+ NULL))
+ {
+ device_path = meta_egl_query_device_string (egl, egl_device,
+ EGL_DRM_DEVICE_FILE_EXT,
+ &local_error);
+ }
+ else
+ {
+ meta_topic (META_DEBUG_WAYLAND,
+ "Only advertising zwp_linux_dmabuf_v1 interface version 3 "
+ "support, missing 'EGL_EXT_device_drm' and "
+ "'EGL_EXT_device_drm_render_node'");
+ protocol_version = 3;
+ goto initialize;
+ }
+
+ if (!device_path)
+ {
+ g_warning ("Failed to query EGL device path: %s",
+ local_error->message);
+ protocol_version = 3;
+ goto initialize;
+ }
+
+ if (stat (device_path, &device_stat) != 0)
+ {
+ g_warning ("Failed to fetch device file ID for '%s': %s",
+ device_path,
+ g_strerror (errno));
+ protocol_version = 3;
+ goto initialize;
+ }
+
+ device_id = device_stat.st_rdev;
+
+ protocol_version = 4;
+
+initialize:
+
dma_buf_manager = g_new0 (MetaWaylandDmaBufManager, 1);
if (!wl_global_create (compositor->wayland_display,
&zwp_linux_dmabuf_v1_interface,
- META_ZWP_LINUX_DMABUF_V1_VERSION,
+ protocol_version,
dma_buf_manager,
dma_buf_bind))
{
@@ -804,8 +1148,10 @@ meta_wayland_dma_buf_manager_new (MetaWaylandCompositor *compositor,
}
dma_buf_manager->compositor = compositor;
+ dma_buf_manager->main_device_id = device_id;
init_formats (dma_buf_manager, egl_display);
+ init_default_feedback (dma_buf_manager);
return g_steal_pointer (&dma_buf_manager);
}
@@ -813,7 +1159,11 @@ meta_wayland_dma_buf_manager_new (MetaWaylandCompositor *compositor,
void
meta_wayland_dma_buf_manager_free (MetaWaylandDmaBufManager *dma_buf_manager)
{
+ g_clear_pointer (&dma_buf_manager->format_table_file,
+ meta_anonymous_file_free);
g_clear_pointer (&dma_buf_manager->formats, g_array_unref);
+ g_clear_pointer (&dma_buf_manager->default_feedback,
+ meta_wayland_dma_buf_feedback_free);
g_free (dma_buf_manager);
}
diff --git a/src/wayland/meta-wayland-versions.h b/src/wayland/meta-wayland-versions.h
index 8f71c19dce..78e4e6127a 100644
--- a/src/wayland/meta-wayland-versions.h
+++ b/src/wayland/meta-wayland-versions.h
@@ -48,7 +48,6 @@
#define META_ZWP_POINTER_GESTURES_V1_VERSION 1
#define META_ZXDG_EXPORTER_V1_VERSION 1
#define META_ZXDG_IMPORTER_V1_VERSION 1
-#define META_ZWP_LINUX_DMABUF_V1_VERSION 3
#define META_ZWP_KEYBOARD_SHORTCUTS_INHIBIT_V1_VERSION 1
#define META_ZXDG_OUTPUT_V1_VERSION 3
#define META_ZWP_XWAYLAND_KEYBOARD_GRAB_V1_VERSION 1
--
2.51.1

View File

@ -0,0 +1,72 @@
From e4d494916c1045dd24ae44a82c8e398feed2179d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Tue, 7 Dec 2021 22:12:57 +0100
Subject: [PATCH 05/18] wayland/dma-buf: Always advertise non-modifier fallback
This is done to explicitly tell clients that the compositor supports
implicit modifier paths (i.e. using modifier unaware API).
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1959>
(cherry picked from commit 2a16a750c556a916a6792adf10adbe4499d5e092)
---
src/wayland/meta-wayland-dma-buf.c | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/src/wayland/meta-wayland-dma-buf.c b/src/wayland/meta-wayland-dma-buf.c
index 7155d07dcf..ca9be5d601 100644
--- a/src/wayland/meta-wayland-dma-buf.c
+++ b/src/wayland/meta-wayland-dma-buf.c
@@ -851,12 +851,18 @@ should_send_modifiers (MetaBackend *backend)
static void
send_modifiers (struct wl_resource *resource,
- MetaWaylandDmaBufFormat *format)
+ MetaWaylandDmaBufFormat *format,
+ GHashTable *sent_formats)
{
g_assert (wl_resource_get_version (resource) <
ZWP_LINUX_DMABUF_V1_GET_DEFAULT_FEEDBACK_SINCE_VERSION);
- zwp_linux_dmabuf_v1_send_format (resource, format->drm_format);
+ if (!g_hash_table_contains (sent_formats,
+ GUINT_TO_POINTER (format->drm_format)))
+ {
+ g_hash_table_add (sent_formats, GUINT_TO_POINTER (format->drm_format));
+ zwp_linux_dmabuf_v1_send_format (resource, format->drm_format);
+ }
if (wl_resource_get_version (resource) <
ZWP_LINUX_DMABUF_V1_MODIFIER_SINCE_VERSION)
@@ -884,8 +890,11 @@ dma_buf_bind (struct wl_client *client,
if (version < ZWP_LINUX_DMABUF_V1_GET_DEFAULT_FEEDBACK_SINCE_VERSION)
{
+ g_autoptr (GHashTable) sent_formats = NULL;
unsigned int i;
+ sent_formats = g_hash_table_new (NULL, NULL);
+
for (i = 0; i < dma_buf_manager->formats->len; i++)
{
MetaWaylandDmaBufFormat *format =
@@ -893,7 +902,7 @@ dma_buf_bind (struct wl_client *client,
MetaWaylandDmaBufFormat,
i);
- send_modifiers (resource, format);
+ send_modifiers (resource, format, sent_formats);
}
}
}
@@ -943,8 +952,6 @@ add_format (MetaWaylandDmaBufManager *dma_buf_manager,
g_array_append_val (dma_buf_manager->formats, format);
}
- return;
-
add_fallback:
format = (MetaWaylandDmaBufFormat) {
.drm_format = drm_format,
--
2.51.1

View File

@ -0,0 +1,98 @@
From 15168d00affa1e05fd1307abef196b6e395a14bb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Thu, 5 Aug 2021 16:03:26 +0200
Subject: [PATCH 06/18] wayland/surface: Remove unnecessary NULL check
This check has caused repeated confusion, as there are no current code
paths where this can ever end up in the true-branch.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1959>
(cherry picked from commit 90076cf268bde6c18e49908514d7dc7af4b3a92e)
---
src/wayland/meta-wayland-surface.c | 28 ----------------------------
1 file changed, 28 deletions(-)
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index 6e6457b249..e033b7b911 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -1027,10 +1027,6 @@ wl_surface_attach (struct wl_client *client,
MetaWaylandSurfaceState *pending = surface->pending_state;
MetaWaylandBuffer *buffer;
- /* X11 unmanaged window */
- if (!surface)
- return;
-
if (buffer_resource)
buffer = meta_wayland_buffer_from_resource (buffer_resource);
else
@@ -1068,10 +1064,6 @@ wl_surface_damage (struct wl_client *client,
MetaWaylandSurfaceState *pending = surface->pending_state;
cairo_rectangle_int_t rectangle;
- /* X11 unmanaged window */
- if (!surface)
- return;
-
rectangle = (cairo_rectangle_int_t) {
.x = x,
.y = y,
@@ -1100,10 +1092,6 @@ wl_surface_frame (struct wl_client *client,
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
MetaWaylandSurfaceState *pending = surface->pending_state;
- /* X11 unmanaged window */
- if (!surface)
- return;
-
callback = g_new0 (MetaWaylandFrameCallback, 1);
callback->surface = surface;
callback->resource = wl_resource_create (client,
@@ -1124,10 +1112,6 @@ wl_surface_set_opaque_region (struct wl_client *client,
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
MetaWaylandSurfaceState *pending = surface->pending_state;
- /* X11 unmanaged window */
- if (!surface)
- return;
-
g_clear_pointer (&pending->opaque_region, cairo_region_destroy);
if (region_resource)
{
@@ -1146,10 +1130,6 @@ wl_surface_set_input_region (struct wl_client *client,
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
MetaWaylandSurfaceState *pending = surface->pending_state;
- /* X11 unmanaged window */
- if (!surface)
- return;
-
g_clear_pointer (&pending->input_region, cairo_region_destroy);
if (region_resource)
{
@@ -1166,10 +1146,6 @@ wl_surface_commit (struct wl_client *client,
{
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
- /* X11 unmanaged window */
- if (!surface)
- return;
-
meta_wayland_surface_commit (surface);
}
@@ -1257,10 +1233,6 @@ wl_surface_damage_buffer (struct wl_client *client,
MetaWaylandSurfaceState *pending = surface->pending_state;
cairo_rectangle_int_t rectangle;
- /* X11 unmanaged window */
- if (!surface)
- return;
-
rectangle = (cairo_rectangle_int_t) {
.x = x,
.y = y,
--
2.51.1

View File

@ -0,0 +1,145 @@
From ba03e83acc2157fa96bb06784ca43d0da7e942ab Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Fri, 6 Aug 2021 15:23:15 +0200
Subject: [PATCH 07/18] wayland/dma-buf: Make manager object a GObject
Will make certain operations easier, i.e. setting up a GQuark.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1959>
(cherry picked from commit 9c942a43d6c49a728ab472d08640cef929cc94b0)
---
src/wayland/meta-wayland-dma-buf.c | 48 ++++++++++++++++++++++--------
src/wayland/meta-wayland-dma-buf.h | 6 ++--
src/wayland/meta-wayland.c | 3 +-
3 files changed, 40 insertions(+), 17 deletions(-)
diff --git a/src/wayland/meta-wayland-dma-buf.c b/src/wayland/meta-wayland-dma-buf.c
index ca9be5d601..6b798ec2dd 100644
--- a/src/wayland/meta-wayland-dma-buf.c
+++ b/src/wayland/meta-wayland-dma-buf.c
@@ -98,6 +98,8 @@ typedef struct _MetaWaylandDmaBufFeedback
struct _MetaWaylandDmaBufManager
{
+ GObject parent;
+
MetaWaylandCompositor *compositor;
dev_t main_device_id;
@@ -122,6 +124,9 @@ struct _MetaWaylandDmaBufBuffer
G_DEFINE_TYPE (MetaWaylandDmaBufBuffer, meta_wayland_dma_buf_buffer, G_TYPE_OBJECT);
+G_DEFINE_TYPE (MetaWaylandDmaBufManager, meta_wayland_dma_buf_manager,
+ G_TYPE_OBJECT)
+
static MetaWaylandDmaBufTranche *
meta_wayland_dma_buf_tranche_new (dev_t device_id,
GArray *formats,
@@ -1066,7 +1071,7 @@ meta_wayland_dma_buf_manager_new (MetaWaylandCompositor *compositor,
EGLDeviceEXT egl_device;
EGLAttrib attrib;
g_autoptr (GError) local_error = NULL;
- g_autofree MetaWaylandDmaBufManager *dma_buf_manager = NULL;
+ g_autoptr (MetaWaylandDmaBufManager) dma_buf_manager = NULL;
const char *device_path = NULL;
struct stat device_stat;
@@ -1141,7 +1146,7 @@ meta_wayland_dma_buf_manager_new (MetaWaylandCompositor *compositor,
initialize:
- dma_buf_manager = g_new0 (MetaWaylandDmaBufManager, 1);
+ dma_buf_manager = g_object_new (META_TYPE_WAYLAND_DMA_BUF_MANAGER, NULL);
if (!wl_global_create (compositor->wayland_display,
&zwp_linux_dmabuf_v1_interface,
@@ -1163,17 +1168,6 @@ initialize:
return g_steal_pointer (&dma_buf_manager);
}
-void
-meta_wayland_dma_buf_manager_free (MetaWaylandDmaBufManager *dma_buf_manager)
-{
- g_clear_pointer (&dma_buf_manager->format_table_file,
- meta_anonymous_file_free);
- g_clear_pointer (&dma_buf_manager->formats, g_array_unref);
- g_clear_pointer (&dma_buf_manager->default_feedback,
- meta_wayland_dma_buf_feedback_free);
- g_free (dma_buf_manager);
-}
-
static void
meta_wayland_dma_buf_buffer_finalize (GObject *object)
{
@@ -1207,3 +1201,31 @@ meta_wayland_dma_buf_buffer_class_init (MetaWaylandDmaBufBufferClass *klass)
object_class->finalize = meta_wayland_dma_buf_buffer_finalize;
}
+
+static void
+meta_wayland_dma_buf_manager_finalize (GObject *object)
+{
+ MetaWaylandDmaBufManager *dma_buf_manager =
+ META_WAYLAND_DMA_BUF_MANAGER (object);
+
+ g_clear_pointer (&dma_buf_manager->format_table_file,
+ meta_anonymous_file_free);
+ g_clear_pointer (&dma_buf_manager->formats, g_array_unref);
+ g_clear_pointer (&dma_buf_manager->default_feedback,
+ meta_wayland_dma_buf_feedback_free);
+
+ G_OBJECT_CLASS (meta_wayland_dma_buf_manager_parent_class)->finalize (object);
+}
+
+static void
+meta_wayland_dma_buf_manager_class_init (MetaWaylandDmaBufManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = meta_wayland_dma_buf_manager_finalize;
+}
+
+static void
+meta_wayland_dma_buf_manager_init (MetaWaylandDmaBufManager *dma_buf)
+{
+}
diff --git a/src/wayland/meta-wayland-dma-buf.h b/src/wayland/meta-wayland-dma-buf.h
index 72fd0b16a0..dc1231560b 100644
--- a/src/wayland/meta-wayland-dma-buf.h
+++ b/src/wayland/meta-wayland-dma-buf.h
@@ -37,13 +37,15 @@
G_DECLARE_FINAL_TYPE (MetaWaylandDmaBufBuffer, meta_wayland_dma_buf_buffer,
META, WAYLAND_DMA_BUF_BUFFER, GObject);
+#define META_TYPE_WAYLAND_DMA_BUF_MANAGER (meta_wayland_dma_buf_manager_get_type ())
+G_DECLARE_FINAL_TYPE (MetaWaylandDmaBufManager, meta_wayland_dma_buf_manager,
+ META, WAYLAND_DMA_BUF_MANAGER, GObject)
+
typedef struct _MetaWaylandDmaBufBuffer MetaWaylandDmaBufBuffer;
MetaWaylandDmaBufManager * meta_wayland_dma_buf_manager_new (MetaWaylandCompositor *compositor,
GError **error);
-void meta_wayland_dma_buf_manager_free (MetaWaylandDmaBufManager *dma_buf_manager);
-
gboolean
meta_wayland_dma_buf_buffer_attach (MetaWaylandBuffer *buffer,
CoglTexture **texture,
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index a566a35449..28af6ae196 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -618,8 +618,7 @@ meta_wayland_finalize (void)
if (compositor->wayland_display)
wl_display_destroy_clients (compositor->wayland_display);
- g_clear_pointer (&compositor->dma_buf_manager,
- meta_wayland_dma_buf_manager_free);
+ g_clear_object (&compositor->dma_buf_manager);
g_clear_pointer (&compositor->seat, meta_wayland_seat_free);
--
2.51.1

View File

@ -0,0 +1,108 @@
From c5f6a8435d526438c722f6b13869d177bcc31855 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Fri, 6 Aug 2021 16:20:14 +0200
Subject: [PATCH 08/18] wayland/dma-buf: Add tranche priorities
Unused for now, but will be added to prioritize scanout tranches higher
than render only ones.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1959>
(cherry picked from commit 9a47766a9627e75fffb7c5a20c0e3d63aae38539)
---
src/wayland/meta-wayland-dma-buf.c | 36 ++++++++++++++++++++++++++----
1 file changed, 32 insertions(+), 4 deletions(-)
diff --git a/src/wayland/meta-wayland-dma-buf.c b/src/wayland/meta-wayland-dma-buf.c
index 6b798ec2dd..a255158993 100644
--- a/src/wayland/meta-wayland-dma-buf.c
+++ b/src/wayland/meta-wayland-dma-buf.c
@@ -76,6 +76,12 @@ typedef enum _MetaWaylandDmaBufTrancheFlags
META_WAYLAND_DMA_BUF_TRANCHE_FLAG_SCANOUT = 1,
} MetaWaylandDmaBufTrancheFlags;
+typedef enum _MetaWaylandDmaBufTranchePriority
+{
+ META_WAYLAND_DMA_BUF_TRANCHE_PRIORITY_HIGH = 0,
+ META_WAYLAND_DMA_BUF_TRANCHE_PRIORITY_DEFAULT = 10,
+} MetaWaylandDmaBufTranchePriority;
+
typedef struct _MetaWaylandDmaBufFormat
{
uint32_t drm_format;
@@ -85,6 +91,7 @@ typedef struct _MetaWaylandDmaBufFormat
typedef struct _MetaWaylandDmaBufTranche
{
+ MetaWaylandDmaBufTranchePriority priority;
dev_t target_device_id;
GArray *formats;
MetaWaylandDmaBufTrancheFlags flags;
@@ -127,16 +134,33 @@ G_DEFINE_TYPE (MetaWaylandDmaBufBuffer, meta_wayland_dma_buf_buffer, G_TYPE_OBJE
G_DEFINE_TYPE (MetaWaylandDmaBufManager, meta_wayland_dma_buf_manager,
G_TYPE_OBJECT)
+static gint
+compare_tranches (gconstpointer a,
+ gconstpointer b)
+{
+ const MetaWaylandDmaBufTranche *tranche_a = a;
+ const MetaWaylandDmaBufTranche *tranche_b = b;
+
+ if (tranche_a->priority > tranche_b->priority)
+ return 1;
+ if (tranche_a->priority < tranche_b->priority)
+ return -1;
+ else
+ return 0;
+}
+
static MetaWaylandDmaBufTranche *
-meta_wayland_dma_buf_tranche_new (dev_t device_id,
- GArray *formats,
- MetaWaylandDmaBufTrancheFlags flags)
+meta_wayland_dma_buf_tranche_new (dev_t device_id,
+ GArray *formats,
+ MetaWaylandDmaBufTranchePriority priority,
+ MetaWaylandDmaBufTrancheFlags flags)
{
MetaWaylandDmaBufTranche *tranche;
tranche = g_new0 (MetaWaylandDmaBufTranche, 1);
tranche->target_device_id = device_id;
tranche->formats = g_array_copy (formats);
+ tranche->priority = priority;
tranche->flags = flags;
return tranche;
@@ -217,7 +241,8 @@ static void
meta_wayland_dma_buf_feedback_add_tranche (MetaWaylandDmaBufFeedback *feedback,
MetaWaylandDmaBufTranche *tranche)
{
- feedback->tranches = g_list_append (feedback->tranches, tranche);
+ feedback->tranches = g_list_insert_sorted (feedback->tranches, tranche,
+ compare_tranches);
}
static MetaWaylandDmaBufFeedback *
@@ -1035,15 +1060,18 @@ init_formats (MetaWaylandDmaBufManager *dma_buf_manager,
static void
init_default_feedback (MetaWaylandDmaBufManager *dma_buf_manager)
{
+ MetaWaylandDmaBufTranchePriority priority;
MetaWaylandDmaBufTrancheFlags flags;
MetaWaylandDmaBufTranche *tranche;
dma_buf_manager->default_feedback =
meta_wayland_dma_buf_feedback_new (dma_buf_manager->main_device_id);
+ priority = META_WAYLAND_DMA_BUF_TRANCHE_PRIORITY_DEFAULT;
flags = META_WAYLAND_DMA_BUF_TRANCHE_FLAG_NONE;
tranche = meta_wayland_dma_buf_tranche_new (dma_buf_manager->main_device_id,
dma_buf_manager->formats,
+ priority,
flags);
meta_wayland_dma_buf_feedback_add_tranche (dma_buf_manager->default_feedback,
tranche);
--
2.51.1

View File

@ -0,0 +1,302 @@
From f928306ebbec7bcbdb80a456b07e7db0219da36c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Fri, 6 Aug 2021 17:00:19 +0200
Subject: [PATCH 09/18] compositor/native: Track what Wayland surface is a
scanout candidate
For the current candidate, set the candidate CRTC on that surface. This
will later be used to send DMA buffer feedback for direct scanout purposes.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1959>
(cherry picked from commit 43161c66602febd5bf635f8dea927da1b282c757)
---
src/compositor/meta-compositor-native.c | 69 +++++++++++++++++----
src/compositor/meta-surface-actor-wayland.c | 3 +-
src/wayland/meta-wayland-surface.c | 60 ++++++++++++++++++
src/wayland/meta-wayland-surface.h | 8 +++
4 files changed, 127 insertions(+), 13 deletions(-)
diff --git a/src/compositor/meta-compositor-native.c b/src/compositor/meta-compositor-native.c
index 00f66b70d4..7822789a3e 100644
--- a/src/compositor/meta-compositor-native.c
+++ b/src/compositor/meta-compositor-native.c
@@ -23,11 +23,14 @@
#include "compositor/meta-compositor-native.h"
#include "backends/meta-logical-monitor.h"
+#include "backends/native/meta-crtc-kms.h"
#include "compositor/meta-surface-actor-wayland.h"
struct _MetaCompositorNative
{
MetaCompositorServer parent;
+
+ MetaWaylandSurface *current_scanout_candidate;
};
G_DEFINE_TYPE (MetaCompositorNative, meta_compositor_native,
@@ -62,57 +65,88 @@ get_window_view (MetaRenderer *renderer,
static void
maybe_assign_primary_plane (MetaCompositor *compositor)
{
+ MetaCompositorNative *compositor_native = META_COMPOSITOR_NATIVE (compositor);
MetaBackend *backend = meta_get_backend ();
MetaRenderer *renderer = meta_backend_get_renderer (backend);
MetaWindowActor *window_actor;
MetaWindow *window;
MetaRendererView *view;
+ MetaCrtc *crtc;
CoglFramebuffer *framebuffer;
CoglOnscreen *onscreen;
MetaSurfaceActor *surface_actor;
MetaSurfaceActorWayland *surface_actor_wayland;
+ MetaWaylandSurface *surface;
+ MetaWaylandSurface *old_candidate =
+ compositor_native->current_scanout_candidate;
+ MetaWaylandSurface *new_candidate = NULL;
g_autoptr (CoglScanout) scanout = NULL;
if (meta_compositor_is_unredirect_inhibited (compositor))
- return;
+ goto done;
window_actor = meta_compositor_get_top_window_actor (compositor);
if (!window_actor)
- return;
+ goto done;
if (meta_window_actor_effect_in_progress (window_actor))
- return;
+ goto done;
if (clutter_actor_has_transitions (CLUTTER_ACTOR (window_actor)))
- return;
+ goto done;
if (clutter_actor_get_n_children (CLUTTER_ACTOR (window_actor)) != 1)
- return;
+ goto done;
window = meta_window_actor_get_meta_window (window_actor);
if (!window)
- return;
+ goto done;
view = get_window_view (renderer, window);
if (!view)
- return;
+ goto done;
+
+ crtc = meta_renderer_view_get_crtc (META_RENDERER_VIEW (view));
+ if (!META_IS_CRTC_KMS (crtc))
+ goto done;
framebuffer = clutter_stage_view_get_framebuffer (CLUTTER_STAGE_VIEW (view));
if (!COGL_IS_ONSCREEN (framebuffer))
- return;
+ goto done;
surface_actor = meta_window_actor_get_surface (window_actor);
if (!META_IS_SURFACE_ACTOR_WAYLAND (surface_actor))
- return;
-
+ goto done;
surface_actor_wayland = META_SURFACE_ACTOR_WAYLAND (surface_actor);
+
+ surface = meta_surface_actor_wayland_get_surface (surface_actor_wayland);
+ if (!surface)
+ goto done;
+
+ new_candidate = surface;
+
onscreen = COGL_ONSCREEN (framebuffer);
scanout = meta_surface_actor_wayland_try_acquire_scanout (surface_actor_wayland,
onscreen);
if (!scanout)
- return;
+ goto done;
clutter_stage_view_assign_next_scanout (CLUTTER_STAGE_VIEW (view), scanout);
+
+done:
+
+ if (old_candidate && old_candidate != new_candidate)
+ {
+ meta_wayland_surface_set_scanout_candidate (old_candidate, NULL);
+ g_clear_weak_pointer (&compositor_native->current_scanout_candidate);
+ }
+
+ if (new_candidate)
+ {
+ meta_wayland_surface_set_scanout_candidate (surface, crtc);
+ g_set_weak_pointer (&compositor_native->current_scanout_candidate,
+ surface);
+ }
}
static void
@@ -137,6 +171,16 @@ meta_compositor_native_new (MetaDisplay *display,
NULL);
}
+static void
+meta_compositor_native_finalize (GObject *object)
+{
+ MetaCompositorNative *compositor_native = META_COMPOSITOR_NATIVE (object);
+
+ g_clear_weak_pointer (&compositor_native->current_scanout_candidate);
+
+ G_OBJECT_CLASS (meta_compositor_native_parent_class)->finalize (object);
+}
+
static void
meta_compositor_native_init (MetaCompositorNative *compositor_native)
{
@@ -145,7 +189,10 @@ meta_compositor_native_init (MetaCompositorNative *compositor_native)
static void
meta_compositor_native_class_init (MetaCompositorNativeClass *klass)
{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
MetaCompositorClass *compositor_class = META_COMPOSITOR_CLASS (klass);
+ object_class->finalize = meta_compositor_native_finalize;
+
compositor_class->before_paint = meta_compositor_native_before_paint;
}
diff --git a/src/compositor/meta-surface-actor-wayland.c b/src/compositor/meta-surface-actor-wayland.c
index 8c2a93da1e..4e131b0ba6 100644
--- a/src/compositor/meta-surface-actor-wayland.c
+++ b/src/compositor/meta-surface-actor-wayland.c
@@ -80,8 +80,7 @@ meta_surface_actor_wayland_try_acquire_scanout (MetaSurfaceActorWayland *self,
return NULL;
surface = meta_surface_actor_wayland_get_surface (self);
- if (!surface)
- return NULL;
+ g_return_val_if_fail (surface, NULL);
scanout = meta_wayland_surface_try_acquire_scanout (surface, onscreen);
if (!scanout)
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index e033b7b911..c69433352e 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -79,6 +79,17 @@ typedef struct _MetaWaylandSurfaceRolePrivate
MetaWaylandSurface *surface;
} MetaWaylandSurfaceRolePrivate;
+enum
+{
+ PROP_0,
+
+ PROP_SCANOUT_CANDIDATE,
+
+ N_PROPS
+};
+
+static GParamSpec *obj_props[N_PROPS];
+
G_DEFINE_TYPE (MetaWaylandSurface, meta_wayland_surface, G_TYPE_OBJECT);
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaWaylandSurfaceRole,
@@ -1413,6 +1424,7 @@ wl_surface_destructor (struct wl_resource *resource)
g_signal_emit (surface, surface_signals[SURFACE_DESTROY], 0);
+ g_clear_object (&surface->scanout_candidate);
g_clear_object (&surface->role);
if (surface->unassigned.buffer)
@@ -1697,11 +1709,41 @@ meta_wayland_surface_init (MetaWaylandSurface *surface)
g_node_prepend_data (surface->subsurface_branch_node, surface);
}
+static void
+meta_wayland_surface_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ MetaWaylandSurface *surface = META_WAYLAND_SURFACE (object);
+
+ switch (prop_id)
+ {
+ case PROP_SCANOUT_CANDIDATE:
+ g_value_set_object (value, surface->scanout_candidate);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
static void
meta_wayland_surface_class_init (MetaWaylandSurfaceClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->get_property = meta_wayland_surface_get_property;
+
+ obj_props[PROP_SCANOUT_CANDIDATE] =
+ g_param_spec_object ("scanout-candidate",
+ "scanout-candidate",
+ "Scanout candidate for given CRTC",
+ META_TYPE_CRTC,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS);
+ g_object_class_install_properties (object_class, N_PROPS, obj_props);
+
surface_signals[SURFACE_DESTROY] =
g_signal_new ("destroy",
G_TYPE_FROM_CLASS (object_class),
@@ -2104,3 +2146,21 @@ meta_wayland_surface_try_acquire_scanout (MetaWaylandSurface *surface,
return scanout;
}
+
+MetaCrtc *
+meta_wayland_surface_get_scanout_candidate (MetaWaylandSurface *surface)
+{
+ return surface->scanout_candidate;
+}
+
+void
+meta_wayland_surface_set_scanout_candidate (MetaWaylandSurface *surface,
+ MetaCrtc *crtc)
+{
+ if (surface->scanout_candidate == crtc)
+ return;
+
+ g_set_object (&surface->scanout_candidate, crtc);
+ g_object_notify_by_pspec (G_OBJECT (surface),
+ obj_props[PROP_SCANOUT_CANDIDATE]);
+}
diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h
index f0153b23b9..7e90cf095c 100644
--- a/src/wayland/meta-wayland-surface.h
+++ b/src/wayland/meta-wayland-surface.h
@@ -247,6 +247,9 @@ struct _MetaWaylandSurface
*/
uint64_t sequence;
} presentation_time;
+
+ /* dma-buf feedback */
+ MetaCrtc *scanout_candidate;
};
void meta_wayland_shell_init (MetaWaylandCompositor *compositor);
@@ -362,6 +365,11 @@ int meta_wayland_surface_get_height (MetaWaylandSurface *surface
CoglScanout * meta_wayland_surface_try_acquire_scanout (MetaWaylandSurface *surface,
CoglOnscreen *onscreen);
+MetaCrtc * meta_wayland_surface_get_scanout_candidate (MetaWaylandSurface *surface);
+
+void meta_wayland_surface_set_scanout_candidate (MetaWaylandSurface *surface,
+ MetaCrtc *crtc);
+
static inline GNode *
meta_get_next_subsurface_sibling (GNode *n)
{
--
2.51.1

View File

@ -0,0 +1,75 @@
From 2890b4a152f1efbc1492626a4ee055083cc40159 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Fri, 6 Aug 2021 17:07:21 +0200
Subject: [PATCH 10/18] wayland/dma-buf: Move should_send_modifiers() to the
top
It's very much an auxiliary method; lets move it to where it belongs,
according to HACKING.md.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1959>
(cherry picked from commit 4c54b36126a610c43b05f36f4aab33f302fdc021)
---
src/wayland/meta-wayland-dma-buf.c | 39 ++++++++++++++++--------------
1 file changed, 21 insertions(+), 18 deletions(-)
diff --git a/src/wayland/meta-wayland-dma-buf.c b/src/wayland/meta-wayland-dma-buf.c
index a255158993..c9e4671074 100644
--- a/src/wayland/meta-wayland-dma-buf.c
+++ b/src/wayland/meta-wayland-dma-buf.c
@@ -134,6 +134,27 @@ G_DEFINE_TYPE (MetaWaylandDmaBufBuffer, meta_wayland_dma_buf_buffer, G_TYPE_OBJE
G_DEFINE_TYPE (MetaWaylandDmaBufManager, meta_wayland_dma_buf_manager,
G_TYPE_OBJECT)
+static gboolean
+should_send_modifiers (MetaBackend *backend)
+{
+ MetaSettings *settings = meta_backend_get_settings (backend);
+
+ if (meta_settings_is_experimental_feature_enabled (
+ settings, META_EXPERIMENTAL_FEATURE_KMS_MODIFIERS))
+ return TRUE;
+
+#ifdef HAVE_NATIVE_BACKEND
+ if (META_IS_BACKEND_NATIVE (backend))
+ {
+ MetaRenderer *renderer = meta_backend_get_renderer (backend);
+ MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer);
+ return meta_renderer_native_use_modifiers (renderer_native);
+ }
+#endif
+
+ return FALSE;
+}
+
static gint
compare_tranches (gconstpointer a,
gconstpointer b)
@@ -861,24 +882,6 @@ static const struct zwp_linux_dmabuf_v1_interface dma_buf_implementation =
dma_buf_handle_get_surface_feedback,
};
-static gboolean
-should_send_modifiers (MetaBackend *backend)
-{
- MetaSettings *settings = meta_backend_get_settings (backend);
-
-#ifdef HAVE_NATIVE_BACKEND
- if (META_IS_BACKEND_NATIVE (backend))
- {
- MetaRenderer *renderer = meta_backend_get_renderer (backend);
- MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer);
- return meta_renderer_native_use_modifiers (renderer_native);
- }
-#endif
-
- return meta_settings_is_experimental_feature_enabled (
- settings, META_EXPERIMENTAL_FEATURE_KMS_MODIFIERS);
-}
-
static void
send_modifiers (struct wl_resource *resource,
MetaWaylandDmaBufFormat *format,
--
2.51.1

View File

@ -0,0 +1,378 @@
From 6bb16eb5ac7f70b42533b189a4928f29d0fbc768 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Fri, 6 Aug 2021 17:04:18 +0200
Subject: [PATCH 11/18] wayland/dma-buf: Add support for scanout surface
feedback
Whenever a surface is promoted as a scanout candidate by
MetaCompositorNative, it'll get a CRTC set as the candidate CRTC.
When a client asks for DMA buffer surface feedback, use this property to
determine whether we should send a scanout feedback tranche.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1959>
(cherry picked from commit 64e6bedb6bcd6cedc8439c6848003991906c9c80)
---
src/wayland/meta-wayland-dma-buf.c | 287 ++++++++++++++++++++++++++++-
1 file changed, 284 insertions(+), 3 deletions(-)
diff --git a/src/wayland/meta-wayland-dma-buf.c b/src/wayland/meta-wayland-dma-buf.c
index c9e4671074..385012f1ab 100644
--- a/src/wayland/meta-wayland-dma-buf.c
+++ b/src/wayland/meta-wayland-dma-buf.c
@@ -95,6 +95,7 @@ typedef struct _MetaWaylandDmaBufTranche
dev_t target_device_id;
GArray *formats;
MetaWaylandDmaBufTrancheFlags flags;
+ uint64_t scanout_crtc_id;
} MetaWaylandDmaBufTranche;
typedef struct _MetaWaylandDmaBufFeedback
@@ -103,6 +104,15 @@ typedef struct _MetaWaylandDmaBufFeedback
GList *tranches;
} MetaWaylandDmaBufFeedback;
+typedef struct _MetaWaylandDmaBufSurfaceFeedback
+{
+ MetaWaylandDmaBufManager *dma_buf_manager;
+ MetaWaylandSurface *surface;
+ MetaWaylandDmaBufFeedback *feedback;
+ GList *resources;
+ gulong scanout_candidate_changed_id;
+} MetaWaylandDmaBufSurfaceFeedback;
+
struct _MetaWaylandDmaBufManager
{
GObject parent;
@@ -134,6 +144,8 @@ G_DEFINE_TYPE (MetaWaylandDmaBufBuffer, meta_wayland_dma_buf_buffer, G_TYPE_OBJE
G_DEFINE_TYPE (MetaWaylandDmaBufManager, meta_wayland_dma_buf_manager,
G_TYPE_OBJECT)
+static GQuark quark_dma_buf_surface_feedback;
+
static gboolean
should_send_modifiers (MetaBackend *backend)
{
@@ -194,6 +206,15 @@ meta_wayland_dma_buf_tranche_free (MetaWaylandDmaBufTranche *tranche)
g_free (tranche);
}
+static MetaWaylandDmaBufTranche *
+meta_wayland_dma_buf_tranche_copy (MetaWaylandDmaBufTranche *tranche)
+{
+ return meta_wayland_dma_buf_tranche_new (tranche->target_device_id,
+ tranche->formats,
+ tranche->priority,
+ tranche->flags);
+}
+
static void
meta_wayland_dma_buf_tranche_send (MetaWaylandDmaBufTranche *tranche,
struct wl_resource *resource)
@@ -285,6 +306,20 @@ meta_wayland_dma_buf_feedback_free (MetaWaylandDmaBufFeedback *feedback)
g_free (feedback);
}
+static MetaWaylandDmaBufFeedback *
+meta_wayland_dma_buf_feedback_copy (MetaWaylandDmaBufFeedback *feedback)
+{
+ MetaWaylandDmaBufFeedback *new_feedback;
+
+ new_feedback = meta_wayland_dma_buf_feedback_new (feedback->main_device_id);
+ new_feedback->tranches =
+ g_list_copy_deep (feedback->tranches,
+ (GCopyFunc) meta_wayland_dma_buf_tranche_copy,
+ NULL);
+
+ return new_feedback;
+}
+
static gboolean
meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer,
GError **error)
@@ -848,6 +883,242 @@ dma_buf_handle_get_default_feedback (struct wl_client *client,
feedback_resource);
}
+#ifdef HAVE_NATIVE_BACKEND
+static int
+find_scanout_tranche_func (gconstpointer a,
+ gconstpointer b)
+{
+ const MetaWaylandDmaBufTranche *tranche = a;
+
+ if (tranche->scanout_crtc_id)
+ return 0;
+ else
+ return -1;
+}
+
+static gboolean
+has_modifier (GArray *modifiers,
+ uint64_t drm_modifier)
+{
+ int i;
+
+ for (i = 0; i < modifiers->len; i++)
+ {
+ if (drm_modifier == g_array_index (modifiers, uint64_t, i))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
+crtc_supports_modifier (MetaCrtcKms *crtc_kms,
+ uint32_t drm_format,
+ uint64_t drm_modifier)
+{
+ GArray *crtc_modifiers;
+
+ crtc_modifiers = meta_crtc_kms_get_modifiers (crtc_kms, drm_format);
+ if (!crtc_modifiers)
+ return FALSE;
+
+ return has_modifier (crtc_modifiers, drm_modifier);
+}
+
+static void
+ensure_scanout_tranche (MetaWaylandDmaBufSurfaceFeedback *surface_feedback,
+ MetaCrtc *crtc)
+{
+ MetaWaylandDmaBufManager *dma_buf_manager = surface_feedback->dma_buf_manager;
+ MetaWaylandDmaBufFeedback *feedback = surface_feedback->feedback;
+ MetaCrtcKms *crtc_kms;
+ MetaWaylandDmaBufTranche *tranche;
+ GList *el;
+ int i;
+ g_autoptr (GArray) formats = NULL;
+ MetaWaylandDmaBufTranchePriority priority;
+ MetaWaylandDmaBufTrancheFlags flags;
+
+ g_return_if_fail (META_IS_CRTC_KMS (crtc));
+ crtc_kms = META_CRTC_KMS (crtc);
+
+ el = g_list_find_custom (feedback->tranches, NULL, find_scanout_tranche_func);
+ if (el)
+ {
+ tranche = el->data;
+
+ if (tranche->scanout_crtc_id == meta_crtc_get_id (crtc))
+ return;
+
+ meta_wayland_dma_buf_tranche_free (tranche);
+ feedback->tranches = g_list_delete_link (feedback->tranches, el);
+ }
+
+ formats = g_array_new (FALSE, FALSE, sizeof (MetaWaylandDmaBufFormat));
+ if (should_send_modifiers (meta_get_backend ()))
+ {
+ for (i = 0; i < dma_buf_manager->formats->len; i++)
+ {
+ MetaWaylandDmaBufFormat format =
+ g_array_index (dma_buf_manager->formats,
+ MetaWaylandDmaBufFormat,
+ i);
+
+ if (!crtc_supports_modifier (crtc_kms,
+ format.drm_format,
+ format.drm_modifier))
+ continue;
+
+ g_array_append_val (formats, format);
+ }
+
+ if (formats->len == 0)
+ return;
+ }
+ else
+ {
+ for (i = 0; i < dma_buf_manager->formats->len; i++)
+ {
+ MetaWaylandDmaBufFormat format =
+ g_array_index (dma_buf_manager->formats,
+ MetaWaylandDmaBufFormat,
+ i);
+
+ if (format.drm_modifier != DRM_FORMAT_MOD_INVALID)
+ continue;
+
+ if (!meta_crtc_kms_get_modifiers (crtc_kms, format.drm_format))
+ continue;
+
+ g_array_append_val (formats, format);
+ }
+
+ if (formats->len == 0)
+ return;
+ }
+
+ priority = META_WAYLAND_DMA_BUF_TRANCHE_PRIORITY_HIGH;
+ flags = META_WAYLAND_DMA_BUF_TRANCHE_FLAG_SCANOUT;
+ tranche = meta_wayland_dma_buf_tranche_new (feedback->main_device_id,
+ formats,
+ priority,
+ flags);
+ tranche->scanout_crtc_id = meta_crtc_get_id (crtc);
+ meta_wayland_dma_buf_feedback_add_tranche (feedback, tranche);
+}
+
+static void
+clear_scanout_tranche (MetaWaylandDmaBufSurfaceFeedback *surface_feedback)
+{
+ MetaWaylandDmaBufFeedback *feedback = surface_feedback->feedback;
+ MetaWaylandDmaBufTranche *tranche;
+ GList *el;
+
+ el = g_list_find_custom (feedback->tranches, NULL, find_scanout_tranche_func);
+ if (!el)
+ return;
+
+ tranche = el->data;
+ meta_wayland_dma_buf_tranche_free (tranche);
+ feedback->tranches = g_list_delete_link (feedback->tranches, el);
+}
+#endif /* HAVE_NATIVE_BACKEND */
+
+static void
+update_surface_feedback_tranches (MetaWaylandDmaBufSurfaceFeedback *surface_feedback)
+{
+#ifdef HAVE_NATIVE_BACKEND
+ MetaCrtc *crtc;
+
+ crtc = meta_wayland_surface_get_scanout_candidate (surface_feedback->surface);
+ if (crtc)
+ ensure_scanout_tranche (surface_feedback, crtc);
+ else
+ clear_scanout_tranche (surface_feedback);
+#endif /* HAVE_NATIVE_BACKEND */
+}
+
+static void
+on_scanout_candidate_changed (MetaWaylandSurface *surface,
+ GParamSpec *pspec,
+ MetaWaylandDmaBufSurfaceFeedback *surface_feedback)
+{
+ GList *l;
+
+ update_surface_feedback_tranches (surface_feedback);
+
+ for (l = surface_feedback->resources; l; l = l->next)
+ {
+ struct wl_resource *resource = l->data;
+
+ meta_wayland_dma_buf_feedback_send (surface_feedback->feedback,
+ surface_feedback->dma_buf_manager,
+ resource);
+ }
+}
+
+static void
+surface_feedback_surface_destroyed_cb (gpointer user_data)
+{
+ MetaWaylandDmaBufSurfaceFeedback *surface_feedback = user_data;
+
+ g_list_foreach (surface_feedback->resources,
+ (GFunc) wl_resource_set_user_data,
+ NULL);
+ g_list_free (surface_feedback->resources);
+
+ g_free (surface_feedback);
+}
+
+static MetaWaylandDmaBufSurfaceFeedback *
+ensure_surface_feedback (MetaWaylandDmaBufManager *dma_buf_manager,
+ MetaWaylandSurface *surface)
+{
+ MetaWaylandDmaBufSurfaceFeedback *surface_feedback;
+
+ surface_feedback = g_object_get_qdata (G_OBJECT (surface),
+ quark_dma_buf_surface_feedback);
+ if (surface_feedback)
+ return surface_feedback;
+
+ surface_feedback = g_new0 (MetaWaylandDmaBufSurfaceFeedback, 1);
+ surface_feedback->dma_buf_manager = dma_buf_manager;
+ surface_feedback->surface = surface;
+ surface_feedback->feedback =
+ meta_wayland_dma_buf_feedback_copy (dma_buf_manager->default_feedback);
+
+ surface_feedback->scanout_candidate_changed_id =
+ g_signal_connect (surface, "notify::scanout-candidate",
+ G_CALLBACK (on_scanout_candidate_changed),
+ surface_feedback);
+
+ g_object_set_qdata_full (G_OBJECT (surface),
+ quark_dma_buf_surface_feedback,
+ surface_feedback,
+ surface_feedback_surface_destroyed_cb);
+
+ return surface_feedback;
+}
+
+static void
+surface_feedback_destructor (struct wl_resource *resource)
+{
+ MetaWaylandDmaBufSurfaceFeedback *surface_feedback =
+
+ surface_feedback = wl_resource_get_user_data (resource);
+ if (!surface_feedback)
+ return;
+
+ surface_feedback->resources = g_list_remove (surface_feedback->resources,
+ resource);
+ if (!surface_feedback->resources)
+ {
+ g_clear_signal_handler (&surface_feedback->scanout_candidate_changed_id,
+ surface_feedback->surface);
+ g_object_set_qdata (G_OBJECT (surface_feedback->surface),
+ quark_dma_buf_surface_feedback, NULL);
+ }
+}
+
static void
dma_buf_handle_get_surface_feedback (struct wl_client *client,
struct wl_resource *dma_buf_resource,
@@ -856,8 +1127,13 @@ dma_buf_handle_get_surface_feedback (struct wl_client *client,
{
MetaWaylandDmaBufManager *dma_buf_manager =
wl_resource_get_user_data (dma_buf_resource);
+ MetaWaylandSurface *surface =
+ wl_resource_get_user_data (surface_resource);
+ MetaWaylandDmaBufSurfaceFeedback *surface_feedback;
struct wl_resource *feedback_resource;
+ surface_feedback = ensure_surface_feedback (dma_buf_manager, surface);
+
feedback_resource =
wl_resource_create (client,
&zwp_linux_dmabuf_feedback_v1_interface,
@@ -866,10 +1142,12 @@ dma_buf_handle_get_surface_feedback (struct wl_client *client,
wl_resource_set_implementation (feedback_resource,
&feedback_implementation,
- NULL,
- feedback_destructor);
+ surface_feedback,
+ surface_feedback_destructor);
+ surface_feedback->resources = g_list_prepend (surface_feedback->resources,
+ feedback_resource);
- meta_wayland_dma_buf_feedback_send (dma_buf_manager->default_feedback,
+ meta_wayland_dma_buf_feedback_send (surface_feedback->feedback,
dma_buf_manager,
feedback_resource);
}
@@ -1254,6 +1532,9 @@ meta_wayland_dma_buf_manager_class_init (MetaWaylandDmaBufManagerClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = meta_wayland_dma_buf_manager_finalize;
+
+ quark_dma_buf_surface_feedback =
+ g_quark_from_static_string ("-meta-wayland-dma-buf-surface-feedback");
}
static void
--
2.51.1

View File

@ -0,0 +1,30 @@
From 405673317976d578d7b228f4ab5ceea0e1366d99 Mon Sep 17 00:00:00 2001
From: Robert Mader <robert.mader@collabora.com>
Date: Tue, 15 Feb 2022 20:56:27 +0100
Subject: [PATCH 12/18] wayland/dma-buf: Add missing wl_array_release()
So we don't leak the array.
Fixes 7acecb1c7233dad0b9b314f59121882a518901d7
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2297>
(cherry picked from commit 5b9abecc1bbe6acf8f65f976c660d5eefead16d8)
---
src/wayland/meta-wayland-dma-buf.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/wayland/meta-wayland-dma-buf.c b/src/wayland/meta-wayland-dma-buf.c
index 385012f1ab..4e21632159 100644
--- a/src/wayland/meta-wayland-dma-buf.c
+++ b/src/wayland/meta-wayland-dma-buf.c
@@ -271,6 +271,7 @@ meta_wayland_dma_buf_feedback_send (MetaWaylandDmaBufFeedback *feedback,
device_id_ptr = wl_array_add (&main_device_buf, sizeof (*device_id_ptr));
*device_id_ptr = feedback->main_device_id;
zwp_linux_dmabuf_feedback_v1_send_main_device (resource, &main_device_buf);
+ wl_array_release (&main_device_buf);
g_list_foreach (feedback->tranches,
(GFunc) meta_wayland_dma_buf_tranche_send,
--
2.51.1

View File

@ -0,0 +1,29 @@
From 70ff9d15f67dc88b6d81f794e8bb35820c23dfc2 Mon Sep 17 00:00:00 2001
From: Robert Mader <robert.mader@collabora.com>
Date: Tue, 15 Feb 2022 21:31:06 +0100
Subject: [PATCH 13/18] wayland/dma-buf: Fix typos in struct name
Fixes 7acecb1c7233dad0b9b314f59121882a518901d7
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2297>
(cherry picked from commit 8f91d831ee20b9c73036561ee1b57bf9f5efef65)
---
src/wayland/meta-wayland-dma-buf.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/wayland/meta-wayland-dma-buf.c b/src/wayland/meta-wayland-dma-buf.c
index 4e21632159..f28070da80 100644
--- a/src/wayland/meta-wayland-dma-buf.c
+++ b/src/wayland/meta-wayland-dma-buf.c
@@ -1281,7 +1281,7 @@ add_fallback:
*
* [ 32 bit format ][ 32 bit padding ][ 64 bit modifier ]
*/
-typedef struct _MetaMetaWaylanDmaBdufFormatEntry
+typedef struct _MetaWaylandDmaBufFormatEntry
{
uint32_t drm_format;
uint32_t unused_padding;
--
2.51.1

View File

@ -0,0 +1,45 @@
From ba94be928ecf77bd202bd57bbcc5dc5dffb4aee5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michel=20D=C3=A4nzer?= <mdaenzer@redhat.com>
Date: Thu, 16 Jun 2022 12:17:36 +0200
Subject: [PATCH 14/18] wayland/dma-buf: Free feedback in
surface_feedback_surface_destroyed_cb
Fixes leak:
==14889== 2,168 (16 direct, 2,152 indirect) bytes in 1 blocks are definitely lost in loss record 15,308 of 15,584
==14889== at 0x48445EF: calloc (vg_replace_malloc.c:1328)
==14889== by 0x4BAC1D0: g_malloc0 (gmem.c:155)
==14889== by 0x4AAFF60: meta_wayland_dma_buf_feedback_new (meta-wayland-dma-buf.c:298)
==14889== by 0x4AAFFE0: meta_wayland_dma_buf_feedback_copy (meta-wayland-dma-buf.c:317)
==14889== by 0x4AB16B6: ensure_surface_feedback (meta-wayland-dma-buf.c:1121)
==14889== by 0x4AB1848: dma_buf_handle_get_surface_feedback (meta-wayland-dma-buf.c:1169)
==14889== by 0x66F77E9: ??? (in /usr/lib/x86_64-linux-gnu/libffi.so.8.1.0)
==14889== by 0x66F6922: ??? (in /usr/lib/x86_64-linux-gnu/libffi.so.8.1.0)
==14889== by 0x5318750: ??? (in /usr/lib/x86_64-linux-gnu/libwayland-server.so.0.20.0)
==14889== by 0x5313B99: ??? (in /usr/lib/x86_64-linux-gnu/libwayland-server.so.0.20.0)
==14889== by 0x5316649: wl_event_loop_dispatch (in /usr/lib/x86_64-linux-gnu/libwayland-server.so.0.20.0)
==14889== by 0x4AA7C19: wayland_event_source_dispatch (meta-wayland.c:110)
Fixes: 64e6bedb6bcd ("wayland/dma-buf: Add support for scanout surface feedback")
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2469>
(cherry picked from commit 4af54225de3a653e7b44ab1905b64ebddf57da4a)
---
src/wayland/meta-wayland-dma-buf.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/wayland/meta-wayland-dma-buf.c b/src/wayland/meta-wayland-dma-buf.c
index f28070da80..3a1d92ecf6 100644
--- a/src/wayland/meta-wayland-dma-buf.c
+++ b/src/wayland/meta-wayland-dma-buf.c
@@ -1067,6 +1067,8 @@ surface_feedback_surface_destroyed_cb (gpointer user_data)
NULL);
g_list_free (surface_feedback->resources);
+ meta_wayland_dma_buf_feedback_free (surface_feedback->feedback);
+
g_free (surface_feedback);
}
--
2.51.1

View File

@ -0,0 +1,144 @@
From 43feafa1c2c061acb226a8df0a6b6a1f5a9b1ba0 Mon Sep 17 00:00:00 2001
From: Robert Mader <robert.mader@posteo.de>
Date: Mon, 25 Apr 2022 18:00:50 +0200
Subject: [PATCH 15/18] wayland/dma-buf: Only advertise supported formats
Analogous to how we use `eglQueryDmaBufModifiersEXT()` to query
supported modifiers, use `eglQueryDmaBufFormatsEXT()` to ensure
we only advertise formats supported by both the compositor and the
driver.
If there is no overlap, don't advertise `zwp_linux_dmabuf_v1` at
all.
Closes https://gitlab.gnome.org/GNOME/mutter/-/issues/2238
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2386>
(cherry picked from commit c8095b430689365c5cdd4646c54de4b07a0da7ee)
---
src/wayland/meta-wayland-dma-buf.c | 89 +++++++++++++++++++++++-------
1 file changed, 69 insertions(+), 20 deletions(-)
diff --git a/src/wayland/meta-wayland-dma-buf.c b/src/wayland/meta-wayland-dma-buf.c
index 3a1d92ecf6..145fd0cdab 100644
--- a/src/wayland/meta-wayland-dma-buf.c
+++ b/src/wayland/meta-wayland-dma-buf.c
@@ -1317,28 +1317,71 @@ init_format_table (MetaWaylandDmaBufManager *dma_buf_manager)
meta_anonymous_file_new (size, (uint8_t *) format_table);
}
-static void
-init_formats (MetaWaylandDmaBufManager *dma_buf_manager,
- EGLDisplay egl_display)
+static EGLint supported_formats[] = {
+ DRM_FORMAT_ARGB8888,
+ DRM_FORMAT_ABGR8888,
+ DRM_FORMAT_XRGB8888,
+ DRM_FORMAT_XBGR8888,
+ DRM_FORMAT_ARGB2101010,
+ DRM_FORMAT_ABGR2101010,
+ DRM_FORMAT_XRGB2101010,
+ DRM_FORMAT_XBGR2101010,
+ DRM_FORMAT_RGB565,
+ DRM_FORMAT_ABGR16161616F,
+ DRM_FORMAT_XBGR16161616F,
+ DRM_FORMAT_XRGB16161616F,
+ DRM_FORMAT_ARGB16161616F
+};
+
+static gboolean
+init_formats (MetaWaylandDmaBufManager *dma_buf_manager,
+ EGLDisplay egl_display,
+ GError **error)
{
+ MetaBackend *backend = meta_get_backend ();
+ MetaEgl *egl = meta_backend_get_egl (backend);
+ EGLint num_formats;
+ g_autofree EGLint *driver_formats = NULL;
+ int i, j;
+
dma_buf_manager->formats = g_array_new (FALSE, FALSE,
sizeof (MetaWaylandDmaBufFormat));
- add_format (dma_buf_manager, egl_display, DRM_FORMAT_ARGB8888);
- add_format (dma_buf_manager, egl_display, DRM_FORMAT_ABGR8888);
- add_format (dma_buf_manager, egl_display, DRM_FORMAT_XRGB8888);
- add_format (dma_buf_manager, egl_display, DRM_FORMAT_XBGR8888);
- add_format (dma_buf_manager, egl_display, DRM_FORMAT_ARGB2101010);
- add_format (dma_buf_manager, egl_display, DRM_FORMAT_ABGR2101010);
- add_format (dma_buf_manager, egl_display, DRM_FORMAT_XRGB2101010);
- add_format (dma_buf_manager, egl_display, DRM_FORMAT_XBGR2101010);
- add_format (dma_buf_manager, egl_display, DRM_FORMAT_RGB565);
- add_format (dma_buf_manager, egl_display, DRM_FORMAT_ABGR16161616F);
- add_format (dma_buf_manager, egl_display, DRM_FORMAT_XBGR16161616F);
- add_format (dma_buf_manager, egl_display, DRM_FORMAT_XRGB16161616F);
- add_format (dma_buf_manager, egl_display, DRM_FORMAT_ARGB16161616F);
+ if (!meta_egl_query_dma_buf_formats (egl, egl_display, 0, NULL, &num_formats,
+ error))
+ return FALSE;
+
+ if (num_formats == 0)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "EGL doesn't support any DRM formats");
+ return FALSE;
+ }
+
+ driver_formats = g_new0 (EGLint, num_formats);
+ if (!meta_egl_query_dma_buf_formats (egl, egl_display, num_formats,
+ driver_formats, &num_formats, error))
+ return FALSE;
+
+ for (i = 0; i < G_N_ELEMENTS (supported_formats); i++)
+ {
+ for (j = 0; j < num_formats; j++)
+ {
+ if (supported_formats[i] == driver_formats[j])
+ add_format (dma_buf_manager, egl_display, supported_formats[i]);
+ }
+ }
+
+ if (dma_buf_manager->formats->len == 0)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "EGL doesn't support any DRM formats supported by the "
+ "compositor");
+ return FALSE;
+ }
init_format_table (dma_buf_manager);
+ return TRUE;
}
static void
@@ -1460,6 +1503,16 @@ initialize:
dma_buf_manager = g_object_new (META_TYPE_WAYLAND_DMA_BUF_MANAGER, NULL);
+ dma_buf_manager->compositor = compositor;
+ dma_buf_manager->main_device_id = device_id;
+
+ if (!init_formats (dma_buf_manager, egl_display, &local_error))
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "No supported formats detected: %s", local_error->message);
+ return NULL;
+ }
+
if (!wl_global_create (compositor->wayland_display,
&zwp_linux_dmabuf_v1_interface,
protocol_version,
@@ -1471,10 +1524,6 @@ initialize:
return NULL;
}
- dma_buf_manager->compositor = compositor;
- dma_buf_manager->main_device_id = device_id;
-
- init_formats (dma_buf_manager, egl_display);
init_default_feedback (dma_buf_manager);
return g_steal_pointer (&dma_buf_manager);
--
2.51.1

View File

@ -0,0 +1,29 @@
From d7bf34fc6d9b9dd876c665c9e8b84270de86e34e Mon Sep 17 00:00:00 2001
From: Robert Mader <robert.mader@posteo.de>
Date: Tue, 26 Apr 2022 20:27:57 +0200
Subject: [PATCH 16/18] wayland/dma-buf: Remove redundant error check
`meta_egl_*` functions are assumed to set an error on failure.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2386>
(cherry picked from commit aa8d2d6fffbcb4ccf16ff527311e101fa75d4d3c)
---
src/wayland/meta-wayland-dma-buf.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/wayland/meta-wayland-dma-buf.c b/src/wayland/meta-wayland-dma-buf.c
index 145fd0cdab..c59b767b4c 100644
--- a/src/wayland/meta-wayland-dma-buf.c
+++ b/src/wayland/meta-wayland-dma-buf.c
@@ -1252,7 +1252,7 @@ add_format (MetaWaylandDmaBufManager *dma_buf_manager,
&num_modifiers, &error))
{
g_warning ("Failed to query modifiers for format 0x%" PRIu32 ": %s",
- drm_format, error ? error->message : "unknown error");
+ drm_format, error->message);
goto add_fallback;
}
--
2.51.1

View File

@ -0,0 +1,34 @@
From 6e6a88f95e6fae313601fc83e3f3b7e61628e4e0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Wed, 12 Jan 2022 14:02:25 +0100
Subject: [PATCH 17/18] egl: Don't set an error when there is none
Some API will return NULL or the equivalent; sometimes it's an error,
and sometimes it's not, and the way to check that is by looking at the
return value of eglGetError(). When we check this, don't set the GError
if it returned EGL_SUCCESS, as that indicates that the return value is
expected behavior, and not an error.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2151>
(cherry picked from commit 719a6c0006ed5e982b283c9a616973600db8c7f7)
---
src/backends/meta-egl.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/backends/meta-egl.c b/src/backends/meta-egl.c
index c2777271ff..3b6e4b399e 100644
--- a/src/backends/meta-egl.c
+++ b/src/backends/meta-egl.c
@@ -158,6 +158,9 @@ set_egl_error (GError **error)
return;
error_number = eglGetError ();
+ if (error_number == EGL_SUCCESS)
+ return;
+
error_str = get_egl_error_str (error_number);
g_set_error_literal (error, META_EGL_ERROR,
error_number,
--
2.51.1

View File

@ -0,0 +1,72 @@
From b61fc8eb57186dd4fb2f83383f69673a06b0104c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Wed, 12 Jan 2022 12:11:01 +0100
Subject: [PATCH 18/18] wayland/dma-buf: Don't warn if there was no render node
When running in KVM, the EGL driver supports querying the render node
path, but it returns NULL. Handle that better by falling back to
querying the device main device file, instead of falling back on v3 of
the protocol and logging a warning.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2151>
(cherry picked from commit a2382f325117dbfc4dede55f72fc5b9942c3ffb9)
---
src/wayland/meta-wayland-dma-buf.c | 33 +++++++++++++++++-------------
1 file changed, 19 insertions(+), 14 deletions(-)
diff --git a/src/wayland/meta-wayland-dma-buf.c b/src/wayland/meta-wayland-dma-buf.c
index c59b767b4c..75b0bbe858 100644
--- a/src/wayland/meta-wayland-dma-buf.c
+++ b/src/wayland/meta-wayland-dma-buf.c
@@ -1459,29 +1459,34 @@ meta_wayland_dma_buf_manager_new (MetaWaylandCompositor *compositor,
device_path = meta_egl_query_device_string (egl, egl_device,
EGL_DRM_RENDER_NODE_FILE_EXT,
&local_error);
+ if (local_error)
+ {
+ g_warning ("Failed to query EGL render node path: %s",
+ local_error->message);
+ g_clear_error (&local_error);
+ }
}
- else if (meta_egl_egl_device_has_extensions (egl, egl_device, NULL,
- "EGL_EXT_device_drm",
- NULL))
+
+ if (!device_path &&
+ meta_egl_egl_device_has_extensions (egl, egl_device, NULL,
+ "EGL_EXT_device_drm",
+ NULL))
{
device_path = meta_egl_query_device_string (egl, egl_device,
EGL_DRM_DEVICE_FILE_EXT,
&local_error);
- }
- else
- {
- meta_topic (META_DEBUG_WAYLAND,
- "Only advertising zwp_linux_dmabuf_v1 interface version 3 "
- "support, missing 'EGL_EXT_device_drm' and "
- "'EGL_EXT_device_drm_render_node'");
- protocol_version = 3;
- goto initialize;
+ if (local_error)
+ {
+ g_warning ("Failed to query EGL render node path: %s",
+ local_error->message);
+ }
}
if (!device_path)
{
- g_warning ("Failed to query EGL device path: %s",
- local_error->message);
+ meta_topic (META_DEBUG_WAYLAND,
+ "Only advertising zwp_linux_dmabuf_v1 interface version 3 "
+ "support, no suitable device path could be found");
protocol_version = 3;
goto initialize;
}
--
2.51.1

View File

@ -10,7 +10,7 @@
Name: mutter
Version: 40.9
Release: 30%{?dist}
Release: 31%{?dist}
Summary: Window and compositing manager based on Clutter
License: GPLv2+
@ -170,6 +170,26 @@ Patch73: 0001-compositor-x11-sync-again-at-the-end-of-before_paint.patch
# RHEL-113246
Patch74: 0001-compositor-sync-ring-Allow-the-gpu_fence-to-be-moved.patch
# RHEL-129832 - linux_dmabuf v4 support.
Patch75: 0001-egl-Add-eglQueryDisplayAttribEXT-helper.patch
Patch76: 0002-wayland-dma-buf-Add-manager-struct.patch
Patch77: 0003-wayland-dma-buf-Prepare-format-modifier-map-up-front.patch
Patch78: 0004-wayland-dma-buf-Add-basic-support-for-DMA-buffer-fee.patch
Patch79: 0005-wayland-dma-buf-Always-advertise-non-modifier-fallba.patch
Patch80: 0006-wayland-surface-Remove-unnecessary-NULL-check.patch
Patch81: 0007-wayland-dma-buf-Make-manager-object-a-GObject.patch
Patch82: 0008-wayland-dma-buf-Add-tranche-priorities.patch
Patch83: 0009-compositor-native-Track-what-Wayland-surface-is-a-sc.patch
Patch84: 0010-wayland-dma-buf-Move-should_send_modifiers-to-the-to.patch
Patch85: 0011-wayland-dma-buf-Add-support-for-scanout-surface-feed.patch
Patch86: 0012-wayland-dma-buf-Add-missing-wl_array_release.patch
Patch87: 0013-wayland-dma-buf-Fix-typos-in-struct-name.patch
Patch88: 0014-wayland-dma-buf-Free-feedback-in-surface_feedback_su.patch
Patch89: 0015-wayland-dma-buf-Only-advertise-supported-formats.patch
Patch90: 0016-wayland-dma-buf-Remove-redundant-error-check.patch
Patch91: 0017-egl-Don-t-set-an-error-when-there-is-none.patch
Patch92: 0018-wayland-dma-buf-Don-t-warn-if-there-was-no-render-no.patch
# RHEL-70872
Patch533: 0001-x11-iconcache-Turn-icons-from-WM_HINTS-pixmaps-to-ca.patch
@ -224,7 +244,7 @@ BuildRequires: pkgconfig(libdrm)
BuildRequires: pkgconfig(gbm)
BuildRequires: pkgconfig(wayland-server)
BuildRequires: pkgconfig(wayland-eglstream)
BuildRequires: pkgconfig(wayland-protocols)
BuildRequires: pkgconfig(wayland-protocols) >= 1.24
BuildRequires: json-glib-devel >= %{json_glib_version}
BuildRequires: libgudev1-devel
@ -320,6 +340,11 @@ desktop-file-validate %{buildroot}/%{_datadir}/applications/%{name}.desktop
%{_datadir}/mutter-%{mutter_api_version}/tests
%changelog
* Thu Nov 20 2025 Olivier Fourdan <ofourdan@redhat.com> - 40.9-31
- Backport linux-dmabuf v4 support to restore hardware acceleration
in Xwayland 24.1 with Mesa 25.2
Resolves: RHEL-129832
* Mon Nov 10 2025 Jonas Ådahl <jadahl@redhat.com> - 40.9-30
- Fix handling of more WM_HINTS window icon types
Resolves: RHEL-70872