summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Waters <matthew@centricular.com>2023-03-31 17:43:16 +1100
committerTim-Philipp Müller <tim@centricular.com>2024-03-18 17:44:50 +0100
commita81772f9f562129a31eab0456d7fad97b65d6b6b (patch)
tree16e9a9999071d2a660a86d60516aea6e64f2b47e
parent7d7ad5682b6b65f7326b258b96bdb2b9abfa6612 (diff)
vulkan/wayland: use xdg_wm_base when available
wl_shell is deprecated and has been removed from some compositors. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6396>
-rw-r--r--subprojects/gst-plugins-bad/gst-libs/gst/vulkan/meson.build22
-rw-r--r--subprojects/gst-plugins-bad/gst-libs/gst/vulkan/wayland/gstvkdisplay_wayland.c29
-rw-r--r--subprojects/gst-plugins-bad/gst-libs/gst/vulkan/wayland/gstvkdisplay_wayland_private.h39
-rw-r--r--subprojects/gst-plugins-bad/gst-libs/gst/vulkan/wayland/gstvkwindow_wayland.c129
-rw-r--r--subprojects/gst-plugins-bad/gst-libs/gst/vulkan/wayland/gstvkwindow_wayland.h3
5 files changed, 198 insertions, 24 deletions
diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/vulkan/meson.build b/subprojects/gst-plugins-bad/gst-libs/gst/vulkan/meson.build
index 8dd4bd9b5b..361ae6e887 100644
--- a/subprojects/gst-plugins-bad/gst-libs/gst/vulkan/meson.build
+++ b/subprojects/gst-plugins-bad/gst-libs/gst/vulkan/meson.build
@@ -173,12 +173,32 @@ if xcb_dep.found() and xkbcommon_dep.found() and xkbcommon_x11_dep.found() and c
endif
wayland_client_dep = dependency('wayland-client', version : '>=1.4', required : get_option('wayland'))
-if wayland_client_dep.found() and cc.has_header('vulkan/vulkan_wayland.h', dependencies : vulkan_dep)
+wayland_protocols_dep = dependency('wayland-protocols', version : '>= 1.15', required : get_option('wayland'))
+wayland_scanner = find_program('wayland-scanner', required: get_option('wayland'))
+if wayland_client_dep.found() and wayland_protocols_dep.found() and wayland_scanner.found() and cc.has_header('vulkan/vulkan_wayland.h', dependencies : vulkan_dep)
+ # Generate the XDG shell interface
+ wayland_protocols_basedir = wayland_protocols_dep.get_variable('pkgdatadir')
+ xdg_shell_xml_spec = join_paths(wayland_protocols_basedir, 'stable', 'xdg-shell', 'xdg-shell.xml')
+ xdg_shell_header = custom_target('xdg-shell-client-header',
+ command: [ wayland_scanner, 'client-header', '@INPUT@', '@OUTPUT@' ],
+ input: xdg_shell_xml_spec,
+ output: 'xdg-shell-client-protocol.h',
+ )
+ xdg_shell_code = custom_target('xdg-shell-client-code',
+ command: [ wayland_scanner, 'private-code', '@INPUT@', '@OUTPUT@' ],
+ input: xdg_shell_xml_spec,
+ output: 'xdg-shell-client-protocol.c',
+ )
+
vulkan_priv_sources += files(
'wayland/gstvkdisplay_wayland.c',
'wayland/gstvkwindow_wayland.c',
'wayland/wayland_event_source.c',
)
+ vulkan_priv_sources += [
+ xdg_shell_header,
+ xdg_shell_code,
+ ]
vulkan_wayland_sources += files(
'wayland/gstvkdisplay_wayland.c',
)
diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/vulkan/wayland/gstvkdisplay_wayland.c b/subprojects/gst-plugins-bad/gst-libs/gst/vulkan/wayland/gstvkdisplay_wayland.c
index 8f876e5fd7..071ad29c96 100644
--- a/subprojects/gst-plugins-bad/gst-libs/gst/vulkan/wayland/gstvkdisplay_wayland.c
+++ b/subprojects/gst-plugins-bad/gst-libs/gst/vulkan/wayland/gstvkdisplay_wayland.c
@@ -23,6 +23,7 @@
#endif
#include <gst/vulkan/wayland/gstvkdisplay_wayland.h>
+#include "gstvkdisplay_wayland_private.h"
#include "wayland_event_source.h"
@@ -30,7 +31,8 @@ GST_DEBUG_CATEGORY_STATIC (gst_vulkan_display_wayland_debug);
#define GST_CAT_DEFAULT gst_vulkan_display_wayland_debug
G_DEFINE_TYPE_WITH_CODE (GstVulkanDisplayWayland, gst_vulkan_display_wayland,
- GST_TYPE_VULKAN_DISPLAY, GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT,
+ GST_TYPE_VULKAN_DISPLAY, G_ADD_PRIVATE (GstVulkanDisplayWayland);
+ GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT,
"vulkandisplaywayland", 0, "Vulkan Wayland Display");
);
@@ -39,10 +41,23 @@ static gpointer gst_vulkan_display_wayland_get_handle (GstVulkanDisplay *
display);
static void
+handle_xdg_wm_base_ping (void *user_data, struct xdg_wm_base *xdg_wm_base,
+ uint32_t serial)
+{
+ xdg_wm_base_pong (xdg_wm_base, serial);
+}
+
+static const struct xdg_wm_base_listener xdg_wm_base_listener = {
+ handle_xdg_wm_base_ping
+};
+
+static void
registry_handle_global (void *data, struct wl_registry *registry,
uint32_t name, const char *interface, uint32_t version)
{
GstVulkanDisplayWayland *display = data;
+ GstVulkanDisplayWaylandPrivate *priv =
+ gst_vulkan_display_wayland_get_instance_private (display);
GST_TRACE_OBJECT (display, "registry_handle_global with registry %p, "
"interface %s, version %u", registry, interface, version);
@@ -55,6 +70,11 @@ registry_handle_global (void *data, struct wl_registry *registry,
wl_registry_bind (registry, name, &wl_subcompositor_interface, 1);
} else if (g_strcmp0 (interface, "wl_shell") == 0) {
display->shell = wl_registry_bind (registry, name, &wl_shell_interface, 1);
+ } else if (g_strcmp0 (interface, "xdg_wm_base") == 0) {
+ priv->xdg_wm_base =
+ wl_registry_bind (registry, name, &xdg_wm_base_interface, 1);
+ xdg_wm_base_add_listener (priv->xdg_wm_base, &xdg_wm_base_listener,
+ display);
}
}
@@ -83,6 +103,13 @@ _connect_listeners (GstVulkanDisplayWayland * display)
wl_display_roundtrip (display->display);
}
+GstVulkanDisplayWaylandPrivate *
+gst_vulkan_display_wayland_get_private (GstVulkanDisplayWayland *
+ display_wayland)
+{
+ return gst_vulkan_display_wayland_get_instance_private (display_wayland);
+}
+
static void
gst_vulkan_display_wayland_class_init (GstVulkanDisplayWaylandClass * klass)
{
diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/vulkan/wayland/gstvkdisplay_wayland_private.h b/subprojects/gst-plugins-bad/gst-libs/gst/vulkan/wayland/gstvkdisplay_wayland_private.h
new file mode 100644
index 0000000000..3acff2a067
--- /dev/null
+++ b/subprojects/gst-plugins-bad/gst-libs/gst/vulkan/wayland/gstvkdisplay_wayland_private.h
@@ -0,0 +1,39 @@
+/*
+ * GStreamer
+ * Copyright (C) 2023 Matthew Waters <matthew@centricular.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <gst/gst.h>
+#include "gstvkdisplay_wayland.h"
+#include <wayland-client.h>
+#include "gst/vulkan/xdg-shell-client-protocol.h"
+
+G_BEGIN_DECLS
+
+typedef struct _GstVulkanDisplayWaylandPrivate GstVulkanDisplayWaylandPrivate;
+
+struct _GstVulkanDisplayWaylandPrivate
+{
+ struct xdg_wm_base *xdg_wm_base;
+};
+
+G_GNUC_INTERNAL
+GstVulkanDisplayWaylandPrivate *
+gst_vulkan_display_wayland_get_private (GstVulkanDisplayWayland * display_wayland);
+
+G_END_DECLS
diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/vulkan/wayland/gstvkwindow_wayland.c b/subprojects/gst-plugins-bad/gst-libs/gst/vulkan/wayland/gstvkwindow_wayland.c
index d133486456..5317a739cf 100644
--- a/subprojects/gst-plugins-bad/gst-libs/gst/vulkan/wayland/gstvkwindow_wayland.c
+++ b/subprojects/gst-plugins-bad/gst-libs/gst/vulkan/wayland/gstvkwindow_wayland.c
@@ -28,6 +28,7 @@
#include <gst/vulkan/wayland/gstvkdisplay_wayland.h>
#include "gstvkwindow_wayland.h"
+#include "gstvkdisplay_wayland_private.h"
#include "wayland_event_source.h"
@@ -60,6 +61,79 @@ gst_vulkan_window_wayland_get_presentation_support (GstVulkanWindow *
window, GstVulkanDevice * device, guint32 queue_family_idx);
static void
+handle_xdg_toplevel_close (void *data, struct xdg_toplevel *xdg_toplevel)
+{
+ GstVulkanWindow *window = data;
+
+ GST_DEBUG ("XDG toplevel got a \"close\" event.");
+
+ gst_vulkan_window_close (window);
+}
+
+static void
+handle_xdg_toplevel_configure (void *data, struct xdg_toplevel *xdg_toplevel,
+ int32_t width, int32_t height, struct wl_array *states)
+{
+#if 0
+ GstVulkanWindowWayland *window_wl = data;
+ const uint32_t *state;
+#endif
+ GST_DEBUG ("configure event on XDG toplevel %p, %ix%i", xdg_toplevel,
+ width, height);
+#if 0
+ // TODO: deal with resizes
+ if (width > 0 && height > 0)
+ window_resize (window_egl, width, height);
+#endif
+}
+
+static const struct xdg_toplevel_listener xdg_toplevel_listener = {
+ handle_xdg_toplevel_configure,
+ handle_xdg_toplevel_close,
+};
+
+static void
+handle_xdg_surface_configure (void *data, struct xdg_surface *xdg_surface,
+ uint32_t serial)
+{
+ xdg_surface_ack_configure (xdg_surface, serial);
+}
+
+static const struct xdg_surface_listener xdg_surface_listener = {
+ handle_xdg_surface_configure,
+};
+
+static void
+create_xdg_surface (GstVulkanWindowWayland * window_wl)
+{
+ GstVulkanDisplayWayland *display =
+ GST_VULKAN_DISPLAY_WAYLAND (GST_VULKAN_WINDOW (window_wl)->display);
+ GstVulkanDisplayWaylandPrivate *display_priv =
+ gst_vulkan_display_wayland_get_private (display);
+ struct xdg_surface *xdg_surface;
+ struct xdg_toplevel *xdg_toplevel;
+
+ GST_DEBUG ("Creating surfaces with XDG-shell");
+
+ /* First create the XDG surface */
+ xdg_surface = xdg_wm_base_get_xdg_surface (display_priv->xdg_wm_base,
+ window_wl->surface);
+ xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, window_wl);
+
+ /* Then the XDG top-level */
+ xdg_toplevel = xdg_surface_get_toplevel (xdg_surface);
+ xdg_toplevel_set_title (xdg_toplevel, "Vulkan Renderer");
+ xdg_toplevel_add_listener (xdg_toplevel, &xdg_toplevel_listener, window_wl);
+
+ /* Commit the xdg_surface state */
+ wl_surface_commit (window_wl->surface);
+
+ /* And save them into the fields */
+ window_wl->xdg_surface = xdg_surface;
+ window_wl->xdg_toplevel = xdg_toplevel;
+}
+
+static void
handle_ping (void *data, struct wl_shell_surface *shell_surface,
uint32_t serial)
{
@@ -98,18 +172,37 @@ static const struct wl_shell_surface_listener shell_surface_listener = {
};
static void
+create_wl_shell_surface (GstVulkanWindowWayland * window_wl)
+{
+ GstVulkanDisplayWayland *display =
+ GST_VULKAN_DISPLAY_WAYLAND (GST_VULKAN_WINDOW (window_wl)->display);
+
+ GST_DEBUG ("Creating surfaces with wl_shell");
+
+ window_wl->shell_surface =
+ wl_shell_get_shell_surface (display->shell, window_wl->surface);
+ if (window_wl->queue)
+ wl_proxy_set_queue ((struct wl_proxy *) window_wl->shell_surface,
+ window_wl->queue);
+
+ wl_shell_surface_add_listener (window_wl->shell_surface,
+ &shell_surface_listener, window_wl);
+
+ wl_shell_surface_set_title (window_wl->shell_surface, "Vulkan Renderer");
+ wl_shell_surface_set_toplevel (window_wl->shell_surface);
+ GST_DEBUG_OBJECT (window_wl, "Successfully created shell surface %p",
+ window_wl->shell_surface);
+}
+
+static void
destroy_surfaces (GstVulkanWindowWayland * window_wl)
{
GST_DEBUG_OBJECT (window_wl, "destroying created surfaces");
- if (window_wl->shell_surface) {
- wl_shell_surface_destroy (window_wl->shell_surface);
- window_wl->shell_surface = NULL;
- }
- if (window_wl->surface) {
- wl_surface_destroy (window_wl->surface);
- window_wl->surface = NULL;
- }
+ g_clear_pointer (&window_wl->xdg_toplevel, xdg_toplevel_destroy);
+ g_clear_pointer (&window_wl->xdg_surface, xdg_surface_destroy);
+ g_clear_pointer (&window_wl->shell_surface, wl_shell_surface_destroy);
+ g_clear_pointer (&window_wl->surface, wl_surface_destroy);
}
static void
@@ -117,6 +210,8 @@ create_surfaces (GstVulkanWindowWayland * window_wl)
{
GstVulkanDisplayWayland *display =
GST_VULKAN_DISPLAY_WAYLAND (GST_VULKAN_WINDOW (window_wl)->display);
+ GstVulkanDisplayWaylandPrivate *display_priv =
+ gst_vulkan_display_wayland_get_private (display);
gint width, height;
if (!window_wl->surface) {
@@ -126,20 +221,10 @@ create_surfaces (GstVulkanWindowWayland * window_wl)
window_wl->queue);
}
- if (!window_wl->shell_surface) {
- window_wl->shell_surface =
- wl_shell_get_shell_surface (display->shell, window_wl->surface);
- if (window_wl->queue)
- wl_proxy_set_queue ((struct wl_proxy *) window_wl->shell_surface,
- window_wl->queue);
-
- wl_shell_surface_add_listener (window_wl->shell_surface,
- &shell_surface_listener, window_wl);
-
- wl_shell_surface_set_title (window_wl->shell_surface, "Vulkan Renderer");
- wl_shell_surface_set_toplevel (window_wl->shell_surface);
- GST_DEBUG_OBJECT (window_wl, "Successfully created shell surface %p",
- window_wl->shell_surface);
+ if (display_priv->xdg_wm_base) {
+ create_xdg_surface (window_wl);
+ } else {
+ create_wl_shell_surface (window_wl);
}
if (window_wl->window_width > 0)
diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/vulkan/wayland/gstvkwindow_wayland.h b/subprojects/gst-plugins-bad/gst-libs/gst/vulkan/wayland/gstvkwindow_wayland.h
index 405d8c76f9..f773f6411b 100644
--- a/subprojects/gst-plugins-bad/gst-libs/gst/vulkan/wayland/gstvkwindow_wayland.h
+++ b/subprojects/gst-plugins-bad/gst-libs/gst/vulkan/wayland/gstvkwindow_wayland.h
@@ -54,6 +54,9 @@ struct _GstVulkanWindowWayland {
struct wl_shell_surface *shell_surface;
struct wl_callback *callback;
+ struct xdg_surface *xdg_surface;
+ struct xdg_toplevel *xdg_toplevel;
+
int window_width, window_height;
GSource *wl_source;