vtgl

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

Commit: 5232c4700ed13bd370bba4300d754cdc00beadb1
Parent: ba72915bf16cf84ddee5f940c76783e64318d191
Author: Randy Palamar
Date:   Tue, 22 Apr 2025 21:17:58 -0600

core: pass OS * in to more functions directly

Diffstat:
Mos.h | 11++++-------
Mos_linux_common.c | 6+++++-
Mos_linux_x11.c | 40++++++++++++++++++++--------------------
Mutil.h | 4+---
Mvtgl.c | 35+++++++++++++++++------------------
Mvtgl.h | 9++++-----
Mvtgl_static.c | 15+++++++--------
7 files changed, 58 insertions(+), 62 deletions(-)

diff --git a/os.h b/os.h @@ -25,6 +25,7 @@ typedef struct { u8 *data; } OSRingBuffer; +typedef struct OS OS; /* NOTE: for now we will do the callback route but this will change if we do multithreading */ #define OS_FILE_WATCH_CALLBACK_FN(name) void name(u8 *path, void *user_ctx) typedef OS_FILE_WATCH_CALLBACK_FN(os_file_watch_callback_fn); @@ -58,7 +59,7 @@ typedef OS_GET_WINDOW_TITLE_FN(os_get_window_title_fn); #define OS_SET_WINDOW_TITLE_FN(name) void name(s8 title) typedef OS_SET_WINDOW_TITLE_FN(os_set_window_title_fn); -#define OS_THREAD_ENTRY_POINT_FN(name) i64 name(iptr context, i32 *sync) +#define OS_THREAD_ENTRY_POINT_FN(name) i64 name(OS *os, iptr context, i32 *sync) typedef OS_THREAD_ENTRY_POINT_FN(os_thread_entry_point_fn); #define OS_GL_SWAP_BUFFERS_FN(name) void name(iptr window) @@ -67,7 +68,7 @@ typedef OS_GL_SWAP_BUFFERS_FN(os_gl_swap_buffers_fn); #define OS_GL_MAKE_CONTEXT_CURRENT_FN(name) void name(iptr window) typedef OS_GL_MAKE_CONTEXT_CURRENT_FN(os_gl_make_context_current_fn); -#define OS_SPAWN_THREAD_FN(name) i32 *name(os_thread_entry_point_fn *entry_point, \ +#define OS_SPAWN_THREAD_FN(name) i32 *name(OS *os, os_thread_entry_point_fn *entry_point, \ char *thread_name, iptr user_context) typedef OS_SPAWN_THREAD_FN(os_spawn_thread_fn); @@ -97,12 +98,8 @@ typedef OS_WRITE_FN(os_write_fn); X(wake_waiters) \ X(write) -typedef struct { #define X(name) os_ ## name ## _fn *name; - OS_FUNCTIONS +struct OS { OS_FUNCTIONS }; #undef X - u8 path_separator; -} OS; - #endif /* _OS_H_ */ diff --git a/os_linux_common.c b/os_linux_common.c @@ -70,6 +70,7 @@ typedef __attribute__((aligned(16))) u8 statx_buffer[256]; struct __attribute__((aligned(16))) stack_base { void (*entry)(struct stack_base *stack); + OS *os; os_thread_entry_point_fn *user_entry_point; iptr user_context; char name[16]; @@ -100,6 +101,8 @@ typedef struct { Arena platform_memory; void *window; + OS os; + TerminalMemory memory; TerminalInput input; @@ -533,7 +536,7 @@ function void thread_entry_point(struct stack_base *stack) { syscall2(SYS_prctl, PR_SET_NAME, (iptr)stack->name); - i64 result = stack->user_entry_point(stack->user_context, &stack->futex); + i64 result = stack->user_entry_point(stack->os, stack->user_context, &stack->futex); syscall1(SYS_exit, result); __builtin_unreachable(); } @@ -549,6 +552,7 @@ function OS_SPAWN_THREAD_FN(os_spawn_thread) stack->entry = thread_entry_point; stack->user_entry_point = entry_point; stack->user_context = user_context; + stack->os = os; new_thread(stack); diff --git a/os_linux_x11.c b/os_linux_x11.c @@ -165,7 +165,7 @@ key_callback(GLFWwindow *win, i32 key, i32 scancode, i32 action, i32 modifiers) button_action(input->keys + KEY_MENU, action == GLFW_PRESS); break; } - vtgl_handle_keys(&ctx->memory, &ctx->input, key, action, modifiers); + vtgl_handle_keys(&ctx->os, &ctx->memory, &ctx->input, key, action, modifiers); } function void @@ -420,22 +420,21 @@ main(i32 argc, char *argv[], char *envp[]) linux_add_file_watch((u8 *)DEBUG_LIB_NAME, debug_reload_library, &linux_ctx); #endif - linux_ctx.memory.os.add_file_watch = linux_add_file_watch; - linux_ctx.memory.os.allocate_ring_buffer = os_allocate_ring_buffer; - linux_ctx.memory.os.get_clipboard = x11_get_clipboard; - linux_ctx.memory.os.set_clipboard = x11_set_clipboard; - linux_ctx.memory.os.read_file = os_read_file; - linux_ctx.memory.os.read = os_read; - linux_ctx.memory.os.set_terminal_size = os_set_terminal_size; - linux_ctx.memory.os.get_window_title = x11_get_window_title; - linux_ctx.memory.os.set_window_title = x11_set_window_title; - linux_ctx.memory.os.gl_swap_buffers = glfw_swap_buffers; - linux_ctx.memory.os.gl_make_context_current = glfw_make_context_current; - linux_ctx.memory.os.spawn_thread = os_spawn_thread; - linux_ctx.memory.os.wait_on_value = os_wait_on_value; - linux_ctx.memory.os.wake_waiters = os_wake_waiters; - linux_ctx.memory.os.write = os_write; - linux_ctx.memory.os.path_separator = '/'; + linux_ctx.os.add_file_watch = linux_add_file_watch; + linux_ctx.os.allocate_ring_buffer = os_allocate_ring_buffer; + linux_ctx.os.get_clipboard = x11_get_clipboard; + linux_ctx.os.set_clipboard = x11_set_clipboard; + linux_ctx.os.read_file = os_read_file; + linux_ctx.os.read = os_read; + linux_ctx.os.set_terminal_size = os_set_terminal_size; + linux_ctx.os.get_window_title = x11_get_window_title; + linux_ctx.os.set_window_title = x11_set_window_title; + linux_ctx.os.gl_swap_buffers = glfw_swap_buffers; + linux_ctx.os.gl_make_context_current = glfw_make_context_current; + linux_ctx.os.spawn_thread = os_spawn_thread; + linux_ctx.os.wait_on_value = os_wait_on_value; + linux_ctx.os.wake_waiters = os_wake_waiters; + linux_ctx.os.write = os_write; if (!glfwInit()) os_fatal(s8("Failed to init GLFW\n")); @@ -454,8 +453,9 @@ main(i32 argc, char *argv[], char *envp[]) iv2 window_size = {.w = 1280, .h = 720}; linux_ctx.window = init_window(&linux_ctx, window_size); - iv2 requested_size = vtgl_initialize(&linux_ctx.memory, &linux_ctx.input, linux_ctx.window, - linux_ctx.child.handle, cells, monitor_size); + iv2 requested_size = vtgl_initialize(&linux_ctx.os, &linux_ctx.memory, &linux_ctx.input, + linux_ctx.window, linux_ctx.child.handle, cells, + monitor_size); if (requested_size.w > 0 && requested_size.h > 0 && (requested_size.w != window_size.w || requested_size.h != window_size.h)) { @@ -492,7 +492,7 @@ main(i32 argc, char *argv[], char *envp[]) last_time = current_time; update_input(&linux_ctx); - vtgl_frame_step(&linux_ctx.memory, &linux_ctx.input); + vtgl_frame_step(&linux_ctx.os, &linux_ctx.memory, &linux_ctx.input); Range current_sel = vtgl_active_selection(&linux_ctx.memory, 0); if (is_valid_range(current_sel) && !equal_range(current_sel, last_sel)) { diff --git a/util.h b/util.h @@ -479,8 +479,6 @@ typedef struct { Arena arena; - OS *os; - /* TODO(rnp): cleanup */ TerminalInput *input; TerminalMemory *memory; @@ -501,7 +499,7 @@ typedef enum { TS_NEEDS_REFILL = 1 << 1, } TerminalState; -typedef struct Term { +typedef struct { Arena arena_for_frame; TempArena temp_arena; diff --git a/vtgl.c b/vtgl.c @@ -828,7 +828,6 @@ terminal_interaction(Term *t, OS *os, TerminalInput *input, u32 click_count) DEBUG_EXPORT VTGL_HANDLE_KEYS_FN(vtgl_handle_keys) { Term *t = memory->memory; - OS *os = &memory->os; iptr child = t->child; #ifdef _DEBUG @@ -854,7 +853,7 @@ DEBUG_EXPORT VTGL_HANDLE_KEYS_FN(vtgl_handle_keys) for (u32 i = 0; i < ARRAY_COUNT(g_hotkeys); i++) { struct hotkey *hk = g_hotkeys + i; if (hk->key == enc) { - b32 handled = hk->fn(t, &memory->os, hk->arg); + b32 handled = hk->fn(t, os, hk->arg); if (handled) return; } @@ -1054,7 +1053,8 @@ try_wait_sync(i32 *sync, i32 timeout_ms, os_wait_on_value_fn *os_wait_on_value) } function void -vtgl_render_frame(RenderThreadContext *ctx, TerminalMemory *memory, TerminalInput *input, Arena arena) +vtgl_render_frame(OS *os, RenderThreadContext *ctx, TerminalMemory *memory, + TerminalInput *input, Arena arena) { BEGIN_TIMED_BLOCK(); @@ -1066,12 +1066,11 @@ vtgl_render_frame(RenderThreadContext *ctx, TerminalMemory *memory, TerminalInpu while (work) { switch (work->kind) { case WQK_RELOAD_SHADER: { - reload_shader(ctx->os, &ctx->gl, work->shader_reload_context, arena); + reload_shader(os, &ctx->gl, work->shader_reload_context, arena); } break; case WQK_RELOAD_ALL_SHADERS: { for (i32 i = 0; i < SID_LAST; i++) { - reload_shader(ctx->os, &ctx->gl, ctx->shader_reload_contexts + i, - arena); + reload_shader(os, &ctx->gl, ctx->shader_reload_contexts + i, arena); } } break; default: INVALID_CODE_PATH; @@ -1101,7 +1100,7 @@ vtgl_render_frame(RenderThreadContext *ctx, TerminalMemory *memory, TerminalInpu while (atomic_exchange_n(&t->resize_lock, 1) != 0); if (ctx->gl.flags & RESIZE_RENDERER) - resize(t, &memory->os, input->window_size); + resize(t, os, input->window_size); if (ctx->gl.queued_render) { ctx->gl.queued_render = 0; @@ -1154,9 +1153,9 @@ vtgl_render_frame(RenderThreadContext *ctx, TerminalMemory *memory, TerminalInpu } function void -vtgl_render_thread_initialize(RenderThreadContext *ctx) +vtgl_render_thread_initialize(OS *os, RenderThreadContext *ctx) { - ctx->os->gl_make_context_current(ctx->window); + os->gl_make_context_current(ctx->window); ctx->error_stream = stream_alloc(&ctx->arena, KB(1)); @@ -1245,11 +1244,11 @@ DEBUG_EXPORT OS_THREAD_ENTRY_POINT_FN(vtgl_render_thread_entry) { RenderThreadContext *ctx = (RenderThreadContext *)context; - vtgl_render_thread_initialize(ctx); + vtgl_render_thread_initialize(os, ctx); for (;;) { - try_wait_sync(sync, -1, ctx->os->wait_on_value); - vtgl_render_frame(ctx, ctx->memory, ctx->input, ctx->arena); - ctx->os->gl_swap_buffers(ctx->window); + try_wait_sync(sync, -1, os->wait_on_value); + vtgl_render_frame(os, ctx, ctx->memory, ctx->input, ctx->arena); + os->gl_swap_buffers(ctx->window); } return 0; } @@ -1280,7 +1279,7 @@ DEBUG_EXPORT VTGL_FRAME_STEP_FN(vtgl_frame_step) /* NOTE(rnp): we skip the resize this time through so that we don't add * input latency waiting for the render thread to release this lock */ if (atomic_exchange_n(&t->resize_lock, 1) == 0) { - resize_terminal(t, &memory->os, input->window_size); + resize_terminal(t, os, input->window_size); t->resize_lock = 0; } else { input->pending_updates = 1; @@ -1297,10 +1296,10 @@ DEBUG_EXPORT VTGL_FRAME_STEP_FN(vtgl_frame_step) t->scroll_offset = 0; t->state |= TS_NEEDS_REFILL; } - memory->os.write(t->child, input->character_input); + os->write(t->child, input->character_input); } - handle_interactions(t, input, &memory->os); + handle_interactions(t, input, os); END_NAMED_BLOCK(mouse_and_keyboard_input); if (t->state & TS_NEEDS_REFILL) { @@ -1313,7 +1312,7 @@ DEBUG_EXPORT VTGL_FRAME_STEP_FN(vtgl_frame_step) OSRingBuffer *rb = &t->views[t->view_idx].log; s8 buffer = {.len = rb->capacity - t->unprocessed_bytes, .data = rb->data + rb->write_index}; - iz bytes_read = memory->os.read(t->child, buffer); + iz bytes_read = os->read(t->child, buffer); ASSERT(bytes_read <= rb->capacity); commit_to_rb(t->views + t->view_idx, bytes_read); @@ -1335,7 +1334,7 @@ DEBUG_EXPORT VTGL_FRAME_STEP_FN(vtgl_frame_step) t->render_thread.gl.flags & DRAW_DEBUG_OVERLAY || !work_queue_empty(&t->render_thread.work_queue)) { - t->os->wake_waiters(t->render_thread.sync); + os->wake_waiters(t->render_thread.sync); } } diff --git a/vtgl.h b/vtgl.h @@ -305,21 +305,20 @@ typedef struct TerminalMemory { u64 debug_memory_size; void *debug_memory; - - OS os; } TerminalMemory; /************************************************************/ /* NOTE: functions provided by the terminal to the platform */ /************************************************************/ -#define VTGL_FRAME_STEP_FN(name) void name(TerminalMemory *memory, TerminalInput *input) +#define VTGL_FRAME_STEP_FN(name) void name(OS *os, TerminalMemory *memory, TerminalInput *input) typedef VTGL_FRAME_STEP_FN(vtgl_frame_step_fn); #define VTGL_ACTIVE_SELECTION_FN(name) Range name(TerminalMemory *memory, Stream *out) typedef VTGL_ACTIVE_SELECTION_FN(vtgl_active_selection_fn); -#define VTGL_HANDLE_KEYS_FN(name) void name(TerminalMemory *memory, TerminalInput *input, \ - KeyboardKey key, ButtonAction action, InputModifier modifiers) +#define VTGL_HANDLE_KEYS_FN(name) void name(OS *os, TerminalMemory *memory, TerminalInput *input, \ + KeyboardKey key, ButtonAction action, \ + InputModifier modifiers) typedef VTGL_HANDLE_KEYS_FN(vtgl_handle_keys_fn); typedef OS_THREAD_ENTRY_POINT_FN(vtgl_render_thread_entry_fn); diff --git a/vtgl_static.c b/vtgl_static.c @@ -15,21 +15,21 @@ function OS_FILE_WATCH_CALLBACK_FN(queue_shader_reload) } function iv2 -vtgl_initialize(TerminalMemory *memory, TerminalInput *input, void *window, iptr child, +vtgl_initialize(OS *os, TerminalMemory *memory, TerminalInput *input, void *window, iptr child, iv2 requested_cells, iv2 monitor_size) { Term *t = (Term *)memory->memory; Arena a = {.beg = (u8 *)(t + 1), .end = memory->memory + memory->memory_size}; - t->os = &memory->os; + t->os = os; t->cursor.state = CURSOR_NORMAL; t->cursor.style.fg = g_colours.data[g_colours.fgidx]; t->cursor.style.bg = g_colours.data[g_colours.bgidx]; - t->views[0].log = memory->os.allocate_ring_buffer(BACKLOG_SIZE); + t->views[0].log = os->allocate_ring_buffer(BACKLOG_SIZE); t->views[0].lines = line_buffer_alloc(&a, t->views[0].log.data, t->cursor.style, BACKLOG_LINES); - t->views[1].log = memory->os.allocate_ring_buffer(ALT_BACKLOG_SIZE); + t->views[1].log = os->allocate_ring_buffer(ALT_BACKLOG_SIZE); t->views[1].lines = line_buffer_alloc(&a, t->views[1].log.data, t->cursor.style, ALT_BACKLOG_LINES); t->views[0].fb.backing_store = memory_block_from_arena(&a, MB(2)); @@ -39,7 +39,6 @@ vtgl_initialize(TerminalMemory *memory, TerminalInput *input, void *window, iptr RenderThreadContext *rtc = &t->render_thread; rtc->arena = sub_arena(&a, MB(8)); - rtc->os = &memory->os; rtc->input = input; rtc->memory = memory; rtc->window = (iptr)window; @@ -62,7 +61,7 @@ vtgl_initialize(TerminalMemory *memory, TerminalInput *input, void *window, iptr src->label = s8(#en); \ src->path = s8(static_path_join(SHADER_PATH_PREFIX, sn ".glsl")); \ src->shader = SID_ ## en; \ - memory->os.add_file_watch(src->path.data, queue_shader_reload, src); \ + os->add_file_watch(src->path.data, queue_shader_reload, src); \ } while (0); FRAGMENT_SHADERS #undef X @@ -73,8 +72,8 @@ vtgl_initialize(TerminalMemory *memory, TerminalInput *input, void *window, iptr work_queue_push_commit(&rtc->work_queue); } - memory->os.gl_make_context_current(0); - rtc->sync = memory->os.spawn_thread(vtgl_render_thread_entry, "[render]", (iptr)rtc); + os->gl_make_context_current(0); + rtc->sync = os->spawn_thread(os, vtgl_render_thread_entry, "[render]", (iptr)rtc); t->size = (iv2){.x = 1, .y = 1}; t->state |= TS_NEEDS_RESIZE;