vtgl

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

Commit: e080b99dc9c1f0f62c13f1ff6aa7fe41e471860f
Parent: e1a7bae479960e5c64543c691955941fb1e05c6d
Author: Randy Palamar
Date:   Mon, 26 Aug 2024 21:09:39 -0600

avoid redrawing the whole framebuffer if it hasn't updated

This is a first pass at reducing CPU usage. We still the render
texture on each frame which allows post processing to take effect.
Since this is a simple fullscreen textured quad it requires
minimal processing power.

Diffstat:
Mterminal.c | 7++++---
Mutil.c | 7+++++++
Mutil.h | 4+++-
Mvtgl.c | 98+++++++++++++++++++++++++++++++++++++++++--------------------------------------
4 files changed, 65 insertions(+), 51 deletions(-)

diff --git a/terminal.c b/terminal.c @@ -235,7 +235,7 @@ swap_screen(Term *t) { t->mode ^= TM_ALTSCREEN; t->view_idx = !!(t->mode & TM_ALTSCREEN); - t->gl.flags |= NEEDS_FULL_BLIT; + t->gl.flags |= NEEDS_FULL_REFILL; } static void @@ -1140,7 +1140,7 @@ blit_lines(Term *t, Arena a, size line_count) { TermView *tv = t->views + t->view_idx; - if (t->gl.flags & NEEDS_FULL_BLIT) { + if (t->gl.flags & NEEDS_FULL_REFILL) { term_reset(t); line_count = t->size.h - 1; } @@ -1156,5 +1156,6 @@ blit_lines(Term *t, Arena a, size line_count) push_line(t, tv->lines.buf + line_idx, a); } - t->gl.flags &= ~(NEEDS_FULL_BLIT|NEEDS_BLIT); + t->gl.flags &= ~(NEEDS_FULL_REFILL|NEEDS_REFILL); + t->gl.flags |= NEEDS_BLIT; } diff --git a/util.c b/util.c @@ -11,6 +11,13 @@ equal_iv2(iv2 a, iv2 b) } static b32 +equal_uv2(uv2 a, uv2 b) +{ + b32 result = a.x == b.x && a.y == b.y; + return result; +} + +static b32 is_valid_range(Range r) { b32 result = !equal_iv2(r.end, INVALID_RANGE_END); diff --git a/util.h b/util.h @@ -195,7 +195,9 @@ typedef struct { enum gl_flags { NEEDS_RESIZE = 1 << 0, NEEDS_BLIT = 1 << 1, - NEEDS_FULL_BLIT = 1 << 2, + NEEDS_REFILL = 1 << 2, + NEEDS_FULL_REFILL = 1 << 3, + UPDATE_RENDER_UNIFORMS = 1 << 29, UPDATE_POST_UNIFORMS = 1 << 30, }; diff --git a/vtgl.c b/vtgl.c @@ -104,16 +104,19 @@ resize(Term *t) ws.w -= 2 * g_term_pad.w; ws.h -= 2 * g_term_pad.h; - v2 cs = get_cell_size(t); - t->size.w = (u32)(ws.w / cs.w); - t->size.h = (u32)(ws.h / cs.h); + uv2 old_size = t->size; + v2 cs = get_cell_size(t); + t->size.w = (u32)(ws.w / cs.w); + t->size.h = (u32)(ws.h / cs.h); + + if (!equal_uv2(old_size, t->size)) { + os_alloc_framebuffer(&t->views[0].fb, t->size.h, t->size.w); + os_alloc_framebuffer(&t->views[1].fb, t->size.h, t->size.w); + t->gl.flags |= NEEDS_FULL_REFILL; + } - os_alloc_framebuffer(&t->views[0].fb, t->size.h, t->size.w); - os_alloc_framebuffer(&t->views[1].fb, t->size.h, t->size.w); os_set_term_size(t->child, t->size.h, t->size.w, ws.w, ws.h); t->gl.flags &= ~NEEDS_RESIZE; - /* TODO: check if we actually changed size */ - t->gl.flags |= NEEDS_FULL_BLIT; } static void @@ -450,7 +453,8 @@ update_selection(Term *t) } } } - sel->range = normalize_range(sel->range); + sel->range = normalize_range(sel->range); + t->gl.flags |= NEEDS_BLIT; } KEYBIND_FN(copy) @@ -535,7 +539,7 @@ KEYBIND_FN(scroll) t->scroll_offset += a.i; CLAMP(t->scroll_offset, 0, tv->lines.filled - (t->size.h - 1)); - t->gl.flags |= NEEDS_FULL_BLIT; + t->gl.flags |= NEEDS_FULL_REFILL; return 1; } @@ -708,7 +712,7 @@ char_callback(GLFWwindow *win, u32 codepoint) Term *t = glfwGetWindowUserPointer(win); if (t->scroll_offset) { t->scroll_offset = 0; - t->gl.flags |= NEEDS_FULL_BLIT; + t->gl.flags |= NEEDS_FULL_REFILL; } os_child_put_char(t->child, codepoint); } @@ -791,58 +795,58 @@ do_terminal(Term *t) .data = rb->buf + (rb->widx - t->unprocessed_bytes) }; parsed_lines = split_raw_input_to_lines(t, raw); - t->gl.flags |= NEEDS_BLIT; + t->gl.flags |= NEEDS_REFILL; } - if (t->gl.flags & (NEEDS_BLIT|NEEDS_FULL_BLIT)) + if (t->gl.flags & (NEEDS_REFILL|NEEDS_FULL_REFILL)) blit_lines(t, t->arena_for_frame, parsed_lines); update_selection(t); - /* NOTE: reset the camera/viewport */ - glUseProgram(t->gl.programs[SHADER_RENDER]); - glUniform1i(t->gl.render.texslot, 0); - glBindFramebuffer(GL_FRAMEBUFFER, t->gl.fb); + v2 ws = t->gl.window_size; - RenderPushBuffer *rpb = alloc(&t->arena_for_frame, RenderPushBuffer, 1); - clear_colour(); - render_framebuffer(t, rpb); + if (t->gl.flags & NEEDS_BLIT) { + glUseProgram(t->gl.programs[SHADER_RENDER]); + glUniform1i(t->gl.render.texslot, 0); + glBindFramebuffer(GL_FRAMEBUFFER, t->gl.fb); - v2 ws = t->gl.window_size; + RenderPushBuffer *rpb = alloc(&t->arena_for_frame, RenderPushBuffer, 1); + clear_colour(); + render_framebuffer(t, rpb); - if (0) { - v2 cell_size = get_cell_size(t); - v2 cursor_pos = { - .x = t->cursor.pos.x * cell_size.w, - .y = ws.h - cell_size.h * (t->cursor.pos.y + 1), - }; + if (0) { + v2 cell_size = get_cell_size(t); + v2 cursor_pos = { + .x = t->cursor.pos.x * cell_size.w, + .y = ws.h - cell_size.h * (t->cursor.pos.y + 1), + }; - v2 src_bl = {0}; - v2 src_tr = { .x = ws.w, .y = src_bl.y + ws.h }; + v2 src_bl = {0}; + v2 src_tr = {.x = ws.w, .y = src_bl.y + ws.h}; - if (t->cursor.pos.y > t->size.h) { - src_tr.y = cursor_pos.y + ws.h; - src_bl.y = cursor_pos.y; - } + if (t->cursor.pos.y > t->size.h) { + src_tr.y = cursor_pos.y + ws.h; + src_bl.y = cursor_pos.y; + } - s8 fps = s8alloc(&t->arena_for_frame, 64); - fps.len = snprintf((char *)fps.data, fps.len, "Render Time: %0.02f ms/f", last_frame_time * 1e3); - v2 ts = measure_text(&t->gl, fps, 1); - v2 pos = { - .x = ws.w - ts.x - 10, - .y = src_tr.y - ts.y - 10 - }; + s8 fps = s8alloc(&t->arena_for_frame, 64); + fps.len = snprintf((char *)fps.data, fps.len, "Render Time: %0.02f ms/f", + last_frame_time * 1e3); + v2 ts = measure_text(&t->gl, fps, 1); + v2 pos = {.x = ws.w - ts.x - 10, .y = src_tr.y - ts.y - 10}; - Rect r = { - .pos = {.x = pos.x - 0.05 * ts.x, .y = pos.y - 0.25 * ts.y}, - .size = {.w = ts.w * 1.1, .h = ts.h * 1.2}, - }; + Rect r = { + .pos = {.x = pos.x - 0.05 * ts.x, .y = pos.y - 0.25 * ts.y}, + .size = {.w = ts.w * 1.1, .h = ts.h * 1.2}, + }; - draw_rectangle(rpb, &t->gl, r, (Colour){.rgba = 0x303030ff}); - draw_text(rpb, &t->gl, fps, pos, (Colour){.rgba = 0x1e9e33ff}, 1); - } + draw_rectangle(rpb, &t->gl, r, (Colour){.rgba = 0x303030ff}); + draw_text(rpb, &t->gl, fps, pos, (Colour){.rgba = 0x1e9e33ff}, 1); + } - flush_render_push_buffer(rpb, &t->gl); + flush_render_push_buffer(rpb, &t->gl); + t->gl.flags &= ~NEEDS_BLIT; + } static f32 param = 0; static f32 p_scale = 1;