vtgl

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

Commit: 00951ccc0c8bc64084152eec08e0d52cdeed9197
Parent: dcf90db4c39ad0b3164b50b46dff5a44db85576a
Author: Randy Palamar
Date:   Tue, 22 Oct 2024 20:11:57 -0600

combine default 1x1 texture with glyph cache texture

This way we can batch rectangle drawing and glyph bitmap drawing
for overlay fonts.

Diffstat:
Mfont.c | 5+++++
Mmain.c | 6++++--
Mutil.h | 2--
Mvtgl.c | 50++++++++++++++++++++++++++++++++------------------
4 files changed, 41 insertions(+), 22 deletions(-)

diff --git a/font.c b/font.c @@ -221,6 +221,8 @@ render_glyph(Arena *a, FontAtlas *fa, u32 cp, enum face_style style, CachedGlyph cg->gpu_tile_index = (tile_coord.y << 16) | (tile_coord.x & 0xFFFF); } + /* NOTE: tile index 0,0 is reserved */ + ASSERT(cg->gpu_tile_index); ASSERT(tile_index); for (u32 i = 0; i < cg->tile_count; i++) @@ -258,6 +260,9 @@ font_atlas_update(FontAtlas *fa, iv2 glyph_bitmap_dim) mem_clear(gc->occupied_tiles, 0, sizeof(*gc->occupied_tiles) * gc->cache_len); get_and_clear_glyph_cache_stats(gc); + /* NOTE: reserve tile 0,0 */ + gc->occupied_tiles[0] = 1; + Font *font = &fa->fonts[0][FS_BOLD]; if (!font) font = &fa->fonts[0][FS_NORMAL]; i32 x0, x1, y0, y1; diff --git a/main.c b/main.c @@ -177,10 +177,12 @@ init_window(Term *t, Arena arena, iv2 window_size) glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * ARRAY_COUNT(rpb->positions) * sizeof(i32), element_indices, GL_STATIC_DRAW); - u32 white = 0xFFFFFFFF; - t->gl.default_tex = gen_2D_texture((iv2){.x = 1, .y = 1}, GL_RGBA, GL_NEAREST, &white); t->gl.glyph_bitmap_tex = gen_2D_texture(t->gl.glyph_bitmap_dim, GL_RGBA, GL_NEAREST, 0); + /* NOTE: set pixel 0,0 to white (tile 0,0 is reserved). We can use this texture for + * drawing glyphs from the font cache or for drawing plain rectangles */ + u32 white = 0xFFFFFFFF; + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &white); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); diff --git a/util.h b/util.h @@ -242,8 +242,6 @@ typedef struct { u32 fb, fb_tex, fb_tex_unit; - u32 default_tex; - u32 programs[SHADER_LAST]; #define X(name) i32 name; struct { GL_POST_UNIFORMS } post; diff --git a/vtgl.c b/vtgl.c @@ -200,7 +200,7 @@ get_render_push_buffer_idx(RenderPushBuffer *rpb, GLCtx *gl, u32 count) } static void -push_rect(RenderPushBuffer *rpb, GLCtx *gl, Rect r, v4 colour, b32 flip_texture) +push_rect_full(RenderPushBuffer *rpb, GLCtx *gl, Rect r, v4 colour, v2 min_tex_coord, v2 max_tex_coord) { u32 idx = get_render_push_buffer_idx(rpb, gl, 4); v2 start = r.pos; @@ -211,23 +211,38 @@ push_rect(RenderPushBuffer *rpb, GLCtx *gl, Rect r, v4 colour, b32 flip_texture) rpb->positions[idx + 2] = (v2){.x = start.x, .y = start.y}; rpb->positions[idx + 3] = (v2){.x = start.x, .y = end.y }; - /* TODO: cleanup */ - if (!flip_texture) { - rpb->texture_coordinates[idx + 0] = (v2){.x = 1.0f, .y = 1.0f}; - rpb->texture_coordinates[idx + 1] = (v2){.x = 1.0f, .y = 0.0f}; - rpb->texture_coordinates[idx + 2] = (v2){.x = 0.0f, .y = 0.0f}; - rpb->texture_coordinates[idx + 3] = (v2){.x = 0.0f, .y = 1.0f}; - } else { - rpb->texture_coordinates[idx + 0] = (v2){.x = 1.0f, .y = 0.0f}; - rpb->texture_coordinates[idx + 1] = (v2){.x = 1.0f, .y = 1.0f}; - rpb->texture_coordinates[idx + 2] = (v2){.x = 0.0f, .y = 1.0f}; - rpb->texture_coordinates[idx + 3] = (v2){.x = 0.0f, .y = 0.0f}; - } + rpb->texture_coordinates[idx + 0] = (v2){.x = max_tex_coord.x, .y = max_tex_coord.y}; + rpb->texture_coordinates[idx + 1] = (v2){.x = max_tex_coord.x, .y = min_tex_coord.y}; + rpb->texture_coordinates[idx + 2] = (v2){.x = min_tex_coord.x, .y = min_tex_coord.y}; + rpb->texture_coordinates[idx + 3] = (v2){.x = min_tex_coord.x, .y = max_tex_coord.y}; rpb->colours[idx + 0] = colour; rpb->colours[idx + 1] = colour; rpb->colours[idx + 2] = colour; rpb->colours[idx + 3] = colour; + +} + +static void +push_rect_textured(RenderPushBuffer *rpb, GLCtx *gl, Rect r, v4 colour, b32 flip_texture) +{ + v2 min_tex_coord, max_tex_coord; + if (!flip_texture) { + max_tex_coord = (v2){.x = 1.0f, .y = 1.0f}; + min_tex_coord = (v2){.x = 0.0f, .y = 0.0f}; + } else { + max_tex_coord = (v2){.x = 1.0f, .y = 0.0f}; + min_tex_coord = (v2){.x = 0.0f, .y = 1.0f}; + } + push_rect_full(rpb, gl, r, colour, min_tex_coord, max_tex_coord); +} + +static void +push_rect(RenderPushBuffer *rpb, GLCtx *gl, Rect r, v4 colour) +{ + f32 max_x = 1.0f / gl->glyph_bitmap_dim.x; + f32 max_y = 1.0f / gl->glyph_bitmap_dim.y; + push_rect_full(rpb, gl, r, colour, (v2){0}, (v2){.x = max_x, .y = max_y}); } #if 0 @@ -835,7 +850,7 @@ do_terminal(Term *t, f32 dt) glBindBufferBase(GL_UNIFORM_BUFFER, 0, t->gl.render_shader_ubo); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(*sp), sp); - push_rect(rpb, &t->gl, (Rect){.size = t->gl.window_size}, (v4){0}, 0); + push_rect_textured(rpb, &t->gl, (Rect){.size = t->gl.window_size}, (v4){0}, 0); flush_render_push_buffer(rpb, &t->gl); static f32 param = 0; @@ -851,16 +866,15 @@ do_terminal(Term *t, f32 dt) glUniform1i(t->gl.post.texslot, t->gl.fb_tex_unit); glUniform1f(t->gl.post.param, param); - push_rect(rpb, &t->gl, (Rect){.size = t->gl.window_size}, (v4){0}, 1); + push_rect_textured(rpb, &t->gl, (Rect){.size = t->gl.window_size}, (v4){0}, 1); flush_render_push_buffer(rpb, &t->gl); #if 0 /* NOTE: this happens at the end so that ui stuff doesn't go through the post * processing/effects shader */ glUseProgram(t->gl.programs[SHADER_RECTS]); - glBindTexture(GL_TEXTURE_2D, t->gl.default_tex); - push_rect(rpb, &t->gl, (Rect){.size = {.w = 300, .h = 200}}, (v4){.r = 0.5, .a = 1}, 0); - push_rect(rpb, &t->gl, (Rect){.pos = {.x = 300, .y = 200}, .size = {.w = 300, .h = 200}}, (v4){.g = 0.5, .a = 1}, 0); + push_rect(rpb, &t->gl, (Rect){.size = {.w = 300, .h = 200}}, (v4){.r = 0.5, .a = 1}); + push_rect(rpb, &t->gl, (Rect){.pos = {.x = 300, .y = 200}, .size = {.w = 300, .h = 200}}, (v4){.g = 0.5, .a = 1}); flush_render_push_buffer(rpb, &t->gl); #endif }