From 3be44fb316b166c0b5d5536fdb5bb6c7abdd3a90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 22 Sep 2022 18:39:00 +0200 Subject: [PATCH] render: overlay: fix visual glitches when double buffering MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When rendering the overlay for scrollback search, the logic assumed buffer re-use. On some compositors this isn’t happening (on e.g. KDE/plasma we’re forced to double buffer). This resulted in matches not being highlighted correctly. The problem is in how we calculated the region for which areas to clear ("un-dim"). It uses the "previous frame’s see-through area" minus the current frame’s see-through area. However, when we’ve detected that the current buffer isn’t the same as the last one, we set the last frame’s see-through region to "the entire buffer". Thus, when calculating the diff, we end up with an empty region, and nothing is highlighted. Fix by simply using the current frame’s see-through region as-is when we’ve detected we’re not re-using the last frame’s buffer. --- CHANGELOG.md | 3 +++ render.c | 29 +++++++++++++++++++---------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 17430354..dd0ac80b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -74,6 +74,9 @@ * Glitchy rendering when scrolling in the scrollback, on compositors that does not allow Wayland buffer re-use (e.g. KDE/plasma) ([#1173][1173]) +* Scrollback search matches not being highlighted correctly, on + compositors that does now allow Wayland buffer re-use + (e.g. KDE/plasma). [1173]: https://codeberg.org/dnkl/foot/issues/1173 diff --git a/render.c b/render.c index 7f883220..b285b120 100644 --- a/render.c +++ b/render.c @@ -1563,11 +1563,12 @@ render_overlay(struct terminal *term) */ pixman_region32_t *see_through = &term->render.last_overlay_clip; pixman_region32_t old_see_through; + const bool buffer_reuse = + buf == term->render.last_overlay_buf && + style == term->render.last_overlay_style && + buf->age == 0; - if (!(buf == term->render.last_overlay_buf && - style == term->render.last_overlay_style && - buf->age == 0)) - { + if (!buffer_reuse) { /* Can’t re-use last frame’s damage - set to full window, * to ensure *everything* is updated */ pixman_region32_init_rect( @@ -1580,8 +1581,8 @@ render_overlay(struct terminal *term) pixman_region32_clear(see_through); + /* Build region consisting of all current search matches */ struct search_match_iterator iter = search_matches_new_iter(term); - for (struct range match = search_matches_next(&iter); match.start.row >= 0; match = search_matches_next(&iter)) @@ -1609,20 +1610,28 @@ render_overlay(struct terminal *term) } } - /* Current see-through, minus old see-through - aka cells that - * need to be cleared */ + /* Areas that need to be cleared: cells that were dimmed in + * the last frame but is now see-through */ pixman_region32_t new_see_through; pixman_region32_init(&new_see_through); - pixman_region32_subtract(&new_see_through, see_through, &old_see_through); + + if (buffer_reuse) + pixman_region32_subtract(&new_see_through, see_through, &old_see_through); + else { + /* Buffer content is unknown - explicitly clear *all* + * current see-through areas */ + pixman_region32_copy(&new_see_through, see_through); + } pixman_image_set_clip_region32(buf->pix[0], &new_see_through); - /* Old see-through, minus new see-through - aka cells that - * needs to be dimmed */ + /* Areas that need to be dimmed: cells that were cleared in + * the last frame but is not anymore */ pixman_region32_t new_dimmed; pixman_region32_init(&new_dimmed); pixman_region32_subtract(&new_dimmed, &old_see_through, see_through); pixman_region32_fini(&old_see_through); + /* Total affected area */ pixman_region32_t damage; pixman_region32_init(&damage); pixman_region32_union(&damage, &new_see_through, &new_dimmed);