diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index 9ba83bf26e636..b6012fe6af582 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -6014,7 +6014,10 @@ them. ``--wayland-disable-vsync=`` Disable mpv's internal vsync for Wayland-based video output (default: no). This is mainly useful for benchmarking wayland VOs when combined with - ``video-sync=display-desync``, ``--audio=no``, and ``--untimed=yes``. + ``video-sync=display-desync``, ``--audio=no``, and ``--untimed=yes``. This + option has no affect if using ``--gpu-api=vulkan`` on a compositor that + supports the commit-timing and fifo protocols since mpv's internal vsync is + not used at all in that case. ``--wayland-edge-pixels-pointer=`` Defines the size of an edge border (default: 16) to initiate client side diff --git a/video/out/meson.build b/video/out/meson.build index de93508217e0b..00681687c6245 100644 --- a/video/out/meson.build +++ b/video/out/meson.build @@ -11,7 +11,8 @@ protocols = [[wl_protocol_dir, 'stable/presentation-time/presentation-time.xml'] wl_protocols_source = [] wl_protocols_headers = [] -foreach v: ['1.32'] +# TODO: bump this to 1.38 when it comes out +foreach v: ['1.32', '1.37'] features += {'wayland-protocols-' + v.replace('.', '-'): wayland['deps'][2].version().version_compare('>=' + v)} endforeach @@ -21,6 +22,11 @@ if features['wayland-protocols-1-32'] [wl_protocol_dir, 'unstable/tablet/tablet-unstable-v2.xml']] # required by cursor-shape endif +if features['wayland-protocols-1-37'] + protocols += [[wl_protocol_dir, 'staging/commit-timing/commit-timing-v1.xml'], + [wl_protocol_dir, 'staging/fifo/fifo-v1.xml']] +endif + foreach p: protocols xml = join_paths(p) wl_protocols_source += custom_target(xml.underscorify() + '_c', diff --git a/video/out/vulkan/context_wayland.c b/video/out/vulkan/context_wayland.c index 700822c9a49a1..377af87cca885 100644 --- a/video/out/vulkan/context_wayland.c +++ b/video/out/vulkan/context_wayland.c @@ -36,7 +36,7 @@ static void wayland_vk_swap_buffers(struct ra_ctx *ctx) { struct vo_wayland_state *wl = ctx->vo->wl; - if (!wl->opts->wl_disable_vsync) + if (!wl->has_commit_timing || !wl->has_fifo || !wl->opts->wl_disable_vsync) vo_wayland_wait_frame(wl); if (wl->use_present) @@ -63,6 +63,7 @@ static bool wayland_vk_init(struct ra_ctx *ctx) { struct priv *p = ctx->priv = talloc_zero(ctx, struct priv); struct mpvk_ctx *vk = &p->vk; + struct vo_wayland_state *wl = ctx->vo->wl; int msgl = ctx->opts.probing ? MSGL_V : MSGL_ERR; if (!mpvk_init(vk, ctx, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME)) @@ -90,13 +91,14 @@ static bool wayland_vk_init(struct ra_ctx *ctx) goto error; } - /* Because in Wayland clients render whenever they receive a callback from - * the compositor, and the fact that the compositor usually stops sending - * callbacks once the surface is no longer visible, using FIFO here would - * mean the entire player would block on acquiring swapchain images. Hence, - * use MAILBOX to guarantee that there'll always be a swapchain image and - * the player won't block waiting on those */ - if (!ra_vk_ctx_init(ctx, vk, params, VK_PRESENT_MODE_MAILBOX_KHR)) + /* If the Wayland compositor does not support commit-timing and fifo + * protocols, the compositor will stop sending callbacks if the surface is + * no longer visible. That means using FIFO would block the entire player + * which is just not good. Use MAILBOX for those compositors to avoid + * indefinite blocking. */ + VkPresentModeKHR mode = wl->has_commit_timing && wl->has_fifo ? VK_PRESENT_MODE_FIFO_KHR : + VK_PRESENT_MODE_MAILBOX_KHR; + if (!ra_vk_ctx_init(ctx, vk, params, mode)) goto error; ra_add_native_resource(ctx->ra, "wl", ctx->vo->wl->display); diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c index d40206cee7e11..2c1b642094113 100644 --- a/video/out/wayland_common.c +++ b/video/out/wayland_common.c @@ -56,6 +56,11 @@ #include "cursor-shape-v1.h" #endif +#if HAVE_WAYLAND_PROTOCOLS_1_37 +#include "commit-timing-v1.h" +#include "fifo-v1.h" +#endif + #if WAYLAND_VERSION_MAJOR > 1 || WAYLAND_VERSION_MINOR >= 22 #define HAVE_WAYLAND_1_22 #endif @@ -1568,6 +1573,11 @@ static void registry_handle_add(void *data, struct wl_registry *reg, uint32_t id wl->shm = wl_registry_bind(reg, id, &wl_shm_interface, ver); } + if (!strcmp(interface, wp_commit_timing_manager_v1_interface.name) && found++) { + ver = 1; + wl->has_commit_timing = true; + } + if (!strcmp(interface, wp_content_type_manager_v1_interface.name) && found++) { ver = 1; wl->content_type_manager = wl_registry_bind(reg, id, &wp_content_type_manager_v1_interface, ver); @@ -1578,6 +1588,11 @@ static void registry_handle_add(void *data, struct wl_registry *reg, uint32_t id wl->single_pixel_manager = wl_registry_bind(reg, id, &wp_single_pixel_buffer_manager_v1_interface, ver); } + if (!strcmp(interface, wp_fifo_manager_v1_interface.name) && found++) { + ver = 1; + wl->has_fifo = true; + } + if (!strcmp(interface, wp_fractional_scale_manager_v1_interface.name) && found++) { ver = 1; wl->fractional_scale_manager = wl_registry_bind(reg, id, &wp_fractional_scale_manager_v1_interface, ver); diff --git a/video/out/wayland_common.h b/video/out/wayland_common.h index 23cca5b8e9594..654b350b80497 100644 --- a/video/out/wayland_common.h +++ b/video/out/wayland_common.h @@ -85,6 +85,9 @@ struct vo_wayland_state { int timeout_count; int wakeup_pipe[2]; + /* commit-timing */ + bool has_commit_timing; + /* content-type */ struct wp_content_type_manager_v1 *content_type_manager; struct wp_content_type_v1 *content_type; @@ -94,6 +97,9 @@ struct vo_wayland_state { /* TODO: unvoid these if required wayland protocols is bumped to 1.32+ */ void *cursor_shape_manager; + /* fifo */ + bool has_fifo; + /* fractional-scale */ struct wp_fractional_scale_manager_v1 *fractional_scale_manager; struct wp_fractional_scale_v1 *fractional_scale;