gstwayland: Support wp_single_pixel_buffer_v1

This protocol does what it says on the box, avoiding the need for a 1x1
wl_shm buffer.

A wayland-projects wrap has been added for users who do not have v1.26
available.

This commit was partly authored by Robert Mader.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2662>
This commit is contained in:
Daniel Stone 2022-06-26 17:44:33 +01:00 committed by Nicolas Dufresne
parent 4fb284346e
commit 3a37778f69
5 changed files with 60 additions and 15 deletions

View file

@ -26,6 +26,7 @@
#include "fullscreen-shell-unstable-v1-client-protocol.h" #include "fullscreen-shell-unstable-v1-client-protocol.h"
#include "linux-dmabuf-unstable-v1-client-protocol.h" #include "linux-dmabuf-unstable-v1-client-protocol.h"
#include "single-pixel-buffer-v1-client-protocol.h"
#include "viewporter-client-protocol.h" #include "viewporter-client-protocol.h"
#include "xdg-shell-client-protocol.h" #include "xdg-shell-client-protocol.h"
@ -48,6 +49,7 @@ typedef struct _GstWlDisplayPrivate
struct wl_subcompositor *subcompositor; struct wl_subcompositor *subcompositor;
struct xdg_wm_base *xdg_wm_base; struct xdg_wm_base *xdg_wm_base;
struct zwp_fullscreen_shell_v1 *fullscreen_shell; struct zwp_fullscreen_shell_v1 *fullscreen_shell;
struct wp_single_pixel_buffer_manager_v1 *single_pixel_buffer;
struct wl_shm *shm; struct wl_shm *shm;
struct wp_viewporter *viewporter; struct wp_viewporter *viewporter;
struct zwp_linux_dmabuf_v1 *dmabuf; struct zwp_linux_dmabuf_v1 *dmabuf;
@ -146,6 +148,9 @@ gst_wl_display_finalize (GObject * gobject)
if (priv->fullscreen_shell) if (priv->fullscreen_shell)
zwp_fullscreen_shell_v1_release (priv->fullscreen_shell); zwp_fullscreen_shell_v1_release (priv->fullscreen_shell);
if (priv->single_pixel_buffer)
wp_single_pixel_buffer_manager_v1_destroy (priv->single_pixel_buffer);
if (priv->compositor) if (priv->compositor)
wl_compositor_destroy (priv->compositor); wl_compositor_destroy (priv->compositor);
@ -323,6 +328,10 @@ registry_handle_global (void *data, struct wl_registry *registry,
priv->dmabuf = priv->dmabuf =
wl_registry_bind (registry, id, &zwp_linux_dmabuf_v1_interface, 3); wl_registry_bind (registry, id, &zwp_linux_dmabuf_v1_interface, 3);
zwp_linux_dmabuf_v1_add_listener (priv->dmabuf, &dmabuf_listener, self); zwp_linux_dmabuf_v1_add_listener (priv->dmabuf, &dmabuf_listener, self);
} else if (g_strcmp0 (interface, "wp_single_pixel_buffer_manager_v1") == 0) {
priv->single_pixel_buffer =
wl_registry_bind (registry, id,
&wp_single_pixel_buffer_manager_v1_interface, 1);
} }
} }
@ -610,6 +619,14 @@ gst_wl_display_get_dmabuf_formats (GstWlDisplay * self)
return priv->dmabuf_formats; return priv->dmabuf_formats;
} }
struct wp_single_pixel_buffer_manager_v1 *
gst_wl_display_get_single_pixel_buffer_manager_v1 (GstWlDisplay * self)
{
GstWlDisplayPrivate *priv = gst_wl_display_get_instance_private (self);
return priv->single_pixel_buffer;
}
gboolean gboolean
gst_wl_display_has_own_display (GstWlDisplay * self) gst_wl_display_has_own_display (GstWlDisplay * self)
{ {

View file

@ -99,6 +99,9 @@ GArray *gst_wl_display_get_dmabuf_modifiers (GstWlDisplay * self);
GST_WL_API GST_WL_API
struct zwp_linux_dmabuf_v1 *gst_wl_display_get_dmabuf_v1 (GstWlDisplay * self); struct zwp_linux_dmabuf_v1 *gst_wl_display_get_dmabuf_v1 (GstWlDisplay * self);
GST_WL_API
struct wp_single_pixel_buffer_manager_v1 * gst_wl_display_get_single_pixel_buffer_manager_v1 (GstWlDisplay * self);
GST_WL_API GST_WL_API
gboolean gst_wl_display_has_own_display (GstWlDisplay * self); gboolean gst_wl_display_has_own_display (GstWlDisplay * self);

View file

@ -27,6 +27,7 @@
#include "gstwlwindow.h" #include "gstwlwindow.h"
#include "fullscreen-shell-unstable-v1-client-protocol.h" #include "fullscreen-shell-unstable-v1-client-protocol.h"
#include "single-pixel-buffer-v1-client-protocol.h"
#include "viewporter-client-protocol.h" #include "viewporter-client-protocol.h"
#include "xdg-shell-client-protocol.h" #include "xdg-shell-client-protocol.h"
@ -553,13 +554,11 @@ static void
gst_wl_window_update_borders (GstWlWindow * self) gst_wl_window_update_borders (GstWlWindow * self)
{ {
GstWlWindowPrivate *priv = gst_wl_window_get_instance_private (self); GstWlWindowPrivate *priv = gst_wl_window_get_instance_private (self);
GstVideoFormat format;
GstVideoInfo info;
gint width, height; gint width, height;
GstBuffer *buf; GstBuffer *buf;
struct wl_buffer *wlbuf; struct wl_buffer *wlbuf;
struct wp_single_pixel_buffer_manager_v1 *single_pixel;
GstWlBuffer *gwlbuf; GstWlBuffer *gwlbuf;
GstAllocator *alloc;
if (gst_wl_display_get_viewporter (priv->display)) { if (gst_wl_display_get_viewporter (priv->display)) {
wp_viewport_set_destination (priv->area_viewport, wp_viewport_set_destination (priv->area_viewport,
@ -579,19 +578,34 @@ gst_wl_window_update_borders (GstWlWindow * self)
height = priv->render_rectangle.h; height = priv->render_rectangle.h;
} }
/* we want WL_SHM_FORMAT_XRGB8888 */
format = GST_VIDEO_FORMAT_BGRx;
/* draw the area_subsurface */ /* draw the area_subsurface */
gst_video_info_set_format (&info, format, width, height); single_pixel =
gst_wl_display_get_single_pixel_buffer_manager_v1 (priv->display);
if (width == 1 && height == 1 && single_pixel) {
buf = gst_buffer_new_allocate (NULL, 1, NULL);
wlbuf =
wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer (single_pixel,
0, 0, 0, 0xffffffffU);
} else {
GstVideoFormat format;
GstVideoInfo info;
GstAllocator *alloc;
alloc = gst_shm_allocator_get (); /* we want WL_SHM_FORMAT_XRGB8888 */
format = GST_VIDEO_FORMAT_BGRx;
gst_video_info_set_format (&info, format, width, height);
alloc = gst_shm_allocator_get ();
buf = gst_buffer_new_allocate (alloc, info.size, NULL);
gst_buffer_memset (buf, 0, 0, info.size);
wlbuf =
gst_wl_shm_memory_construct_wl_buffer (gst_buffer_peek_memory (buf, 0),
priv->display, &info);
g_object_unref (alloc);
}
buf = gst_buffer_new_allocate (alloc, info.size, NULL);
gst_buffer_memset (buf, 0, 0, info.size);
wlbuf =
gst_wl_shm_memory_construct_wl_buffer (gst_buffer_peek_memory (buf, 0),
priv->display, &info);
gwlbuf = gst_buffer_add_wl_buffer (buf, wlbuf, priv->display); gwlbuf = gst_buffer_add_wl_buffer (buf, wlbuf, priv->display);
gst_wl_buffer_attach (gwlbuf, priv->area_surface_wrapper); gst_wl_buffer_attach (gwlbuf, priv->area_surface_wrapper);
wl_surface_damage_buffer (priv->area_surface_wrapper, 0, 0, G_MAXINT32, wl_surface_damage_buffer (priv->area_surface_wrapper, 0, 0, G_MAXINT32,
@ -600,7 +614,6 @@ gst_wl_window_update_borders (GstWlWindow * self)
/* at this point, the GstWlBuffer keeps the buffer /* at this point, the GstWlBuffer keeps the buffer
* alive and will free it on wl_buffer::release */ * alive and will free it on wl_buffer::release */
gst_buffer_unref (buf); gst_buffer_unref (buf);
g_object_unref (alloc);
} }
static void static void

View file

@ -1,6 +1,7 @@
wl_req = '>= 1.15' wl_req = '>= 1.15'
wl_client_dep = dependency('wayland-client', version: wl_req, required: get_option('wayland')) wl_client_dep = dependency('wayland-client', version: wl_req, required: get_option('wayland'))
libdrm_dep = dependency('libdrm', version: '>= 2.4.98', required: get_option('wayland')) libdrm_dep = dependency('libdrm', version: '>= 2.4.98', required: get_option('wayland'))
wl_proto_req = '>= 1.26'
wl_protocol_dep = dependency('wayland-protocols', version: wl_req, required: get_option('wayland')) wl_protocol_dep = dependency('wayland-protocols', version: wl_req, required: get_option('wayland'))
wl_scanner = find_program('wayland-scanner', required: get_option('wayland')) wl_scanner = find_program('wayland-scanner', required: get_option('wayland'))
# Also used in ext/wayland # Also used in ext/wayland
@ -38,7 +39,8 @@ if use_wayland
['viewporter', 'stable', ], ['viewporter', 'stable', ],
['linux-dmabuf', 'unstable', 'v1', ], ['linux-dmabuf', 'unstable', 'v1', ],
['fullscreen-shell', 'unstable', 'v1', ], ['fullscreen-shell', 'unstable', 'v1', ],
['xdg-shell', 'stable', ] ['xdg-shell', 'stable', ],
['single-pixel-buffer', 'staging', 'v1' ],
] ]
protocols_files = [] protocols_files = []

View file

@ -0,0 +1,10 @@
[wrap-file]
directory = wayland-protocols-1.32
source_url = https://gitlab.freedesktop.org/wayland/wayland-protocols/-/releases/1.32/downloads/wayland-protocols-1.32.tar.xz
source_filename = wayland-protocols-1.32.tar.xz
source_hash = 7459799d340c8296b695ef857c07ddef24c5a09b09ab6a74f7b92640d2b1ba11
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/wayland-protocols_1.32-1/wayland-protocols-1.32.tar.xz
wrapdb_version = 1.32-1
[provide]
wayland-protocols = wayland_protocols