vtgl

terminal emulator implemented in OpenGL
git clone anongit@rnpnr.xyz:vtgl.git
Log | Files | Refs | Feed | LICENSE

Commit: 965a04d8039e9152ed57c2f11f1881b570105b8e
Parent: 79037dd472b78007572b4f0a377dc7ae57d9d9d3
Author: Randy Palamar
Date:   Mon, 22 Jul 2024 07:36:05 -0600

only blit newly parsed lines

Blitting a whole screens worth is fine for normal programs but
some alt screen programs like vis do not send line breaking
characters and instead rely on terminal wrapping. This means that
only or two lines of input data are actually needed but the lines
are very long. Reblitting them everytime even though they are not
displayed is a complete waste of processor time and should not be
done.

Diffstat:
Mterminal.c | 17+++++++----------
Mtest.c | 12++++++------
Mutil.h | 4++--
Mvtgl.c | 4+---
4 files changed, 16 insertions(+), 21 deletions(-)

diff --git a/terminal.c b/terminal.c @@ -294,6 +294,8 @@ set_mode(Term *t, CSI *csi, b32 set) else t->gl.mode &= ~WIN_MODE_HIDECURSOR; break; case PRIV(1049): /* TODO: save cursor and switch to alt screen */ + if (set) t->mode |= TM_ALTSCREEN; + else t->mode &= ~TM_ALTSCREEN; break; default: fputs("set_mode: unhandled mode: ", stderr); @@ -641,9 +643,9 @@ static enum escape_moves_cursor_result check_if_escape_moves_cursor(Term *t, s8 *raw) { enum escape_moves_cursor_result result = EMC_NORMAL_RETURN; - u32 cp = get_ascii(raw); - if (raw->len == 0) + if (raw->len < 2) return EMC_NEEDS_MORE_BYTES; + u32 cp = get_ascii(raw); switch(cp) { case '[': result = check_if_csi_moves_cursor(t, raw); @@ -819,15 +821,10 @@ get_line_idx(LineBuf *lb, size off) } static void -blit_lines(Term *t, Arena a) +blit_lines(Term *t, Arena a, size line_count) { - size line_count = t->size.h; - if (line_count > t->log_lines.filled) - line_count = t->log_lines.filled; - - /* NOTE: for now we assume that we blit the whole screen everytime */ - /* TODO: Performance!!! */ - term_reset(t); + /* NOTE: assume altscreen programs are managing the cursor correctly on their own */ + t->cursor.col = t->mode & TM_ALTSCREEN ? t->cursor.col : 0; for (size i = 0; i <= line_count; i++) { size line_idx = get_line_idx(&t->log_lines, -line_count + i); diff --git a/test.c b/test.c @@ -70,12 +70,12 @@ static TEST_FN(cursor_movement) struct test_result result = {.info = __FUNCTION__}; s8 raw = launder_static_string(term, CSI(17;2H)); - split_raw_input_to_lines(term, raw); - blit_lines(term, arena); + size parsed_lines = split_raw_input_to_lines(term, raw); + blit_lines(term, arena, parsed_lines); raw = launder_static_string(term, CSI(7G)); - split_raw_input_to_lines(term, raw); - blit_lines(term, arena); + parsed_lines = split_raw_input_to_lines(term, raw); + blit_lines(term, arena, parsed_lines); result.status = term->cursor.row == 16 && term->cursor.col == 6; @@ -94,8 +94,8 @@ static TEST_FN(colour_setting) launder_static_string(term, CSI(48;2;75;63;42m)); s8 raw = launder_static_string(term, s8("A")); - split_raw_input_to_lines(term, raw); - blit_lines(term, arena); + size parsed_lines = split_raw_input_to_lines(term, raw); + blit_lines(term, arena, parsed_lines); Cell c = { .cp = 'A', .style = { .bg = (Colour){.r = 75, .g = 63, .b = 42, .a = 0xFF}, diff --git a/util.h b/util.h @@ -246,8 +246,8 @@ typedef struct { } FontAtlas; enum terminal_mode { - TM_ALTSCEEN = 1 << 0, - TM_REPLACE = 1 << 1, + TM_ALTSCREEN = 1 << 0, + TM_REPLACE = 1 << 1, }; typedef struct { diff --git a/vtgl.c b/vtgl.c @@ -400,10 +400,8 @@ do_terminal(Term *t, Arena a) .data = t->log.buf + (t->log.widx - t->unprocessed_bytes) }; size parsed_lines = split_raw_input_to_lines(t, raw); - /* TODO: think about only blitting update lines? */ - (void)parsed_lines; + blit_lines(t, a, parsed_lines); } - blit_lines(t, a); /* NOTE: reset the camera/viewport */ glUseProgram(t->gl.programs[SHADER_RENDER]);