summaryrefslogtreecommitdiffstats
path: root/video/out/vulkan/context_wayland.c
diff options
context:
space:
mode:
authorDudemanguy <random342@airmail.cc>2020-08-15 16:07:53 -0500
committerDudemanguy <random342@airmail.cc>2020-08-16 18:34:09 +0000
commite9cde72536b60fc1bad304aa02a4638f63de258b (patch)
treea9d0e23d788a83c77b0bd9c263fb95c3d5b01e6f /video/out/vulkan/context_wayland.c
parent8ec61c366a0e0fad0732102782ba182a75e7508c (diff)
downloadmpv-e9cde72536b60fc1bad304aa02a4638f63de258b.tar.bz2
mpv-e9cde72536b60fc1bad304aa02a4638f63de258b.tar.xz
wayland: refactor presentation time
The motivation for this change was a segfault caused by e107342 which has complicated reasons for occuring (i.e. I'm not 100% sure but I think it is a really weird race). The major part of this commit is moving the initialization of presentation listener to the frame_callback function. Calling it in swap_buffers worked fine but in practice it meant a lot of meaningless function calls if a window was hidden (the presentation would just be immediately discarded). By calling it in frame_callback, we ensure the listener is only created when it is possible to receive a presentation event. Of course calling the presentation listener in feedback_presented or feedback_discarded was considered, but ultimately these events are too slow. Receiving the ust/msc/sbc triplet here and then passing it to mpv results in higher vsync judder since there is (likely) not enough time before the next pageflip. By design, the frame callback is meant to give us as much time as possible before the next repaint so calling it here is probably optimal. Additionally, we can make better use of the feedback_discarded event. The wp_presentation_feedback should not be destroyed here. It will be taken care of either when we get feedback again or when the player quits. Instead what we can do is set a bool that tells wayland_sync_swap to update itself based on mp_time delta. In practice, the result is not any different than before, but it should be more understandable what is going on now. Of course, the segfault mentioned at the beginning is fixed with this as well.
Diffstat (limited to 'video/out/vulkan/context_wayland.c')
-rw-r--r--video/out/vulkan/context_wayland.c57
1 files changed, 30 insertions, 27 deletions
diff --git a/video/out/vulkan/context_wayland.c b/video/out/vulkan/context_wayland.c
index fa5994d280..faac07cdcb 100644
--- a/video/out/vulkan/context_wayland.c
+++ b/video/out/vulkan/context_wayland.c
@@ -29,24 +29,6 @@ struct priv {
struct mpvk_ctx vk;
};
-static const struct wl_callback_listener frame_listener;
-
-static void frame_callback(void *data, struct wl_callback *callback, uint32_t time)
-{
- struct vo_wayland_state *wl = data;
-
- if (callback)
- wl_callback_destroy(callback);
-
- wl->frame_callback = wl_surface_frame(wl->surface);
- wl_callback_add_listener(wl->frame_callback, &frame_listener, wl);
- 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,
@@ -61,9 +43,11 @@ static void feedback_presented(void *data, struct wp_presentation_feedback *fbac
uint32_t flags)
{
struct vo_wayland_state *wl = data;
- wp_presentation_feedback_destroy(fback);
vo_wayland_sync_shift(wl);
+ if (fback)
+ wp_presentation_feedback_destroy(fback);
+
// 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.
@@ -83,11 +67,13 @@ static void feedback_presented(void *data, struct wp_presentation_feedback *fbac
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].filled = true;
+ wl->presentation_discarded = false;
}
static void feedback_discarded(void *data, struct wp_presentation_feedback *fback)
{
- wp_presentation_feedback_destroy(fback);
+ struct vo_wayland_state *wl = data;
+ wl->presentation_discarded = true;
}
static const struct wp_presentation_feedback_listener feedback_listener = {
@@ -96,24 +82,41 @@ static const struct wp_presentation_feedback_listener feedback_listener = {
feedback_discarded,
};
-static void wayland_vk_swap_buffers(struct ra_ctx *ctx)
+static const struct wl_callback_listener frame_listener;
+
+static void frame_callback(void *data, struct wl_callback *callback, uint32_t time)
{
- struct vo_wayland_state *wl = ctx->vo->wl;
+ struct vo_wayland_state *wl = data;
+
+ if (callback)
+ wl_callback_destroy(callback);
+
+ wl->frame_callback = wl_surface_frame(wl->surface);
+ wl_callback_add_listener(wl->frame_callback, &frame_listener, 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);
}
+ wl->frame_wait = false;
+}
+
+static const struct wl_callback_listener frame_listener = {
+ frame_callback,
+};
+
+static void wayland_vk_swap_buffers(struct ra_ctx *ctx)
+{
+ struct vo_wayland_state *wl = ctx->vo->wl;
+
if (!wl->opts->disable_vsync)
vo_wayland_wait_frame(wl);
- if (wl->presentation)
+ if (wl->presentation) {
+ wl->user_sbc += 1;
wayland_sync_swap(wl);
+ }
wl->frame_wait = true;
}