diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index 843f7d926c607..b8d6aac2f3013 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -6024,7 +6024,10 @@ them. Controls whether to use mpv's internal vsync for Wayland-base video outputs (default: ``auto``). This is mainly useful for benchmarking wayland VOs when combined with ``video-sync=display-desync``, ``--audio=no``, and - ``--untimed=yes``. + ``--untimed=yes``. The special ``auto`` value will disable the internal + vsync if the compositor supports the commit-timing and fifo protocols when + using ``--gpu-api=vulkan``. In any other situation, it is exactly the same + as ``yes``. ``--wayland-present=`` Enable the use of wayland's presentation time protocol for more accurate diff --git a/video/out/meson.build b/video/out/meson.build index 95ebd4a8cdbc4..1443905dbbaa4 100644 --- a/video/out/meson.build +++ b/video/out/meson.build @@ -12,7 +12,7 @@ protocols = [[wl_protocol_dir, 'stable/presentation-time/presentation-time.xml'] wl_protocols_source = [] wl_protocols_headers = [] -foreach v: ['1.32'] +foreach v: ['1.32', '1.38'] features += {'wayland-protocols-' + v.replace('.', '-'): wayland['deps'][2].version().version_compare('>=' + v)} endforeach @@ -22,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-38'] + 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 eae5d25e7d3c4..f06e150fbde14 100644 --- a/video/out/vulkan/context_wayland.c +++ b/video/out/vulkan/context_wayland.c @@ -25,6 +25,7 @@ struct priv { struct mpvk_ctx vk; + bool use_fifo; }; static bool wayland_vk_check_visible(struct ra_ctx *ctx) @@ -35,8 +36,9 @@ static bool wayland_vk_check_visible(struct ra_ctx *ctx) static void wayland_vk_swap_buffers(struct ra_ctx *ctx) { struct vo_wayland_state *wl = ctx->vo->wl; + struct priv *p = ctx->priv; - if (wl->opts->wl_internal_vsync) + if ((!p->use_fifo && wl->opts->wl_internal_vsync == 1) || wl->opts->wl_internal_vsync == 2) vo_wayland_wait_frame(wl); if (wl->use_present) @@ -63,6 +65,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 +93,13 @@ 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, fifo, and + * presentation time protocols, the compositor will stop sending callbacks + * if the surface is no longer visible. This means using FIFO would block + * the entire vo thread which is just not good. Use MAILBOX for those + * compositors to avoid indefinite blocking. */ + p->use_fifo = wl->has_commit_timing && wl->has_fifo && wl->use_present; + if (!ra_vk_ctx_init(ctx, vk, params, p->use_fifo ? VK_PRESENT_MODE_FIFO_KHR : VK_PRESENT_MODE_MAILBOX_KHR)) 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 65037e890cad7..c1f2861071d88 100644 --- a/video/out/wayland_common.c +++ b/video/out/wayland_common.c @@ -59,6 +59,11 @@ #include "cursor-shape-v1.h" #endif +#if HAVE_WAYLAND_PROTOCOLS_1_38 +#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 @@ -1720,6 +1725,18 @@ 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 HAVE_WAYLAND_PROTOCOLS_1_38 + if (!strcmp(interface, wp_commit_timing_manager_v1_interface.name) && found++) { + ver = 1; + wl->has_commit_timing = true; + } + + if (!strcmp(interface, wp_fifo_manager_v1_interface.name) && found++) { + ver = 1; + wl->has_fifo = true; + } +#endif + 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 abce364cd5372..e124d10c65597 100644 --- a/video/out/wayland_common.h +++ b/video/out/wayland_common.h @@ -103,6 +103,9 @@ struct vo_wayland_state { int primaries_map[PL_COLOR_PRIM_COUNT]; int transfer_map[PL_COLOR_TRC_COUNT]; + /* commit-timing */ + bool has_commit_timing; + /* content-type */ struct wp_content_type_manager_v1 *content_type_manager; struct wp_content_type_v1 *content_type; @@ -112,6 +115,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;