From bedca07a021863d264e7c4c471cc30102899500f Mon Sep 17 00:00:00 2001 From: dudemanguy Date: Thu, 10 Oct 2019 14:14:40 -0500 Subject: wayland: add presentation time Use ust/msc/refresh values from wayland's presentation time in mpv's ra_swapchain_fns.get_vsync for the wayland contexts. --- video/out/vulkan/context_wayland.c | 81 +++++++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 2 deletions(-) (limited to 'video/out/vulkan/context_wayland.c') diff --git a/video/out/vulkan/context_wayland.c b/video/out/vulkan/context_wayland.c index 783509e4a1..d3da628137 100644 --- a/video/out/vulkan/context_wayland.c +++ b/video/out/vulkan/context_wayland.c @@ -22,6 +22,9 @@ #include "context.h" #include "utils.h" +// Generated from presentation-time.xml +#include "video/out/wayland/presentation-time.h" + struct priv { struct mpvk_ctx vk; }; @@ -37,19 +40,92 @@ static void frame_callback(void *data, struct wl_callback *callback, uint32_t ti wl->frame_callback = wl_surface_frame(wl->surface); wl_callback_add_listener(wl->frame_callback, &frame_listener, wl); - wl->callback_wait = false; + wl->frame_wait = false; } static const struct wl_callback_listener frame_listener = { frame_callback, }; +static const struct wp_presentation_feedback_listener feedback_listener; + +static void feedback_sync_output(void *data, struct wp_presentation_feedback *fback, + struct wl_output *output) +{ +} + +static void feedback_presented(void *data, struct wp_presentation_feedback *fback, + uint32_t tv_sec_hi, uint32_t tv_sec_lo, + uint32_t tv_nsec, uint32_t refresh_nsec, + uint32_t seq_hi, uint32_t seq_lo, + uint32_t flags) +{ + struct vo_wayland_state *wl = data; + wp_presentation_feedback_destroy(fback); + vo_wayland_sync_shift(wl); + + // Very similar to oml_sync_control, in this case we assume that every + // time the compositor receives feedback, a buffer swap has been already + // been performed. + // + // Notes: + // - tv_sec_lo + tv_sec_hi is the equivalent of oml's ust + // - seq_lo + seq_hi is the equivalent of oml's msc + // - these values are updated everytime the compositor receives feedback. + + int index = last_available_sync(wl); + if (index < 0) { + queue_new_sync(wl); + index = 0; + } + int64_t sec = (uint64_t) tv_sec_lo + ((uint64_t) tv_sec_hi << 32); + wl->sync[index].sbc = wl->user_sbc; + wl->sync[index].ust = sec * 1000000LL + (uint64_t) tv_nsec / 1000; + wl->sync[index].msc = (uint64_t) seq_lo + ((uint64_t) seq_hi << 32); + wl->sync[index].refresh_usec = (uint64_t)refresh_nsec/1000; + wl->sync[index].filled = true; +} + +static void feedback_discarded(void *data, struct wp_presentation_feedback *fback) +{ + wp_presentation_feedback_destroy(fback); +} + +static const struct wp_presentation_feedback_listener feedback_listener = { + feedback_sync_output, + feedback_presented, + feedback_discarded, +}; + static void wayland_vk_swap_buffers(struct ra_ctx *ctx) { struct vo_wayland_state *wl = ctx->vo->wl; + if (wl->presentation) { + wl->feedback = wp_presentation_feedback(wl->presentation, wl->surface); + wp_presentation_feedback_add_listener(wl->feedback, &feedback_listener, wl); + wl->user_sbc += 1; + int index = last_available_sync(wl); + if (index < 0) + queue_new_sync(wl); + } + vo_wayland_wait_frame(wl); - wl->callback_wait = true; + + if (wl->presentation) + wayland_sync_swap(wl); + + wl->frame_wait = true; +} + +static void wayland_vk_get_vsync(struct ra_ctx *ctx, struct vo_vsync_info *info) +{ + struct vo_wayland_state *wl = ctx->vo->wl; + if (wl->presentation) { + info->vsync_duration = wl->vsync_duration; + info->skipped_vsyncs = wl->last_skipped_vsyncs; + info->last_queue_display_time = wl->last_queue_display_time; + } } static void wayland_vk_uninit(struct ra_ctx *ctx) @@ -81,6 +157,7 @@ static bool wayland_vk_init(struct ra_ctx *ctx) struct ra_vk_ctx_params params = { .swap_buffers = wayland_vk_swap_buffers, + .get_vsync = wayland_vk_get_vsync, }; VkInstance inst = vk->vkinst->instance; -- cgit v1.2.3