aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Kenny Levinsen <kl@kl.wtf>2019-11-30 16:29:39 +0100
committerLibravatar Simon Ser <contact@emersion.fr>2019-12-01 12:44:07 +0100
commitd1eab10266eabbcb33eeb9178491234d059dbe99 (patch)
tree4a39fd7618a54e012688a9ab33d6e961b47333d2
parentoutput: Replace block_idle_frame with frame_pending (diff)
downloadsway-d1eab10266eabbcb33eeb9178491234d059dbe99.tar.gz
sway-d1eab10266eabbcb33eeb9178491234d059dbe99.tar.zst
sway-d1eab10266eabbcb33eeb9178491234d059dbe99.zip
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
-rw-r--r--include/sway/output.h1
-rw-r--r--sway/desktop/output.c6
2 files changed, 7 insertions, 0 deletions
diff --git a/include/sway/output.h b/include/sway/output.h
index bc03f4c5..b1c74258 100644
--- a/include/sway/output.h
+++ b/include/sway/output.h
@@ -57,6 +57,7 @@ struct sway_output {
57 uint32_t refresh_nsec; 57 uint32_t refresh_nsec;
58 int max_render_time; // In milliseconds 58 int max_render_time; // In milliseconds
59 struct wl_event_source *repaint_timer; 59 struct wl_event_source *repaint_timer;
60 bool surface_needs_frame;
60}; 61};
61 62
62struct sway_output *output_create(struct wlr_output *wlr_output); 63struct sway_output *output_create(struct wlr_output *wlr_output);
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index 6c78e08d..97ea2e7c 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -515,6 +515,9 @@ int output_repaint_timer_handler(void *data) {
515 515
516 output->wlr_output->frame_pending = false; 516 output->wlr_output->frame_pending = false;
517 517
518 bool surface_needs_frame = output->surface_needs_frame;
519 output->surface_needs_frame = false;
520
518 struct sway_workspace *workspace = output->current.active_workspace; 521 struct sway_workspace *workspace = output->current.active_workspace;
519 if (workspace == NULL) { 522 if (workspace == NULL) {
520 return 0; 523 return 0;
@@ -557,6 +560,8 @@ int output_repaint_timer_handler(void *data) {
557 clock_gettime(CLOCK_MONOTONIC, &now); 560 clock_gettime(CLOCK_MONOTONIC, &now);
558 561
559 output_render(output, &now, &damage); 562 output_render(output, &now, &damage);
563 } else if (surface_needs_frame) {
564 wlr_output_schedule_frame(output->wlr_output);
560 } 565 }
561 566
562 pixman_region32_fini(&damage); 567 pixman_region32_fini(&damage);
@@ -672,6 +677,7 @@ static void damage_surface_iterator(struct sway_output *output, struct sway_view
672 wlr_output_damage_add_box(output->damage, &box); 677 wlr_output_damage_add_box(output->damage, &box);
673 } 678 }
674 679
680 output->surface_needs_frame = true;
675 wlr_output_schedule_frame(output->wlr_output); 681 wlr_output_schedule_frame(output->wlr_output);
676} 682}
677 683