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.
This commit is contained in:
Dudemanguy 2020-02-06 23:54:57 -06:00
parent c4570be3b8
commit af021a2891
1 changed files with 6 additions and 6 deletions

View File

@ -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->frame_wait && finish_time > mp_time_us()) {
while (wl_display_prepare_read(wl->display) != 0) int poll_time = ceil((double)(finish_time - mp_time_us()) / 1000);
wl_display_dispatch_pending(wl->display);
wl_display_flush(wl->display);
int poll_time = (finish_time - mp_time_us()) / 1000;
if (poll_time < 0) { if (poll_time < 0) {
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); poll(fds, 1, poll_time);
wl_display_read_events(wl->display); wl_display_read_events(wl->display);
wl_display_dispatch_pending(wl->display); wl_display_roundtrip(wl->display);
} }
if (wl->frame_wait) { if (wl->frame_wait) {