commit d1eab10266eabbcb33eeb9178491234d059dbe99
parent 57f615e122fc0c4d4d5665f7e26c276be6b3ee00
Author: Kenny Levinsen <kl@kl.wtf>
Date: Sat, 30 Nov 2019 16:29:39 +0100
output: Schedule idle frames if we do not render
Repaint scheduling delays output render and frame done events from
output frame events, and block idle frame events from being scheduled in
between output frame done and output render in this period of time.
If a surface is committed after its frame done event, but before output
render, idle frame requests will be blocked, and the surface relies on
the upcoming render to schedule a frame.
If when the repaint timer expires, output render is deemed unnecessary,
no frame will be scheduled. This can lead to surfaces never having their
frame callbacks fire.
To fix this, we store that a surface has requested a frame in
surface_needs_frame. When the repaint expires, if no render is deemed
necessary, we check this flag and schedule an idle frame.
Fixes #4768
Diffstat:
2 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/include/sway/output.h b/include/sway/output.h
@@ -57,6 +57,7 @@ struct sway_output {
uint32_t refresh_nsec;
int max_render_time; // In milliseconds
struct wl_event_source *repaint_timer;
+ bool surface_needs_frame;
};
struct sway_output *output_create(struct wlr_output *wlr_output);
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
@@ -515,6 +515,9 @@ int output_repaint_timer_handler(void *data) {
output->wlr_output->frame_pending = false;
+ bool surface_needs_frame = output->surface_needs_frame;
+ output->surface_needs_frame = false;
+
struct sway_workspace *workspace = output->current.active_workspace;
if (workspace == NULL) {
return 0;
@@ -557,6 +560,8 @@ int output_repaint_timer_handler(void *data) {
clock_gettime(CLOCK_MONOTONIC, &now);
output_render(output, &now, &damage);
+ } else if (surface_needs_frame) {
+ wlr_output_schedule_frame(output->wlr_output);
}
pixman_region32_fini(&damage);
@@ -672,6 +677,7 @@ static void damage_surface_iterator(struct sway_output *output, struct sway_view
wlr_output_damage_add_box(output->damage, &box);
}
+ output->surface_needs_frame = true;
wlr_output_schedule_frame(output->wlr_output);
}