render: improve sixel rendering performance

Up until now, we’ve always re-rendered the entire image (the part of
it that is visible at least), *every* time we render a frame.

This is not really needed. In many cases, the cells covered by the
image hasn’t been touched.

Rewrite the sixel rendering code to only render the part of the sixel
image that covers dirty cells.

This is done on a per-row basis. I.e. Each *row* of the image that
covers at least one dirty cell is re-rendered. For this to work, we
now also dirty all cells covered by the image when we emit the image.

Finally, for this to work, the sixels need to be rendered *before* we
do the normal grid render pass (since that will clear all dirty bits).
This commit is contained in:
Daniel Eklöf 2020-11-13 16:54:40 +01:00
parent 08e4d2c238
commit 4b645376fd
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
2 changed files with 145 additions and 45 deletions

15
sixel.c
View file

@ -741,9 +741,20 @@ sixel_unhook(struct terminal *term)
image.width, image.height,
img_data, stride);
/* Allocate space *first*, then insert */
for (size_t i = 0; i < image.rows; i++)
/* Allocate space *first* (by emitting line-feeds), then insert */
for (size_t i = 0; i < image.rows; i++) {
struct row *row = term->grid->cur_row;
row->dirty = true;
/* Mark cells touched by the sixel as dirty */
for (int col = image.pos.col;
col < min(image.pos.col + image.cols, term->cols);
col++)
{
row->cells[col].attrs.clean = 0;
}
term_linefeed(term);
}
term_carriage_return(term);
_sixel_overwrite_by_rectangle(