From af021a289169ae215ab8443634ff26fd1c79ad36 Mon Sep 17 00:00:00 2001 From: Dudemanguy Date: Thu, 6 Feb 2020 23:54:57 -0600 Subject: [PATCH] wayland: adjust vo_wayland_wait_frame logic Wayland uses vo_wayland_wait_frame plus some polling with a timeout for blocking on vsync. Here are a couple of changes that seem to be improvements. First, the poll time is always rounded up instead of truncated. When rendering frames longer than the standard 16.666 ms timeout, it seems that truncating the poll time slightly early may cause some vsync jitter spikes. Waiting longer, even if it's too long, appears to behave better. The second change is to use wl_display_roundtrip instead of wl_display_dispatch_pending. wl_display_dispatch_pending dispatches all events immediately. This is good to avoid blocking, but it's not guaranteed to wait long enough for all events to be processed on the display fd. The preceding wl_display_read_events routine ensures that all events on the display fd are queued. We just need a semi-blocking routine to dispatch them for the most reliable vsync. wl_display_roundtrip will dispatch any events for us, but also wait for a reply from the display server. This makes it ideal for this role. If the compositor doesn't reply to the client something else is probably horribly broken and wrong anyway. It's also not a permanently blocking call like wl_display_dispatch. If there's no frame callback (i.e. the window is hidden), then it does not dispatch any events and returns immediately. --- video/out/wayland_common.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c index 73949f4555..d42758a7bc 100644 --- a/video/out/wayland_common.c +++ b/video/out/wayland_common.c @@ -1609,19 +1609,19 @@ void vo_wayland_wait_frame(struct vo_wayland_state *wl) while (wl->frame_wait && finish_time > mp_time_us()) { - while (wl_display_prepare_read(wl->display) != 0) - wl_display_dispatch_pending(wl->display); - wl_display_flush(wl->display); - - int poll_time = (finish_time - mp_time_us()) / 1000; + int poll_time = ceil((double)(finish_time - mp_time_us()) / 1000); if (poll_time < 0) { poll_time = 0; } + while (wl_display_prepare_read(wl->display) != 0) + wl_display_dispatch_pending(wl->display); + wl_display_flush(wl->display); + poll(fds, 1, poll_time); wl_display_read_events(wl->display); - wl_display_dispatch_pending(wl->display); + wl_display_roundtrip(wl->display); } if (wl->frame_wait) {