Skip to content

Commit

Permalink
Fix terminal redraw slowdown in presence of true colour.
Browse files Browse the repository at this point in the history
When do_paint breaks up a line of terminal text into contiguous runs
of characters to treat the same, one of the criteria it uses is, 'Does
this character even need redrawing? (or is it already displayed
correctly from the previous redraw?)' When we encounter a character
that matches its previous value, we end the previous run of
characters, so that we can skip the one we've just encountered.

That check was not taking account of the 'truecolour' field of the
termchar it was checking. So it would sometimes falsely believe the
character to be equivalent to its previously drawn value, even when in
fact it was not, and hence insert a run break, anticipating that the
previous character needed drawing and the current one did not.

This didn't cause a _wrong_ redraw, because there's a separate loop
further on which re-checks whether to actually draw things, which
didn't make the same error. So the character that loop github#1 thought
didn't need a redraw, loop github#2 knew _did_ need a redraw, and hence,
everything did get redrawn.

But by the time loop github#2 is running, it's too late to change the run
boundaries. So everything does get redrawn, but in much smaller chunks
than it could have been. The net effect was that if the screen was
filled with text displayed in true colour, and you changed it to the
_same_ text in a different colour, then the whole terminal would be
redrawn in one-character increments instead of the usual behaviour of
folding together runs that can be drawn in one go.

Thanks to Bradley Smith for debugging this very confusing issue!
  • Loading branch information
sgtatham committed Jul 15, 2021
1 parent 640e46a commit 7a25599
Showing 1 changed file with 3 additions and 1 deletion.
4 changes: 3 additions & 1 deletion terminal.c
Original file line number Diff line number Diff line change
Expand Up @@ -6043,7 +6043,9 @@ static void do_paint(Terminal *term)

if (!term->ucsdata->dbcs_screenfont && !dirty_line) {
if (term->disptext[i]->chars[j].chr == tchar &&
(term->disptext[i]->chars[j].attr &~ DATTR_MASK) == tattr)
(term->disptext[i]->chars[j].attr &~ DATTR_MASK)==tattr &&
truecolour_equal(
term->disptext[i]->chars[j].truecolour, tc))
break_run = true;
else if (!dirty_run && ccount == 1)
break_run = true;
Expand Down

0 comments on commit 7a25599

Please sign in to comment.