vtgl

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

Commit: 516e168e738276ff2ab6dcba7472f7a6247b594a
Parent: 477fc2e932cd6ad0f0cc26b8af380ebd1120c52a
Author: Randy Palamar
Date:   Fri, 29 Nov 2024 06:54:07 -0700

remove stat.h include

Diffstat:
Mos_unix.c | 52+++++++++++++++++++---------------------------------
Mplatform_linux_amd64.c | 9++++-----
Mplatform_linux_common.c | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mplatform_linux_x11.c | 86+++----------------------------------------------------------------------------
Mutil.h | 3---
Mvtgl.c | 11+++--------
Mvtgl.h | 11+----------
7 files changed, 113 insertions(+), 142 deletions(-)

diff --git a/os_unix.c b/os_unix.c @@ -4,16 +4,10 @@ #include <pwd.h> #include <sys/mman.h> #include <sys/select.h> -#include <sys/stat.h> #include <sys/wait.h> #include <time.h> #include <unistd.h> -typedef struct { - iptr handle; - iptr process_id; -} posix_platform_process; - #define OS_MAP_READ PROT_READ #define OS_MAP_PRIVATE MAP_PRIVATE @@ -26,17 +20,6 @@ os_get_time(void) return result; } -static PLATFORM_GET_FILESTATS_FN(posix_get_file_stats) -{ - struct stat sb = {0}; - FileStats result = {0}; - if (stat((c8 *)path, &sb) == 0) { - result.size = sb.st_size; - result.timestamp = sb.st_mtim.tv_sec * 1e9 + sb.st_mtim.tv_nsec; - } - return result; -} - static u32 os_file_attribute_to_mode(u32 attr) { @@ -94,19 +77,21 @@ static PLATFORM_READ_FN(posix_read) static PLATFORM_READ_FILE_FN(posix_read_file) { - i32 fd = open((c8 *)path, O_RDONLY); - buffer->errors |= fd < 0; + s8 result = {0}; - if (!buffer->errors) { - s8 text = {.len = buffer->cap - buffer->widx, .data = buffer->buf + buffer->widx}; - size rlen = posix_read(fd, text, 0); + stat_buffer sb; + i64 status = syscall2(SYS_stat, (iptr)path, (iptr)sb); + i32 fd = open((c8 *)path, O_RDONLY); + + if (fd > 0 && status == 0) { + result = s8alloc(a, STAT_FILE_SIZE(sb)); + size rlen = posix_read(fd, result, 0); close(fd); - buffer->errors |= text.len != rlen; - if (!buffer->errors) - buffer->widx += rlen; + if (result.len != rlen) + result.len = 0; } - return !buffer->errors; + return result; } static os_mapped_file @@ -120,13 +105,14 @@ os_map_file(char *path, i32 mode, i32 perm) default: ASSERT(0); } - i32 fd = open(path, open_mode); - FileStats fs = posix_get_file_stats((u8 *)path); + stat_buffer sb; + i64 status = syscall2(SYS_stat, (iptr)path, (iptr)sb); + i32 fd = open(path, open_mode); - if (fd != -1) { - res.data = mmap(NULL, fs.size, mode, perm, fd, 0); + if (fd != -1 && status == 0) { + res.data = mmap(NULL, STAT_FILE_SIZE(sb), mode, perm, fd, 0); if (res.data != MAP_FAILED) - res.len = fs.size; + res.len = STAT_FILE_SIZE(sb); close(fd); } @@ -199,7 +185,7 @@ execsh(char *defcmd) _exit(1); } -static posix_platform_process +static linux_platform_process os_fork_child(char *cmd) { i32 cfd; @@ -222,7 +208,7 @@ os_fork_child(char *cmd) if (fcntl(cfd, F_SETFL, flags | O_NONBLOCK) == -1) os_fatal(s8("os_fork_child: fcntl: F_SETFL\n")); - return (posix_platform_process){.process_id = pid, .handle = cfd}; + return (linux_platform_process){.process_id = pid, .handle = cfd}; } static b32 diff --git a/platform_linux_amd64.c b/platform_linux_amd64.c @@ -22,16 +22,15 @@ #define PAGE_SIZE 4096 -#define STAT_BUF_SIZE 144 -#define STAT_SIZE_OFF 48 +typedef __attribute__((aligned(16))) u8 stat_buffer[144]; +#define STAT_BUF_MEMBER(sb, t, off) (*(t *)((u8 *)(sb) + off)) +#define STAT_INODE(sb) STAT_BUF_MEMBER(sb, i64, 8) +#define STAT_FILE_SIZE(sb) STAT_BUF_MEMBER(sb, i64, 48) #define DIRENT_RECLEN_OFF 16 #define DIRENT_TYPE_OFF 18 #define DIRENT_NAME_OFF 19 -typedef signed long i64; -typedef unsigned long u64; - static i64 syscall1(i64 n, i64 a1) { diff --git a/platform_linux_common.c b/platform_linux_common.c @@ -30,6 +30,35 @@ typedef struct { i32 handle; } linux_file_watch; +typedef struct { + iptr handle; + iptr process_id; +} linux_platform_process; + +typedef struct { + Arena platform_memory; + void *window; + + TerminalMemory memory; + TerminalInput input; + + Stream char_stream; + + linux_platform_process child; + i32 inotify_fd; + i32 win_fd; + + linux_file_watch file_watches[32]; + i32 file_watch_count; + + Stream error_stream; + +#ifdef _DEBUG + void *library_handle; +#endif +} PlatformCtx; +static PlatformCtx linux_ctx; + #include <sys/inotify.h> #define LINUX_INOTIFY_MASK (IN_CLOSE|IN_MODIFY) @@ -97,4 +126,58 @@ usage(char *argv0, Stream *err) os_fatal(stream_to_s8(err)); } +static PLATFORM_ADD_FILE_WATCH_FN(linux_add_file_watch) +{ + stat_buffer sb; + syscall2(SYS_stat, (iptr)path, (iptr)sb); + + i32 wd = inotify_add_watch(linux_ctx.inotify_fd, (c8 *)path, LINUX_INOTIFY_MASK); + i32 idx = linux_ctx.file_watch_count++; + ASSERT(idx < ARRAY_COUNT(linux_ctx.file_watches)); + + linux_ctx.file_watches[idx].fn = fn; + linux_ctx.file_watches[idx].path = path; + linux_ctx.file_watches[idx].handle = wd; + linux_ctx.file_watches[idx].inode = STAT_INODE(sb); + linux_ctx.file_watches[idx].user_ctx = user_ctx; +} + +static void +dispatch_file_watch_events(PlatformCtx *ctx) +{ + u8 *mem = alloc_(&ctx->platform_memory, 4096, 64, 1); + s8 buf = {.len = 4096, .data = mem}; + for (;;) { + size rlen = syscall3(SYS_read, ctx->inotify_fd, (iptr)buf.data, buf.len); + if (rlen <= 0) + break; + struct inotify_event *ie; + for (u8 *data = buf.data; data < buf.data + rlen; data += sizeof(*ie) + ie->len) { + ie = (struct inotify_event *)data; + for (i32 i = 0; i < ctx->file_watch_count; i++) { + linux_file_watch *fw = ctx->file_watches + i; + if (fw->handle == ie->wd) { + b32 file_changed = (ie->mask & IN_CLOSE_WRITE) != 0; + file_changed |= (ie->mask & IN_MODIFY) != 0; + /* NOTE: some editors and the compiler will rewrite a file + * completely and thus the inode will change; here we + * detect that and restart the watch */ + stat_buffer sb; + syscall2(SYS_stat, (iptr)fw->path, (iptr)sb); + if (fw->inode != STAT_INODE(sb)) { + inotify_rm_watch(ctx->inotify_fd, fw->handle); + fw->inode = STAT_INODE(sb); + fw->handle = inotify_add_watch(ctx->inotify_fd, + (c8 *)fw->path, + LINUX_INOTIFY_MASK); + file_changed = 1; + } + if (file_changed) + fw->fn(fw->path, fw->user_ctx); + } + } + } + } +} + #include "os_unix.c" diff --git a/platform_linux_x11.c b/platform_linux_x11.c @@ -17,31 +17,6 @@ typedef void *Window; i32 XConnectionNumber(void *display); i32 XPending(void *display); -typedef struct { - Arena platform_memory; - void *window; - - TerminalMemory memory; - TerminalInput input; - - Stream char_stream; - - posix_platform_process child; - i32 inotify_fd; - i32 x_fd; - - linux_file_watch file_watches[32]; - i32 file_watch_count; - - Stream error_stream; - -#ifdef _DEBUG - void *library_handle; -#endif -} PlatformCtx; - -static PlatformCtx linux_ctx; - #ifndef _DEBUG #define do_debug(...) #include "vtgl.c" @@ -260,50 +235,12 @@ init_window(PlatformCtx *ctx, iv2 window_size) glfwSetWindowFocusCallback(window, focus_callback); glfwSetWindowRefreshCallback(window, refresh_callback); - ctx->x_fd = XConnectionNumber(glfwGetX11Display()); + ctx->win_fd = XConnectionNumber(glfwGetX11Display()); return window; } static void -dispatch_file_watch_events(PlatformCtx *ctx) -{ - u8 *mem = alloc_(&ctx->platform_memory, 4096, 64, 1); - s8 buf = {.len = 4096, .data = mem}; - for (;;) { - size rlen = read(ctx->inotify_fd, buf.data, buf.len); - if (rlen <= 0) - break; - struct inotify_event *ie; - for (u8 *data = buf.data; data < buf.data + rlen; data += sizeof(*ie) + ie->len) { - ie = (struct inotify_event *)data; - for (i32 i = 0; i < ctx->file_watch_count; i++) { - linux_file_watch *fw = ctx->file_watches + i; - if (fw->handle == ie->wd) { - b32 file_changed = (ie->mask & IN_CLOSE_WRITE) != 0; - file_changed |= (ie->mask & IN_MODIFY) != 0; - /* NOTE: some editors and the compiler will rewrite a file - * completely and thus the inode will change; here we - * detect that and restart the watch */ - struct stat sb; - stat((c8 *)fw->path, &sb); - if (fw->inode != sb.st_ino) { - inotify_rm_watch(ctx->inotify_fd, fw->handle); - fw->inode = sb.st_ino; - fw->handle = inotify_add_watch(ctx->inotify_fd, - (c8 *)fw->path, - LINUX_INOTIFY_MASK); - file_changed = 1; - } - if (file_changed) - fw->fn(fw->path, fw->user_ctx); - } - } - } - } -} - -static void update_input(PlatformCtx *ctx) { TerminalInput *input = &ctx->input; @@ -330,10 +267,10 @@ update_input(PlatformCtx *ctx) FD_ZERO(&rfd); FD_SET(ctx->child.handle, &rfd); FD_SET(ctx->inotify_fd, &rfd); - FD_SET(ctx->x_fd, &rfd); + FD_SET(ctx->win_fd, &rfd); i32 max_fd = MAX(ctx->inotify_fd, ctx->child.handle); - max_fd = MAX(max_fd, ctx->x_fd); + max_fd = MAX(max_fd, ctx->win_fd); pselect(max_fd + 1, &rfd, NULL, NULL, &timeout, NULL); input->data_available = FD_ISSET(ctx->child.handle, &rfd) != 0; @@ -395,22 +332,6 @@ static PLATFORM_WINDOW_TITLE_FN(x11_set_window_title) glfwSetWindowTitle(linux_ctx.window, (c8 *)buffer->buf); } -static PLATFORM_ADD_FILE_WATCH_FN(linux_add_file_watch) -{ - struct stat sb; - stat((c8 *)path, &sb); - - i32 wd = inotify_add_watch(linux_ctx.inotify_fd, (c8 *)path, LINUX_INOTIFY_MASK); - i32 idx = linux_ctx.file_watch_count++; - ASSERT(idx < ARRAY_COUNT(linux_ctx.file_watches)); - - linux_ctx.file_watches[idx].fn = fn; - linux_ctx.file_watches[idx].path = path; - linux_ctx.file_watches[idx].handle = wd; - linux_ctx.file_watches[idx].inode = sb.st_ino; - linux_ctx.file_watches[idx].user_ctx = user_ctx; -} - static void linux_render_thread_entry(struct stack_base *stack) { @@ -508,7 +429,6 @@ main(i32 argc, char *argv[], char *envp[]) linux_ctx.memory.platform_api.allocate_ring_buffer = posix_allocate_ring_buffer; linux_ctx.memory.platform_api.get_clipboard = x11_get_clipboard; linux_ctx.memory.platform_api.set_clipboard = x11_set_clipboard; - linux_ctx.memory.platform_api.get_file_stats = posix_get_file_stats; linux_ctx.memory.platform_api.read_file = posix_read_file; linux_ctx.memory.platform_api.read = posix_read; linux_ctx.memory.platform_api.set_terminal_size = posix_set_terminal_size; diff --git a/util.h b/util.h @@ -212,9 +212,6 @@ typedef struct { struct { GL_POST_UNIFORMS } post; #undef X - /* TODO: os file watcher */ - FileStats fs_stats[SHADER_COUNT], vs_stats[SHADER_COUNT]; - _Alignas(16) ShaderParameters shader_parameters; u32 render_shader_ubo; u32 render_shader_ssbo; diff --git a/vtgl.c b/vtgl.c @@ -117,14 +117,9 @@ static PLATFORM_FILE_WATCH_CALLBACK_FN(reload_shader) Arena a = t->arena_for_frame; Stream *err = &t->error_stream; - b32 success = 1; - - FileStats fs_stats = platform->get_file_stats(path); - Stream fs_text = stream_alloc(&a, fs_stats.size); - success &= platform->read_file(path, &fs_text, fs_stats.size); - - if (success) { - u32 program = program_from_shader_text(s8(VERTEX_SHADER_TEXT), stream_to_s8(&fs_text), a); + s8 fs_text = platform->read_file(path, &a); + if (fs_text.len) { + u32 program = program_from_shader_text(s8(VERTEX_SHADER_TEXT), fs_text, a); if (program) { glDeleteProgram(t->gl.programs[ctx->stage]); t->gl.programs[ctx->stage] = program; diff --git a/vtgl.h b/vtgl.h @@ -94,11 +94,6 @@ typedef struct { b32 errors; } Stream; -typedef struct { - size size; - u64 timestamp; -} FileStats; - /* NOTE: virtual memory ring buffer */ typedef struct { size cap; @@ -143,10 +138,7 @@ typedef PLATFORM_ALLOCATE_RING_BUFFER_FN(platform_allocate_ring_buffer_fn); #define PLATFORM_CLIPBOARD_FN(name) b32 name(Stream *buffer, u32 clipboard) typedef PLATFORM_CLIPBOARD_FN(platform_clipboard_fn); -#define PLATFORM_GET_FILESTATS_FN(name) FileStats name(u8 *path) -typedef PLATFORM_GET_FILESTATS_FN(platform_get_file_stats_fn); - -#define PLATFORM_READ_FILE_FN(name) b32 name(u8 *path, Stream *buffer, size file_size) +#define PLATFORM_READ_FILE_FN(name) s8 name(u8 *path, Arena *a) typedef PLATFORM_READ_FILE_FN(platform_read_file_fn); /* TODO: this should possibly just take a stream buffer */ @@ -168,7 +160,6 @@ typedef struct { platform_allocate_ring_buffer_fn *allocate_ring_buffer; platform_clipboard_fn *get_clipboard; platform_clipboard_fn *set_clipboard; - platform_get_file_stats_fn *get_file_stats; platform_read_file_fn *read_file; platform_read_fn *read; platform_set_terminal_size_fn *set_terminal_size;