From 489723916d7d6604b9125c9a069ecfc677d5c024 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Mon, 2 Oct 2023 21:11:44 -0400 Subject: [PATCH] wayland: Get format info for dmabufs For now, all we do with it is dump the formats if you set GDK_DEBUG=misc. In the future, this will be used when attaching dmabufs to subsurfaces. --- gdk/wayland/gdkdisplay-wayland.c | 130 +++++++++++++++++++++++++------ gdk/wayland/gdkdisplay-wayland.h | 11 +++ gdk/wayland/meson.build | 1 + 3 files changed, 119 insertions(+), 23 deletions(-) diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c index 5bd5b9b15f..da8a827517 100644 --- a/gdk/wayland/gdkdisplay-wayland.c +++ b/gdk/wayland/gdkdisplay-wayland.c @@ -24,6 +24,7 @@ #include #include #include +#include #ifdef HAVE_LINUX_MEMFD_H #include @@ -56,6 +57,7 @@ #include #include #include +#include "linux-dmabuf-unstable-v1-client-protocol.h" #include "wm-button-layout-translation.h" @@ -267,40 +269,108 @@ postpone_on_globals_closure (GdkWaylandDisplay *display_wayland, g_list_append (display_wayland->on_has_globals_closures, closure); } -static const char * -get_format_name (uint32_t format, - char name[10]) -{ - if (format == 0) - g_strlcpy (name, "ARGB8888", 10); - else if (format == 1) - g_strlcpy (name, "XRGB8888", 10); - else - g_snprintf (name, 10, "4cc %c%c%c%c", - (char) (format & 0xff), - (char) ((format >> 8) & 0xff), - (char) ((format >> 16) & 0xff), - (char) ((format >> 24) & 0xff)); - - return name; -} - - static void wl_shm_format (void *data, struct wl_shm *wl_shm, uint32_t format) { - char buf[10]; - - GDK_DEBUG (MISC, "supported pixel format %s (0x%X)", - get_format_name (format, buf), (guint) format); + GDK_DEBUG (MISC, "supported shm pixel format %.4s (0x%X)", + format == 0 ? "ARGB8888" + : (format == 1 ? "XRGB8888" + : (char *) &format), format); } static const struct wl_shm_listener wl_shm_listener = { wl_shm_format }; +static void +linux_dmabuf_done (void *data, + struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1) +{ + GDK_DEBUG (MISC, "dmabuf feedback done"); +} + +static void +linux_dmabuf_format_table (void *data, + struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1, + int32_t fd, + uint32_t size) +{ + GdkWaylandDisplay *display_wayland = data; + + display_wayland->linux_dmabuf_n_formats = size / 16; + display_wayland->linux_dmabuf_formats = mmap (NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); + + GDK_DEBUG (MISC, "got dmabuf format table (%lu entries)", display_wayland->linux_dmabuf_n_formats); +} + +static void +linux_dmabuf_main_device (void *data, + struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1, + struct wl_array *device) +{ + dev_t dev G_GNUC_UNUSED = *(dev_t *)device->data; + + GDK_DEBUG (MISC, "got dmabuf main device: %u %u", major (dev), minor (dev)); +} + +static void +linux_dmabuf_tranche_done (void *data, + struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1) +{ + GDK_DEBUG (MISC, "dmabuf feedback tranche done"); +} + +static void +linux_dmabuf_tranche_target_device (void *data, + struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1, + struct wl_array *device) +{ + dev_t dev G_GNUC_UNUSED = *(dev_t *)device->data; + + GDK_DEBUG (MISC, "got dmabuf tranche target device: %u %u", major (dev), minor (dev)); +} + +static void +linux_dmabuf_tranche_formats (void *data, + struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1, + struct wl_array *indices) +{ + GdkWaylandDisplay *display_wayland = data; + + GDK_DEBUG (MISC, "got dmabuf tranche formats (%lu entries):", indices->size / sizeof (guint16)); + guint16 *pos; + + wl_array_for_each (pos, indices) + { + LinuxDmabufFormat *fmt G_GNUC_UNUSED = &display_wayland->linux_dmabuf_formats[*pos]; + uint32_t f G_GNUC_UNUSED = fmt->fourcc; + uint64_t m G_GNUC_UNUSED = fmt->modifier; + GDK_DEBUG (MISC, " %.4s:%#" G_GINT64_MODIFIER "x", (char *) &f, m); + } +} + +static void +linux_dmabuf_tranche_flags (void *data, + struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1, + uint32_t flags) +{ + GDK_DEBUG (MISC, + "got dmabuf tranche flags: %s", + flags & ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SCANOUT ? "scanout" : ""); +} + +static const struct zwp_linux_dmabuf_feedback_v1_listener linux_dmabuf_feedback_listener = { + linux_dmabuf_done, + linux_dmabuf_format_table, + linux_dmabuf_main_device, + linux_dmabuf_tranche_done, + linux_dmabuf_tranche_target_device, + linux_dmabuf_tranche_formats, + linux_dmabuf_tranche_flags, +}; + static void server_decoration_manager_default_mode (void *data, struct org_kde_kwin_server_decoration_manager *manager, @@ -375,6 +445,16 @@ gdk_registry_handle_global (void *data, wl_registry_bind (display_wayland->wl_registry, id, &wl_shm_interface, 1); wl_shm_add_listener (display_wayland->shm, &wl_shm_listener, display_wayland); } + else if (strcmp (interface, "zwp_linux_dmabuf_v1") == 0 && version >= 4) + { + display_wayland->linux_dmabuf = + wl_registry_bind (display_wayland->wl_registry, id, &zwp_linux_dmabuf_v1_interface, version); + display_wayland->linux_dmabuf_feedback = + zwp_linux_dmabuf_v1_get_default_feedback (display_wayland->linux_dmabuf); + zwp_linux_dmabuf_feedback_v1_add_listener (display_wayland->linux_dmabuf_feedback, + &linux_dmabuf_feedback_listener, display_wayland); + _gdk_wayland_display_async_roundtrip (display_wayland); + } else if (strcmp (interface, "xdg_wm_base") == 0) { display_wayland->xdg_wm_base_id = id; @@ -719,6 +799,10 @@ gdk_wayland_display_dispose (GObject *object) g_clear_pointer (&display_wayland->xdg_activation, xdg_activation_v1_destroy); g_clear_pointer (&display_wayland->fractional_scale, wp_fractional_scale_manager_v1_destroy); g_clear_pointer (&display_wayland->viewporter, wp_viewporter_destroy); + g_clear_pointer (&display_wayland->linux_dmabuf, zwp_linux_dmabuf_v1_destroy); + g_clear_pointer (&display_wayland->linux_dmabuf_feedback, zwp_linux_dmabuf_feedback_v1_destroy); + if (display_wayland->linux_dmabuf_formats) + munmap (display_wayland->linux_dmabuf_formats, display_wayland->linux_dmabuf_n_formats * 16); g_clear_pointer (&display_wayland->shm, wl_shm_destroy); g_clear_pointer (&display_wayland->wl_registry, wl_registry_destroy); diff --git a/gdk/wayland/gdkdisplay-wayland.h b/gdk/wayland/gdkdisplay-wayland.h index 0758901e2f..b7566b2066 100644 --- a/gdk/wayland/gdkdisplay-wayland.h +++ b/gdk/wayland/gdkdisplay-wayland.h @@ -71,6 +71,13 @@ typedef enum _GdkWaylandShellVariant GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6 } GdkWaylandShellVariant; +typedef struct +{ + uint32_t fourcc; + uint32_t padding; + uint64_t modifier; +} LinuxDmabufFormat; + struct _GdkWaylandDisplay { GdkDisplay parent_instance; @@ -95,6 +102,10 @@ struct _GdkWaylandDisplay struct wl_registry *wl_registry; struct wl_compositor *compositor; struct wl_shm *shm; + struct zwp_linux_dmabuf_v1 *linux_dmabuf; + struct zwp_linux_dmabuf_feedback_v1 *linux_dmabuf_feedback; + gsize linux_dmabuf_n_formats; + LinuxDmabufFormat *linux_dmabuf_formats; struct xdg_wm_base *xdg_wm_base; struct zxdg_shell_v6 *zxdg_shell_v6; struct gtk_shell1 *gtk_shell; diff --git a/gdk/wayland/meson.build b/gdk/wayland/meson.build index c6e6236ca8..798c5a4995 100644 --- a/gdk/wayland/meson.build +++ b/gdk/wayland/meson.build @@ -67,6 +67,7 @@ proto_sources = [ ['idle-inhibit', 'unstable', 'v1', ], ['xdg-activation', 'staging', 'v1', ], ['fractional-scale', 'staging', 'v1', ], + ['linux-dmabuf', 'unstable', 'v1', ], ] gdk_wayland_gen_headers = []