From 85ef9df586dfca22d16d04c9777dc38ff896223a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 30 Jul 2019 18:03:03 +0200 Subject: [PATCH] render: add a 'clean' bit to each cell; only render cells that aren't clean This patch takes a bit from the foreground color value in a cell (todo: split up foreground/background into bitfields with a separate field for 'foreground/background' has been set), and only re-renders cells that aren't marked as clean. Note: we use a 'clean' bit rather than a 'dirty' bit to make it easy to erase cells - we can (keep doing) do that by simply memsetting a cell range to 0. --- csi.c | 25 +++++++++++++++---------- grid.c | 2 ++ main.c | 6 ++++-- render.c | 11 ++++++++--- terminal.c | 24 ++++++++++++++++-------- terminal.h | 7 +++++-- vt.c | 10 ++-------- 7 files changed, 52 insertions(+), 33 deletions(-) diff --git a/csi.c b/csi.c index 5f37663c..a82f03f3 100644 --- a/csi.c +++ b/csi.c @@ -126,7 +126,7 @@ csi_sgr(struct terminal *term) case 35: case 36: case 37: - term->vt.attrs.foreground = 1 << 31 | term->colors.regular[param - 30]; + term->vt.attrs.foreground = 1 << 30 | term->colors.regular[param - 30]; break; case 38: { @@ -141,7 +141,7 @@ csi_sgr(struct terminal *term) color = term->colors.bright[idx - 8]; else color = colors256[idx]; - term->vt.attrs.foreground = 1 << 31 | color; + term->vt.attrs.foreground = 1 << 30 | color; i += 2; } @@ -152,7 +152,7 @@ csi_sgr(struct terminal *term) uint8_t r = term->vt.params.v[i + 2].value; uint8_t g = term->vt.params.v[i + 3].value; uint8_t b = term->vt.params.v[i + 4].value; - term->vt.attrs.foreground = 1 << 31 | r << 16 | g << 8 | b; + term->vt.attrs.foreground = 1 << 30 | r << 16 | g << 8 | b; i += 4; } @@ -168,7 +168,7 @@ csi_sgr(struct terminal *term) /* 6 - CS tolerance */ /* 7 - color space associated with tolerance */ - term->vt.attrs.foreground = 1 << 31 | r << 16 | g << 8 | b; + term->vt.attrs.foreground = 1 << 30 | r << 16 | g << 8 | b; } else { LOG_ERR("invalid CSI SGR sequence"); abort(); @@ -195,7 +195,7 @@ csi_sgr(struct terminal *term) case 45: case 46: case 47: - term->vt.attrs.background = 1 << 31 | term->colors.regular[param - 40]; + term->vt.attrs.background = 1 << 30 | term->colors.regular[param - 40]; break; case 48: { @@ -211,7 +211,7 @@ csi_sgr(struct terminal *term) color = term->colors.bright[idx - 8]; else color = colors256[idx]; - term->vt.attrs.background = 1 << 31 | color; + term->vt.attrs.background = 1 << 30 | color; i += 2; } @@ -221,7 +221,7 @@ csi_sgr(struct terminal *term) uint8_t r = term->vt.params.v[i + 2].value; uint8_t g = term->vt.params.v[i + 3].value; uint8_t b = term->vt.params.v[i + 4].value; - term->vt.attrs.background = 1 << 31 | r << 16 | g << 8 | b; + term->vt.attrs.background = 1 << 30 | r << 16 | g << 8 | b; i += 4; } @@ -238,7 +238,7 @@ csi_sgr(struct terminal *term) /* 6 - CS tolerance */ /* 7 - color space associated with tolerance */ - term->vt.attrs.background = 1 << 31 | r << 16 | g << 8 | b; + term->vt.attrs.background = 1 << 30 | r << 16 | g << 8 | b; } else { LOG_ERR("invalid CSI SGR sequence"); abort(); @@ -265,7 +265,7 @@ csi_sgr(struct terminal *term) case 95: case 96: case 97: - term->vt.attrs.foreground = 1 << 31 | term->colors.bright[param - 90]; + term->vt.attrs.foreground = 1 << 30 | term->colors.bright[param - 90]; break; /* Regular background colors */ @@ -277,7 +277,7 @@ csi_sgr(struct terminal *term) case 105: case 106: case 107: - term->vt.attrs.background = 1 << 31 | term->colors.bright[param - 100]; + term->vt.attrs.background = 1 << 30 | term->colors.bright[param - 100]; break; default: @@ -487,6 +487,9 @@ csi_dispatch(struct terminal *term, uint8_t final) memmove(&term->grid->cur_row->cells[term->cursor.col], &term->grid->cur_row->cells[term->cursor.col + count], remaining * sizeof(term->grid->cur_row->cells[0])); + + for (size_t c = 0; c < remaining; c++) + term->grid->cur_row->cells[term->cursor.col + c].attrs.clean = 0; term->grid->cur_row->dirty = true; /* Erase the remainder of the line */ @@ -511,6 +514,8 @@ csi_dispatch(struct terminal *term, uint8_t final) memmove(&term->grid->cur_row->cells[term->cursor.col + count], &term->grid->cur_row->cells[term->cursor.col], remaining * sizeof(term->grid->cur_row->cells[0])); + for (size_t c = 0; c < remaining; c++) + term->grid->cur_row->cells[term->cursor.col + count + c].attrs.clean = 0; term->grid->cur_row->dirty = true; /* Erase (insert space characters) */ diff --git a/grid.c b/grid.c index 47e09065..2ff82bd7 100644 --- a/grid.c +++ b/grid.c @@ -29,6 +29,8 @@ grid_row_alloc(int cols) { struct row *row = malloc(sizeof(*row)); row->cells = calloc(cols, sizeof(row->cells[0])); + for (size_t c = 0; c < cols; c++) + row->cells[c].attrs.clean = 1; row->dirty = false; /* TODO: parameter? */ return row; } diff --git a/main.c b/main.c index 0368c687..bdb1de3e 100644 --- a/main.c +++ b/main.c @@ -831,9 +831,11 @@ main(int argc, char *const *argv) for (int r = 0; r < term.rows; r++) { struct row *row = grid_row_in_view(term.grid, r); for (int col = 0; col < term.cols; col++) { - if (row->cells[col].attrs.blink) { + struct cell *cell = &row->cells[col]; + + if (cell->attrs.blink) { + cell->attrs.clean = 0; row->dirty = true; - break; } } } diff --git a/render.c b/render.c index 123e5593..60aa43b4 100644 --- a/render.c +++ b/render.c @@ -174,8 +174,13 @@ arm_blink_timer(struct terminal *term) static void render_cell(struct terminal *term, struct buffer *buf, size_t buf_idx, - const struct cell *cell, int col, int row, bool has_cursor) + struct cell *cell, int col, int row, bool has_cursor) { + if (cell->attrs.clean) + return; + + cell->attrs.clean = 1; + cairo_t *cr = buf->cairo[buf_idx]; double width = term->cell_width; double height = term->cell_height; @@ -185,10 +190,10 @@ render_cell(struct terminal *term, struct buffer *buf, size_t buf_idx, bool block_cursor = has_cursor && term->cursor_style == CURSOR_BLOCK; bool is_selected = coord_is_selected(term, col, row); - uint32_t _fg = cell->attrs.foreground >> 31 + uint32_t _fg = cell->attrs.foreground >> 30 ? cell->attrs.foreground : !term->reverse ? term->colors.fg : term->colors.bg; - uint32_t _bg = cell->attrs.background >> 31 + uint32_t _bg = cell->attrs.background >> 30 ? cell->attrs.background : !term->reverse ? term->colors.bg : term->colors.fg; diff --git a/terminal.c b/terminal.c index 871e6dcb..d6742259 100644 --- a/terminal.c +++ b/terminal.c @@ -20,29 +20,36 @@ void term_damage_rows(struct terminal *term, int start, int end) { assert(start <= end); - for (int r = start; r <= end; r++) - grid_row(term->grid, r)->dirty = true; + for (int r = start; r <= end; r++) { + struct row *row = grid_row(term->grid, r); + row->dirty = true; + for (int c = 0; c < term->grid->num_cols; c++) + row->cells[c].attrs.clean = 0; + } } void term_damage_rows_in_view(struct terminal *term, int start, int end) { assert(start <= end); - for (int r = start; r <= end; r++) - grid_row_in_view(term->grid, r)->dirty = true; + for (int r = start; r <= end; r++) { + struct row *row = grid_row_in_view(term->grid, r); + row->dirty = true; + for (int c = 0; c < term->grid->num_cols; c++) + row->cells[c].attrs.clean = 0; + } } void term_damage_all(struct terminal *term) { - term_damage_rows(term, 0, term->rows); + term_damage_rows(term, 0, term->rows - 1); } void term_damage_view(struct terminal *term) { - for (int i = 0; i < term->rows; i++) - grid_row_in_view(term->grid, i)->dirty = true; + term_damage_rows_in_view(term, 0, term->rows - 1); } void @@ -73,9 +80,10 @@ erase_cell_range(struct terminal *term, struct row *row, int start, int end) assert(start < term->cols); assert(end < term->cols); - if (unlikely(term->vt.attrs.background >> 31)) { + if (unlikely(term->vt.attrs.background >> 30)) { for (int col = start; col <= end; col++) { row->cells[col].c[0] = '\0'; + row->cells[col].attrs.clean = 0; row->cells[col].attrs.background = term->vt.attrs.background; } } else { diff --git a/terminal.h b/terminal.h index de359576..3d2bbf72 100644 --- a/terminal.h +++ b/terminal.h @@ -65,8 +65,11 @@ struct attributes { uint8_t conceal:1; uint8_t reverse:1; - uint32_t foreground; - uint32_t background; + uint32_t clean:1; + uint32_t foreground:31; + + uint32_t reserved:1; + uint32_t background:31; } __attribute__((packed)); struct cell { diff --git a/vt.c b/vt.c index 7ee59acb..399583ea 100644 --- a/vt.c +++ b/vt.c @@ -698,7 +698,6 @@ pre_print(struct terminal *term) static inline void post_print(struct terminal *term) { - term->grid->cur_row->dirty = true; if (term->cursor.col < term->cols - 1) term_cursor_right(term, 1); else @@ -716,13 +715,6 @@ print_insert(struct terminal *term) &row[term->cursor.col + 1], &row[term->cursor.col], term->cols - term->cursor.col - 1); - -#if 0 - term_damage_update( - term, term->cursor.linear + 1, term->cols - term->cursor.col - 1); -#else - row->dirty = true; -#endif } } @@ -737,6 +729,7 @@ action_print_utf8(struct terminal *term) term_damage_update(term, term->cursor.linear, 1); #else row->dirty = true; + cell->attrs.clean = 0; #endif print_insert(term); @@ -761,6 +754,7 @@ action_print(struct terminal *term, uint8_t c) term_damage_update(term, term->cursor.linear, 1); #else row->dirty = true; + cell->attrs.clean = 0; #endif print_insert(term);