vtgl

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

Commit: 216c2baee2b37bcc99db63176fbbb5f71cda4c63
Parent: 106916dc7f689fcdf4961d3da1f57a52582ac88d
Author: Randy Palamar
Date:   Mon,  2 Dec 2024 05:38:11 -0700

don't clobber pending renders when the input and render threads overlap

Diffstat:
Mutil.h | 3++-
Mvtgl.c | 50++++++++++++++++++++++++--------------------------
2 files changed, 26 insertions(+), 27 deletions(-)

diff --git a/util.h b/util.h @@ -166,7 +166,6 @@ typedef struct { enum gl_flags { NEEDS_RESIZE = 1 << 0, NEEDS_REFILL = 1 << 1, - UPDATE_RENDER_BUFFER = 1 << 2, DRAW_DEBUG_OVERLAY = 1 << 30, }; @@ -219,6 +218,8 @@ typedef struct { u32 glyph_bitmap_tex; u32 flags; + + u32 queued_render; } GLCtx; typedef struct { diff --git a/vtgl.c b/vtgl.c @@ -237,12 +237,11 @@ get_terminal_top_left(Term *t) static void resize_terminal(Term *t, PlatformAPI *platform, iv2 window_size) { - iv2 old_size = t->size; - v2 ws = v2_from_iv2(window_size); ws.w -= 2 * g_term_margin.w; ws.h -= 2 * g_term_margin.h; + iv2 old_size = t->size; v2 cs = get_cell_size(&t->fa); t->size.w = (i32)(ws.w / cs.w); t->size.h = (i32)(ws.h / cs.h); @@ -288,12 +287,16 @@ resize(Term *t, PlatformAPI *platform, iv2 window_size) glBufferData(GL_SHADER_STORAGE_BUFFER, buffer_size, 0, GL_DYNAMIC_DRAW); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, gl->render_shader_ssbo); LABEL_GL_OBJECT(GL_BUFFER, gl->render_shader_ssbo, s8("RenderCells")); - gl->flags |= UPDATE_RENDER_BUFFER; + gl->queued_render = 1; v2 cs = get_cell_size(&t->fa); ShaderParameters *sp = &gl->shader_parameters; sp->cell_size = (iv2){.w = cs.w, .h = cs.h}; + sp->strike_min = (t->fa.info.baseline + 0.40 * t->fa.info.h); + sp->strike_max = (t->fa.info.baseline + 0.48 * t->fa.info.h); + sp->underline_min = (0.89 * t->fa.info.h); + sp->underline_max = (0.96 * t->fa.info.h); sp->top_left_margin = g_term_margin; sp->margin_colour = g_colours.data[g_colours.bgidx].rgba; //sp->margin_colour = 0x7f003f00; @@ -511,24 +514,23 @@ render_framebuffer(Term *t, RenderCell *render_buf, TerminalInput *input, Arena /* NOTE: draw whole framebuffer */ for (u32 row = 0; row < t->size.h; row++) { for (u32 col = 0; col < t->size.w; col++) { - Cell *c = &tv->fb.rows[row][col]; + Cell c = tv->fb.rows[row][col]; RenderCell *rc = render_buf + (row * t->size.w + col); CachedGlyph *cg; - rc->gpu_glyph = get_gpu_glyph_index(arena, &t->gl, &t->fa, c->cp, 0, - c->bg & FS_MASK, &cg); - rc->fg = c->fg; - rc->bg = c->bg; + rc->gpu_glyph = get_gpu_glyph_index(arena, &t->gl, &t->fa, c.cp, 0, + c.bg & FS_MASK, &cg); + rc->fg = c.fg; + rc->bg = c.bg; /* TODO: there is probably a better way to do this */ u32 tiles = cg->tile_count; if (tiles > 1) { - for (u32 i = 1; i < tiles; i++) { - rc[i].gpu_glyph = rc->gpu_glyph + i; - rc[i].fg = rc->fg; - rc[i].bg = rc->bg; - } - col += tiles - 1; + ASSERT(tiles == 2); + rc[1].gpu_glyph = rc->gpu_glyph + 1; + rc[1].fg = rc->fg; + rc[1].bg = rc->bg; + col++; } } } @@ -645,7 +647,7 @@ begin_selection(Term *t, u32 click_count, v2 mouse) case SS_NONE: break; } - t->gl.flags |= UPDATE_RENDER_BUFFER; + t->gl.queued_render = 1; } static void @@ -684,7 +686,7 @@ update_selection(Term *t, TerminalInput *input) sel->range = normalize_range(sel->range); if (!equal_range(old_range, sel->range)) - t->gl.flags |= UPDATE_RENDER_BUFFER; + t->gl.queued_render = 1; } KEYBIND_FN(copy) @@ -1231,6 +1233,8 @@ DEBUG_EXPORT VTGL_RENDER_FRAME_FN(vtgl_render_frame) dt_for_frame = input->dt; + b32 update_render_buffer = __atomic_exchange_n(&t->gl.queued_render, 0, __ATOMIC_SEQ_CST); + TempArena temp_arena = begin_temp_arena(&arena); if (t->gl.flags & NEEDS_RESIZE || !equal_iv2(input->window_size, t->gl.window_size)) @@ -1259,23 +1263,17 @@ DEBUG_EXPORT VTGL_RENDER_FRAME_FN(vtgl_render_frame) glBindFramebuffer(GL_FRAMEBUFFER, t->gl.fb); clear_colour(); - if (t->gl.flags & UPDATE_RENDER_BUFFER) { + if (update_render_buffer) { u32 cell_count = t->size.h * t->size.w; RenderCell *render_buf = alloc(&arena, RenderCell, cell_count); render_framebuffer(t, render_buf, input, arena); glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, cell_count * sizeof(*render_buf), render_buf); - t->gl.flags &= ~UPDATE_RENDER_BUFFER; } render_cursor(t, input->window_focused, arena); ShaderParameters *sp = &t->gl.shader_parameters; sp->blink_parameter += 2 * PI * g_blink_speed * dt_for_frame; if (sp->blink_parameter > 2 * PI) sp->blink_parameter -= 2 * PI; - sp->strike_min = (t->fa.info.baseline + 0.40 * t->fa.info.h); - sp->strike_max = (t->fa.info.baseline + 0.48 * t->fa.info.h); - sp->underline_min = (0.89 * t->fa.info.h); - sp->underline_max = (0.96 * t->fa.info.h); - sp->reverse_video_mask = REVERSE_VIDEO_MASK * !!(t->mode.win & WM_REVERSE); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(*sp), sp); @@ -1340,7 +1338,7 @@ DEBUG_EXPORT VTGL_FRAME_STEP_FN(vtgl_frame_step) if (t->gl.flags & NEEDS_REFILL) { blit_lines(t, t->arena_for_frame); - t->gl.flags |= UPDATE_RENDER_BUFFER; + t->gl.queued_render = 1; } BEGIN_NAMED_BLOCK(input_from_child); @@ -1358,7 +1356,7 @@ DEBUG_EXPORT VTGL_FRAME_STEP_FN(vtgl_frame_step) .data = rb->buf + (rb->widx - t->unprocessed_bytes) }; handle_input(t, t->arena_for_frame, raw); - t->gl.flags |= UPDATE_RENDER_BUFFER; + t->gl.queued_render = 1; } END_NAMED_BLOCK(input_from_child); @@ -1370,7 +1368,7 @@ DEBUG_EXPORT VTGL_FRAME_STEP_FN(vtgl_frame_step) END_TIMED_BLOCK(); - return (t->gl.flags & UPDATE_RENDER_BUFFER) || input->window_refreshed; + return t->gl.queued_render || input->window_refreshed; } #ifdef _DEBUG