vtgl

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

Commit: 44c66d713476841767a1ea3ab1804160535651a7
Parent: ce58f33b0b4890f4d698377161a5eee187e29dac
Author: Randy Palamar
Date:   Tue, 27 Aug 2024 06:56:33 -0600

use a static buffer for render_glyph and cleanup some misuse of Term *

Diffstat:
Mfont.c | 31+++++++++++++++++--------------
Mvtgl.c | 54++++++++++++++++++++++++++----------------------------
2 files changed, 43 insertions(+), 42 deletions(-)

diff --git a/font.c b/font.c @@ -159,8 +159,10 @@ get_and_clear_glyph_cache_stats(GlyphCache *gc) return result; } +static u32 glyph_buf[MAX_FONT_SIZE * MAX_FONT_SIZE * sizeof(u32)]; + static u32 * -render_glyph(FontAtlas *fa, Arena a, u32 cp, Glyph *out_glyph, u32 *out_idx) +render_glyph(FontAtlas *fa, u32 cp, Glyph *out_glyph, u32 *out_idx) { /* NOTE: first check if glyph is in the cache and valid */ u32 idx = get_glyph_entry_index(&fa->glyph_cache, cp); @@ -194,7 +196,7 @@ render_glyph(FontAtlas *fa, Arena a, u32 cp, Glyph *out_glyph, u32 *out_idx) cg->g.delta.x = gs->bitmap_left; cg->g.delta.y = gs->bitmap_top - cg->g.size.h; - u32 *rgba_bitmap = alloc(&a, u32, cg->g.size.h * cg->g.size.w); + u32 *rgba_bitmap = mem_clear((u8 *)glyph_buf, 0, sizeof(glyph_buf)); for (u32 i = 0; i < cg->g.size.h; i++) { for (u32 j = 0; j < cg->g.size.w; j++) { /* TODO: handled coloured glyphs */ @@ -211,27 +213,28 @@ render_glyph(FontAtlas *fa, Arena a, u32 cp, Glyph *out_glyph, u32 *out_idx) } static void -update_font_metrics(Term *t) +update_font_metrics(FontAtlas *fa) { - t->fa.size.h = 0; - t->fa.size.w = 0; - t->fa.deltay = 0; + fa->size.h = 0; + fa->size.w = 0; + fa->deltay = 0; Glyph g; u32 index; for (u32 i = ' '; i <= '~'; i++) { - render_glyph(&t->fa, t->arena_for_frame, i, &g, &index); - t->fa.size.h = MAX(t->fa.size.h, g.size.h); - t->fa.size.w = MAX(t->fa.size.w, g.size.w); - t->fa.deltay = MAX(t->fa.deltay, -g.delta.y); + render_glyph(fa, i, &g, &index); + fa->size.h = MAX(fa->size.h, g.size.h); + fa->size.w = MAX(fa->size.w, g.size.w); + fa->deltay = MAX(fa->deltay, -g.delta.y); } /* NOTE: ' ' has 0 size in freetype but we need it to have a width! */ - render_glyph(&t->fa, t->arena_for_frame, ' ', &g, &index); - t->fa.glyph_cache.glyphs[index].g.size.w = t->fa.size.w; + render_glyph(fa, ' ', &g, &index); + fa->glyph_cache.glyphs[index].g.size.w = fa->size.w; } static void -initialize_glyph_cache(GlyphCache *gc) +initialize_glyph_cache(FontAtlas *fa) { + GlyphCache *gc = &fa->glyph_cache; mem_clear((u8 *)gc->glyphs, 0, sizeof(*gc->glyphs) * gc->cache_len); mem_clear((u8 *)gc->hash_table, 0, sizeof(*gc->hash_table) * gc->cache_len); for(u32 i = 0; i < gc->cache_len - 1; i++) @@ -275,5 +278,5 @@ init_fonts(Term *t, Arena *a) t->fa.glyph_cache.glyphs = alloc(a, CachedGlyph, t->fa.glyph_cache.cache_len); t->fa.glyph_cache.hash_table = alloc(a, u32, t->fa.glyph_cache.cache_len); - initialize_glyph_cache(&t->fa.glyph_cache); + initialize_glyph_cache(&t->fa); } diff --git a/vtgl.c b/vtgl.c @@ -120,20 +120,20 @@ resize(Term *t) } static void -update_font_textures(Term *t) +update_font_textures(GLCtx *gl, FontAtlas *fa) { glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D_ARRAY, t->gl.glyph_tex); + glBindTexture(GL_TEXTURE_2D_ARRAY, gl->glyph_tex); glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, MAX_FONT_SIZE, MAX_FONT_SIZE, TEXTURE_GLYPH_COUNT, 0, GL_RED, GL_UNSIGNED_BYTE, 0); - initialize_glyph_cache(&t->fa.glyph_cache); + initialize_glyph_cache(fa); for (u32 i = ' '; i <= '~'; i++) { u32 depth_idx; Glyph g; - u32 *data = render_glyph(&t->fa, t->arena_for_frame, i, &g, &depth_idx); + u32 *data = render_glyph(fa, i, &g, &depth_idx); if (data) { ASSERT(depth_idx); glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, depth_idx, @@ -141,7 +141,7 @@ update_font_textures(Term *t) GL_UNSIGNED_BYTE, data); } } - update_font_metrics(t); + update_font_metrics(fa); } static void @@ -171,14 +171,14 @@ update_uniforms(Term *t, enum shader_stages stage) set_projection_matrix(&t->gl); /* TODO: this doesn't need to be called so often */ - update_font_textures(t); + update_font_textures(&t->gl, &t->fa); } static i32 -get_gpu_glyph_index(Term *t, u32 codepoint, Glyph *out_glyph) +get_gpu_glyph_index(FontAtlas *fa, u32 codepoint, Glyph *out_glyph) { u32 depth_idx; - u32 *data = render_glyph(&t->fa, t->arena_for_frame, codepoint, out_glyph, &depth_idx); + u32 *data = render_glyph(fa, codepoint, out_glyph, &depth_idx); if (data) { ASSERT(depth_idx); glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, depth_idx, @@ -189,19 +189,19 @@ get_gpu_glyph_index(Term *t, u32 codepoint, Glyph *out_glyph) } static v2 -measure_text(GLCtx *gl, s8 text, b32 monospaced) +measure_text(FontAtlas *fa, s8 text, b32 monospaced) { v2 result = {0}; -#if 0 - f32 single_space_width = gl->glyph_cache[0].size.w; + Glyph g; + get_gpu_glyph_index(fa, ' ', &g); + f32 single_space_width = g.size.w; for (size i = 0; i < text.len; i++) { - Glyph g = gl->glyph_cache[text.data[i] - ' ']; + get_gpu_glyph_index(fa, text.data[i], &g); /* TODO: should we consider offset characters in y? */ if (g.size.h > result.y) result.y = g.size.h; result.x += monospaced? single_space_width : g.size.w; } -#endif return result; } @@ -254,21 +254,20 @@ push_empty_cell_rect(RenderPushBuffer *rpb, Term *t, u32 minrow, u32 maxrow, u32 } static void -draw_text(RenderPushBuffer *rpb, GLCtx *gl, s8 text, v2 position, Colour colour, b32 monospaced) +draw_text(RenderPushBuffer *rpb, GLCtx *gl, FontAtlas *fa, s8 text, v2 position, Colour colour, b32 monospaced) { - #if 0 - f32 single_space_width = gl->glyph_cache[0].size.w; + Glyph g; + get_gpu_glyph_index(fa, ' ', &g); + f32 single_space_width = g.size.w; for (size i = 0; i < text.len; i++) { - Glyph g; u32 cp = text.data[i]; - i32 glyph_idx = get_gpu_glyph_index(gl, cp, &g); + i32 glyph_idx = get_gpu_glyph_index(fa, cp, &g); v2 texscale = {.x = g.size.w / MAX_FONT_SIZE, .y = g.size.h / MAX_FONT_SIZE}; v2 vertscale = {.x = g.size.w, .y = g.size.h}; v2 vertoff = {.x = position.x + g.delta.x, .y = position.y + g.delta.y}; push_char(rpb, gl, vertscale, vertoff, texscale, (uv2){.x = colour.rgba}, glyph_idx); position.x += monospaced? single_space_width : g.size.w; } - #endif } static void @@ -277,15 +276,14 @@ draw_rectangle(RenderPushBuffer *rpb, GLCtx *gl, Rect r, Colour colour) push_char(rpb, gl, r.size, r.pos, (v2){0}, (uv2){.y = colour.rgba}, 0); } -/* TODO: this doesn't need to take the whole Term * */ static void -push_cell(RenderPushBuffer *rpb, Term *t, Cell c, Rect r, f32 font_text_dy) +push_cell(RenderPushBuffer *rpb, GLCtx *gl, FontAtlas *fa, Cell c, Rect r, f32 font_text_dy) { - u32 idx = get_render_push_buffer_idx(rpb, &t->gl, 2); + u32 idx = get_render_push_buffer_idx(rpb, gl, 2); ASSERT(c.cp); Glyph g; - i32 depth_idx = get_gpu_glyph_index(t, c.cp, &g); + i32 depth_idx = get_gpu_glyph_index(fa, c.cp, &g); rpb->vertscales[idx + 0] = r.size; rpb->vertscales[idx + 1] = (v2){.x = g.size.w, .y = g.size.h}; @@ -330,7 +328,7 @@ push_cell_row(Term *t, Cell *row, u32 len, b32 inverse, Rect cr, RenderPushBuffe if (cell.style.attr & ATTR_WIDE) cr.size = csw; else cr.size = cs; cell.style.attr ^= inverse * ATTR_INVERSE; - push_cell(rpb, t, cell, cr, t->fa.deltay); + push_cell(rpb, &t->gl, &t->fa, cell, cr, t->fa.deltay); cr.pos.x += cr.size.w; } } @@ -384,7 +382,7 @@ render_framebuffer(Term *t, RenderPushBuffer *rpb) if (cursor.style.attr & ATTR_WIDE) cr.size.w *= 2; cursor.style.attr ^= ATTR_INVERSE; - push_cell(rpb, t, cursor, cr, t->fa.deltay); + push_cell(rpb, &t->gl, &t->fa, cursor, cr, t->fa.deltay); } } @@ -547,7 +545,7 @@ KEYBIND_FN(scroll) KEYBIND_FN(zoom) { shift_font_sizes(&t->fa, a.i); - update_font_textures(t); + update_font_textures(&t->gl, &t->fa); t->gl.flags |= NEEDS_RESIZE; return 1; } @@ -832,7 +830,7 @@ do_terminal(Term *t) 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 ts = measure_text(&t->fa, fps, 1); v2 pos = {.x = ws.w - ts.x - 10, .y = src_tr.y - ts.y - 10}; Rect r = { @@ -841,7 +839,7 @@ do_terminal(Term *t) }; draw_rectangle(rpb, &t->gl, r, (Colour){.rgba = 0x303030ff}); - draw_text(rpb, &t->gl, fps, pos, (Colour){.rgba = 0x1e9e33ff}, 1); + draw_text(rpb, &t->gl, &t->fa, fps, pos, (Colour){.rgba = 0x1e9e33ff}, 1); } flush_render_push_buffer(rpb, &t->gl);