From a62f71bfbeb8f35bf5f09f12e48b63505c475750 Mon Sep 17 00:00:00 2001 From: LaserEyess Date: Tue, 15 Nov 2022 20:52:56 -0500 Subject: [PATCH] vo_dmabuf_wayland: use single-pixel-buffer-v1 The new single-pixel-buffer protocol is designed to optimize the case for using a solid color as an underlay wl_surface. It works the same as the wl_shm 1x1 pixel trick currently used, but it allows the compositor to make optimizations with more certainty than the wl_shm trick. --- generated/wayland/meson.build | 3 ++- video/out/vo_dmabuf_wayland.c | 48 ++++++++++++++++++++++------------- video/out/wayland_common.c | 15 +++++++++++ video/out/wayland_common.h | 4 +++ wscript_build.py | 7 +++++ 5 files changed, 58 insertions(+), 19 deletions(-) diff --git a/generated/wayland/meson.build b/generated/wayland/meson.build index 919a280107..423fc7c76e 100644 --- a/generated/wayland/meson.build +++ b/generated/wayland/meson.build @@ -12,7 +12,8 @@ features += {'wayland_protocols_1_24': wayland['deps'][2].version().version_comp features += {'wayland_protocols_1_27': wayland['deps'][2].version().version_compare('>=1.27')} if features['wayland_protocols_1_27'] - protocols += [[wl_protocol_dir, 'staging/content-type/content-type-v1.xml']] + protocols += [[wl_protocol_dir, 'staging/content-type/content-type-v1.xml'], + [wl_protocol_dir, 'staging/single-pixel-buffer/single-pixel-buffer-v1.xml']] endif foreach p: protocols diff --git a/video/out/vo_dmabuf_wayland.c b/video/out/vo_dmabuf_wayland.c index 24ced832ab..e6ce97f643 100644 --- a/video/out/vo_dmabuf_wayland.c +++ b/video/out/vo_dmabuf_wayland.c @@ -41,9 +41,15 @@ #include "present_sync.h" #include "wayland_common.h" #include "wlbuf_pool.h" + +// Generated from wayland-protocols #include "generated/wayland/linux-dmabuf-unstable-v1.h" #include "generated/wayland/viewporter.h" +#if HAVE_WAYLAND_PROTOCOLS_1_27 +#include "generated/wayland/single-pixel-buffer-v1.h" +#endif + struct priv { struct mp_log *log; struct ra_ctx *ctx; @@ -238,24 +244,6 @@ static int query_format(struct vo *vo, int format) static int reconfig(struct vo *vo, struct mp_image_params *params) { - struct priv *p = vo->priv; - struct vo_wayland_state *wl = vo->wl; - - if (!p->solid_buffer_pool) { - int width = 1; - int height = 1; - int stride = MP_ALIGN_UP(width * 4, 16); - int fd = vo_wayland_allocate_memfd(vo, stride); - if (fd < 0) - return VO_ERROR; - p->solid_buffer_pool = wl_shm_create_pool(wl->shm, fd, height * stride); - if (!p->solid_buffer_pool) - return VO_ERROR; - p->solid_buffer = wl_shm_pool_create_buffer(p->solid_buffer_pool, 0, width, height, stride, WL_SHM_FORMAT_XRGB8888); - if (!p->solid_buffer) - return VO_ERROR; - wl_surface_attach(wl->surface, p->solid_buffer, 0, 0); - } if (!vo_wayland_reconfig(vo)) return VO_ERROR; @@ -354,6 +342,30 @@ static int preinit(struct vo *vo) return VO_ERROR; } + + if (vo->wl->single_pixel_manager) { +#if HAVE_WAYLAND_PROTOCOLS_1_27 + p->solid_buffer = wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer( + vo->wl->single_pixel_manager, 0, 0, 0, UINT32_MAX); /* R, G, B, A */ +#endif + } else { + int width = 1; + int height = 1; + int stride = MP_ALIGN_UP(width * 4, 16); + int fd = vo_wayland_allocate_memfd(vo, stride); + if (fd < 0) + return VO_ERROR; + p->solid_buffer_pool = wl_shm_create_pool(vo->wl->shm, fd, height * stride); + if (!p->solid_buffer_pool) + return VO_ERROR; + p->solid_buffer = wl_shm_pool_create_buffer( + p->solid_buffer_pool, 0, width, height, stride, WL_SHM_FORMAT_XRGB8888); + } + if (!p->solid_buffer) + return VO_ERROR; + + wl_surface_attach(vo->wl->surface, p->solid_buffer, 0, 0); + vo->hwdec_devs = hwdec_devices_create(); hwdec_devices_set_loader(vo->hwdec_devs, call_request_hwdec_api, vo); assert(!p->hwdec_ctx.ra); diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c index ebcce69df2..7987dcef44 100644 --- a/video/out/wayland_common.c +++ b/video/out/wayland_common.c @@ -44,6 +44,7 @@ #if HAVE_WAYLAND_PROTOCOLS_1_27 #include "generated/wayland/content-type-v1.h" +#include "generated/wayland/single-pixel-buffer-v1.h" #endif #if WAYLAND_VERSION_MAJOR > 1 || WAYLAND_VERSION_MINOR >= 20 @@ -1240,6 +1241,10 @@ static void registry_handle_add(void *data, struct wl_registry *reg, uint32_t id if (!strcmp(interface, wp_content_type_manager_v1_interface.name) && found++) { wl->content_type_manager = wl_registry_bind(reg, id, &wp_content_type_manager_v1_interface, 1); } + + if (!strcmp(interface, wp_single_pixel_buffer_manager_v1_interface.name) && found++) { + wl->single_pixel_manager = wl_registry_bind(reg, id, &wp_single_pixel_buffer_manager_v1_interface, 1); + } #endif if (!strcmp(interface, wp_presentation_interface.name) && found++) { @@ -2007,6 +2012,11 @@ int vo_wayland_init(struct vo *vo) MP_VERBOSE(wl, "Compositor doesn't support the %s protocol!\n", wp_content_type_manager_v1_interface.name); } + + if (!wl->single_pixel_manager) { + MP_VERBOSE(wl, "Compositor doesn't support the %s protocol!\n", + wp_single_pixel_buffer_manager_v1_interface.name); + } #endif if (wl->dnd_devman && wl->seat) { @@ -2225,6 +2235,11 @@ void vo_wayland_uninit(struct vo *vo) if (wl->shm) wl_shm_destroy(wl->shm); +#if HAVE_WAYLAND_PROTOCOLS_1_27 + if (wl->single_pixel_manager) + wp_single_pixel_buffer_manager_v1_destroy(wl->single_pixel_manager); +#endif + if (wl->surface) wl_surface_destroy(wl->surface); diff --git a/video/out/wayland_common.h b/video/out/wayland_common.h index 627ea0d057..4f505b903b 100644 --- a/video/out/wayland_common.h +++ b/video/out/wayland_common.h @@ -106,6 +106,10 @@ struct vo_wayland_state { int64_t refresh_interval; bool use_present; + /* single-pixel-buffer */ + /* TODO: unvoid this if required wayland-protocols is bumped to 1.27+ */ + void *single_pixel_manager; + /* xdg-decoration */ struct zxdg_decoration_manager_v1 *xdg_decoration_manager; struct zxdg_toplevel_decoration_v1 *xdg_toplevel_decoration; diff --git a/wscript_build.py b/wscript_build.py index 1621b94b97..46138982be 100644 --- a/wscript_build.py +++ b/wscript_build.py @@ -147,6 +147,12 @@ def build(ctx): ctx.wayland_protocol_header(proto_dir = ctx.env.WL_PROTO_DIR, protocol = "staging/content-type/content-type-v1", target = "generated/wayland/content-type-v1.h") + ctx.wayland_protocol_code(proto_dir = ctx.env.WL_PROTO_DIR, + protocol = "staging/single-pixel-buffer/single-pixel-buffer-v1", + target = "generated/wayland/single-pixel-buffer-v1.c") + ctx.wayland_protocol_header(proto_dir = ctx.env.WL_PROTO_DIR, + protocol = "staging/single-pixel-buffer/single-pixel-buffer-v1", + target = "generated/wayland/single-pixel-buffer-v1.h") ctx(features = "ebml_header", target = "generated/ebml_types.h") ctx(features = "ebml_definitions", target = "generated/ebml_defs.inc") @@ -548,6 +554,7 @@ def build(ctx): ( "video/out/vulkan/context_xlib.c", "vulkan && x11" ), ( "video/out/vulkan/utils.c", "vulkan" ), ( "video/out/w32_common.c", "win32-desktop" ), + ( "generated/wayland/single-pixel-buffer-v1.c", "wayland-protocols-1-27" ), ( "generated/wayland/content-type-v1.c", "wayland-protocols-1-27" ), ( "generated/wayland/idle-inhibit-unstable-v1.c", "wayland" ), ( "generated/wayland/presentation-time.c", "wayland" ),