wayland: be less strict about when to render

efb0c5c changed the rendering logic of mpv on wayland and made it skip
rendering when it did not receive frame callback in time. The idea was
to skip rendering when the surface was hidden and be less wasteful. This
unfortunately had issues in certain instances where a frame callback
could be missed (but the window was still in view) due to imprecise
rendering (like the default audio video-sync mode). This would lead to
the video appearing to stutter since mpv would skip rendering in those
cases.

To account for this case, simply re-add an old heuristic for detecting
if a window is hidden or not since the goal is to simply not render when
a window is hidden. If the wait on the frame callback times out enough
times in a row, then we consider the window hidden and thus begin to
skip rendering then. The actual threshold to consider a surface as
hidden is completely arbitrary (greater than your monitor's refresh
rate), but it's safe enough since realistically you're not going to miss
60+ frame callbacks in a row unless the surface actually is hidden.
Fixes #8169.
This commit is contained in:
Dudemanguy 2020-10-13 10:36:08 -05:00
parent cfead22b80
commit deaea70630
5 changed files with 16 additions and 3 deletions

View File

@ -145,7 +145,7 @@ static bool wayland_egl_start_frame(struct ra_swapchain *sw, struct ra_fbo *out_
struct ra_ctx *ctx = sw->ctx;
struct vo_wayland_state *wl = ctx->vo->wl;
bool render = !wl->frame_wait || wl->opts->disable_vsync;
bool render = !wl->hidden || wl->opts->disable_vsync;
if (wl->frame_wait && wl->presentation)
vo_wayland_sync_clear(wl);

View File

@ -248,7 +248,7 @@ static void draw_image(struct vo *vo, struct mp_image *src)
struct vo_wayland_state *wl = vo->wl;
struct buffer *buf;
if (wl->frame_wait)
if (wl->hidden)
return;
wl->frame_wait = true;

View File

@ -106,7 +106,7 @@ static bool wayland_vk_start_frame(struct ra_ctx *ctx)
{
struct vo_wayland_state *wl = ctx->vo->wl;
bool render = !wl->frame_wait || wl->opts->disable_vsync;
bool render = !wl->hidden || wl->opts->disable_vsync;
if (wl->frame_wait && wl->presentation)
vo_wayland_sync_clear(wl);

View File

@ -1717,6 +1717,17 @@ void vo_wayland_wait_frame(struct vo_wayland_state *wl)
wl_display_dispatch_pending(wl->display);
}
if (!wl->hidden && wl->frame_wait) {
wl->timeout_count += 1;
if (wl->timeout_count > wl->current_output->refresh_rate)
wl->hidden = true;
}
if (!wl->frame_wait) {
wl->timeout_count = 0;
wl->hidden = false;
}
if (wl_display_get_error(wl->display) == 0)
wl_display_roundtrip(wl->display);
}

View File

@ -79,6 +79,8 @@ struct vo_wayland_state {
bool activated;
bool has_keyboard_input;
bool focused;
bool hidden;
int timeout_count;
int wakeup_pipe[2];
int pending_vo_events;
int mouse_x;