Commit: fab540b6a860a098902b477d89aca29587fbda6d
Parent: e2ff94b95e6c84c27b2aaa51aee38457b94fadb3
Author: Randy Palamar
Date: Tue, 3 Dec 2024 07:49:58 -0700
block terminal resizes while rendering
We aren't resizing every frame so its probably ok to push this
behind a lock.
Diffstat:
6 files changed, 55 insertions(+), 32 deletions(-)
diff --git a/debug.c b/debug.c
@@ -392,9 +392,8 @@ debug_frame_end(TerminalMemory *memory)
g_debug_table.snapshot_index++;
if (g_debug_table.snapshot_index == MAX_DEBUG_RECORD_COUNT)
g_debug_table.snapshot_index = 0;
- u64 event_array_event_index = __atomic_exchange_n(&g_debug_table.event_array_event_index,
- (u64)g_debug_table.snapshot_index << 32,
- __ATOMIC_ACQUIRE);
+ u64 event_array_event_index = atomic_exchange_n(&g_debug_table.event_array_event_index,
+ (u64)g_debug_table.snapshot_index << 32);
u32 array_index = event_array_event_index >> 32;
u32 event_count = event_array_event_index & 0xFFFFFFFF;
diff --git a/platform_linux_common.c b/platform_linux_common.c
@@ -22,6 +22,8 @@
#define VERSION "unknown"
#endif
+#define atomic_exchange_n(ptr, val) __atomic_exchange_n(ptr, val, __ATOMIC_SEQ_CST)
+
struct __attribute__((aligned(16))) stack_base {
void (*entry)(struct stack_base *stack);
Arena thread_arena;
diff --git a/platform_linux_x11.c b/platform_linux_x11.c
@@ -262,6 +262,10 @@ update_input(PlatformCtx *ctx)
ctx->char_stream.widx = 0;
struct timespec timeout = {.tv_nsec = 25e6};
+ if (input->pending_updates) {
+ timeout.tv_nsec = 0;
+ input->pending_updates = 0;
+ }
fd_set rfd;
FD_ZERO(&rfd);
diff --git a/util.h b/util.h
@@ -164,8 +164,9 @@ typedef struct {
X(texslot)
enum gl_flags {
- NEEDS_RESIZE = 1 << 0,
- NEEDS_REFILL = 1 << 1,
+ RESIZE_RENDERER = 1 << 0,
+ NEEDS_RESIZE = 1 << 1,
+ NEEDS_REFILL = 1 << 2,
DRAW_DEBUG_OVERLAY = 1 << 30,
};
@@ -415,7 +416,9 @@ typedef struct Term {
Cursor cursor;
Cursor saved_cursors[2];
+
TermView views[2];
+ i32 resize_lock;
i32 view_idx;
i32 scroll_offset;
diff --git a/vtgl.c b/vtgl.c
@@ -262,6 +262,9 @@ resize_terminal(Term *t, PlatformAPI *platform, iv2 window_size)
}
platform->set_terminal_size(t->child, t->size.h, t->size.w, ws.w, ws.h);
+
+ t->gl.flags |= RESIZE_RENDERER;
+ t->gl.flags &= ~NEEDS_RESIZE;
}
static void
@@ -304,7 +307,9 @@ resize(Term *t, PlatformAPI *platform, iv2 window_size)
sp->term_size_in_pixels = gl->window_size;
sp->term_size_in_cells = t->size;
- gl->flags &= ~NEEDS_RESIZE;
+ set_projection_matrix(gl);
+
+ gl->flags &= ~RESIZE_RENDERER;
}
static RenderCtx
@@ -509,13 +514,13 @@ render_framebuffer(Term *t, RenderCell *render_buf, TerminalInput *input, Arena
{
BEGIN_TIMED_BLOCK();
- TermView *tv = t->views + t->view_idx;
-
+ TermView *tv = t->views + t->view_idx;
+ iv2 term_size = t->size;
/* NOTE: draw whole framebuffer */
- for (u32 row = 0; row < t->size.h; row++) {
- for (u32 col = 0; col < t->size.w; col++) {
+ for (u32 row = 0; row < term_size.h; row++) {
+ for (u32 col = 0; col < term_size.w; col++) {
Cell c = tv->fb.rows[row][col];
- RenderCell *rc = render_buf + (row * t->size.w + col);
+ RenderCell *rc = render_buf + (row * term_size.w + col);
CachedGlyph *cg;
rc->gpu_glyph = get_gpu_glyph_index(arena, &t->gl, &t->fa, c.cp, 0,
@@ -536,12 +541,10 @@ render_framebuffer(Term *t, RenderCell *render_buf, TerminalInput *input, Arena
}
/* NOTE: draw selection if active */
- if (is_valid_range(t->selection.range)) {
- SelectionIterator si = selection_iterator(t->selection.range, tv->fb.rows, t->size.w);
- for (Cell *c = selection_next(&si); c; c = selection_next(&si)) {
- RenderCell *rc = render_buf + si.cursor.y * t->size.w + si.cursor.x;
- rc->fg ^= SHADER_PACK_ATTR(ATTR_INVERSE);
- }
+ SelectionIterator si = selection_iterator(t->selection.range, tv->fb.rows, term_size.w);
+ for (Cell *c = selection_next(&si); c; c = selection_next(&si)) {
+ RenderCell *rc = render_buf + si.cursor.y * term_size.w + si.cursor.x;
+ rc->fg ^= SHADER_PACK_ATTR(ATTR_INVERSE);
}
END_TIMED_BLOCK();
@@ -1234,13 +1237,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))
- resize(t, &memory->platform_api, input->window_size);
-
if (input->executable_reloaded) {
reload_all_shaders(memory);
}
@@ -1256,21 +1254,30 @@ DEBUG_EXPORT VTGL_RENDER_FRAME_FN(vtgl_render_frame)
BEGIN_NAMED_BLOCK(update_render);
- set_projection_matrix(&t->gl);
-
RenderCtx rc = make_render_ctx(&arena, &t->gl, &t->fa);
glUseProgram(t->gl.programs[SHADER_RENDER]);
glBindFramebuffer(GL_FRAMEBUFFER, t->gl.fb);
clear_colour();
- 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);
+ b32 can_render_term = atomic_exchange_n(&t->resize_lock, 1) == 0;
+ if (can_render_term) {
+ if (t->gl.flags & RESIZE_RENDERER)
+ resize(t, &memory->platform_api, input->window_size);
+
+ if (t->gl.queued_render) {
+ t->gl.queued_render = 0;
+ 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);
+ }
+ render_cursor(t, input->window_focused, arena);
+ t->resize_lock = 0;
+ } else if (t->gl.queued_render) {
+ input->pending_updates = 1;
}
- render_cursor(t, input->window_focused, arena);
ShaderParameters *sp = &t->gl.shader_parameters;
sp->blink_parameter += 2 * PI * g_blink_speed * dt_for_frame;
@@ -1322,8 +1329,15 @@ DEBUG_EXPORT VTGL_FRAME_STEP_FN(vtgl_frame_step)
t->temp_arena = begin_temp_arena(&t->arena_for_frame);
- if (t->gl.flags & NEEDS_RESIZE || !equal_iv2(input->window_size, t->gl.window_size))
- resize_terminal(t, &memory->platform_api, input->window_size);
+ if (t->gl.flags & NEEDS_RESIZE || !equal_iv2(input->window_size, t->gl.window_size)) {
+ b32 can_resize_term = atomic_exchange_n(&t->resize_lock, 1) == 0;
+ if (can_resize_term) {
+ resize_terminal(t, &memory->platform_api, input->window_size);
+ t->resize_lock = 0;
+ } else {
+ input->pending_updates = 1;
+ }
+ }
BEGIN_NAMED_BLOCK(mouse_and_keyboard_input);
if (input->character_input.len) {
diff --git a/vtgl.h b/vtgl.h
@@ -340,6 +340,7 @@ typedef struct TerminalInput {
b32 executable_reloaded;
b32 window_refreshed;
b32 window_focused;
+ b32 pending_updates;
u32 modifiers;