diff options
author | Simon Ser <contact@emersion.fr> | 2021-09-07 10:45:05 +0200 |
---|---|---|
committer | Kenny Levinsen <kl@kl.wtf> | 2021-09-07 22:27:31 +0200 |
commit | 04304c322e6d6e7b2c020b1e1bada3a84f5c06c6 (patch) | |
tree | 47f25d5572057d87984f1e9a27be71f62f33974e | |
parent | 35f0a0d5700fba0626137fbcf5f3b04f03a831ec (diff) |
output-damage: fix damage on modeset
On modeset wlr_output will internally allocate a buffer. The
backend will emit a "mode" output event, then wlr_output will
emit a "commit" event.
wlr_output_damage handles the "mode" event by damaging the whole
output, and then handles the "commit" event. However the commit
event has a buffer, so wlr_output_damage rotates the damage in its
ring buffer, thinking the compositor has rendered a frame. The
compositor hasn't rendered a frame, what wlr_output_damage sees is
the internal wlr_output black buffer used for the modeset.
Let's fix this by damaging the whole output in the "commit" event
handler if the mode has changed. Additionally, damage the whole
output after rotating the damage ring buffer.
-rw-r--r-- | types/wlr_output_damage.c | 41 |
1 files changed, 20 insertions, 21 deletions
diff --git a/types/wlr_output_damage.c b/types/wlr_output_damage.c index 08a2baaa..6d24a4bf 100644 --- a/types/wlr_output_damage.c +++ b/types/wlr_output_damage.c @@ -61,31 +61,30 @@ static void output_handle_commit(struct wl_listener *listener, void *data) { wl_container_of(listener, output_damage, output_commit); struct wlr_output_event_commit *event = data; - if (event->committed & (WLR_OUTPUT_STATE_SCALE | WLR_OUTPUT_STATE_TRANSFORM)) { - wlr_output_damage_add_whole(output_damage); - } + if (event->committed & WLR_OUTPUT_STATE_BUFFER) { + pixman_region32_t *prev; + if (output_damage->pending_attach_render) { + // render-buffers have been swapped, rotate the damage + + // same as decrementing, but works on unsigned integers + output_damage->previous_idx += WLR_OUTPUT_DAMAGE_PREVIOUS_LEN - 1; + output_damage->previous_idx %= WLR_OUTPUT_DAMAGE_PREVIOUS_LEN; + + prev = &output_damage->previous[output_damage->previous_idx]; + pixman_region32_copy(prev, &output_damage->current); + } else { + // accumulate render-buffer damage + prev = &output_damage->previous[output_damage->previous_idx]; + pixman_region32_union(prev, prev, &output_damage->current); + } - if (!(event->committed & WLR_OUTPUT_STATE_BUFFER)) { - return; + pixman_region32_clear(&output_damage->current); } - pixman_region32_t *prev; - if (output_damage->pending_attach_render) { - // render-buffers have been swapped, rotate the damage - - // same as decrementing, but works on unsigned integers - output_damage->previous_idx += WLR_OUTPUT_DAMAGE_PREVIOUS_LEN - 1; - output_damage->previous_idx %= WLR_OUTPUT_DAMAGE_PREVIOUS_LEN; - - prev = &output_damage->previous[output_damage->previous_idx]; - pixman_region32_copy(prev, &output_damage->current); - } else { - // accumulate render-buffer damage - prev = &output_damage->previous[output_damage->previous_idx]; - pixman_region32_union(prev, prev, &output_damage->current); + if (event->committed & (WLR_OUTPUT_STATE_MODE | WLR_OUTPUT_STATE_SCALE | + WLR_OUTPUT_STATE_TRANSFORM)) { + wlr_output_damage_add_whole(output_damage); } - - pixman_region32_clear(&output_damage->current); } struct wlr_output_damage *wlr_output_damage_create(struct wlr_output *output) { |