Commit: edc98a4478a6aa44b1916586cf1f30d5f30f081a
Parent: 974e3f2ae6f0c1b4489cf8176b028758730719db
Author: Randy Palamar
Date: Mon, 11 Nov 2024 21:47:33 -0700
remove runtime framebuffer allocations
We can just set off some space during initialization and use that
for resizing later. The chosen size of 2MB per framebuffer is
about 2 times the required size for a full 4K screen with 8 pixel
character height. In the unlikely case it is not big enough we
just clamp the number of visible rows.
Diffstat:
7 files changed, 57 insertions(+), 70 deletions(-)
diff --git a/os_unix.c b/os_unix.c
@@ -211,52 +211,6 @@ static PLATFORM_ALLOCATE_RING_BUFFER_FN(posix_allocate_ring_buffer)
}
static void
-os_alloc_framebuffer(Framebuffer *fb, u32 rows, u32 cols)
-{
- size pagesize = sysconf(_SC_PAGESIZE);
-
- size fb_needed_space = rows * cols * sizeof(Cell);
- if (fb->cells_alloc_size < fb_needed_space) {
- if (fb_needed_space % pagesize != 0)
- fb_needed_space += pagesize - fb_needed_space % pagesize;
-
- Cell *new = mmap(0, fb_needed_space, PROT_READ|PROT_WRITE,
- MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
- /* TODO: properly handle this case */
- ASSERT(new != MAP_FAILED);
-
- if (fb->cells)
- munmap(fb->cells, fb->cells_alloc_size);
-
- fb->cells = new;
- fb->cells_alloc_size = fb_needed_space;
- }
-
- size rows_needed_space = rows * sizeof(Row);
- if (fb->rows_alloc_size < rows_needed_space) {
- if (rows_needed_space % pagesize != 0)
- rows_needed_space += pagesize - rows_needed_space % pagesize;
-
- Row *new = mmap(0, rows_needed_space, PROT_READ|PROT_WRITE,
- MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
- /* TODO: properly handle this case */
- ASSERT(new != MAP_FAILED);
-
- if (fb->rows)
- munmap(fb->rows, fb->rows_alloc_size);
-
- fb->rows = new;
- fb->rows_alloc_size = rows_needed_space;
- }
-
- fb->cells_count = rows * cols;
- fb->rows_count = rows;
-
- for (u32 i = 0; i < fb->rows_count; i++)
- fb->rows[i] = fb->cells + i * cols;
-}
-
-static void
execsh(char *defcmd)
{
char *sh;
diff --git a/platform_linux_x11.c b/platform_linux_x11.c
@@ -376,19 +376,19 @@ i32
main(i32 argc, char *argv[], char *envp[])
{
{
- MemoryBlock terminal_memory = posix_alloc(16 * MEGABYTE);
+ MemoryBlock terminal_memory = posix_alloc(32 * MEGABYTE);
linux_ctx.memory.memory = terminal_memory.memory;
linux_ctx.memory.memory_size = terminal_memory.size;
#ifdef _DEBUG
- MemoryBlock debug_memory = posix_alloc(128 * MEGABYTE);
+ MemoryBlock debug_memory = posix_alloc(128 * MEGABYTE);
linux_ctx.memory.debug_memory = debug_memory.memory;
linux_ctx.memory.debug_memory_size = debug_memory.size;
#endif
}
+ linux_ctx.memory.platform_api.allocate_ring_buffer = posix_allocate_ring_buffer;
linux_ctx.memory.platform_api.read = posix_read;
linux_ctx.memory.platform_api.write = posix_write;
- linux_ctx.memory.platform_api.allocate_ring_buffer = posix_allocate_ring_buffer;
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.get_clipboard = x11_get_clipboard;
@@ -458,9 +458,8 @@ main(i32 argc, char *argv[], char *envp[])
GLFWmonitor *mon = glfwGetPrimaryMonitor();
if (!mon) {
glfwTerminate();
- os_fatal(s8("Failed to get GLFW monitor\n"));
+ os_fatal(s8("Failed to find any monitors!\n"));
}
-
iv2 monitor_size;
glfwGetMonitorWorkarea(mon, NULL, NULL, &monitor_size.w, &monitor_size.h);
diff --git a/terminal.c b/terminal.c
@@ -8,6 +8,27 @@ static const u8 utf8overhangmask[32] = {
#define SPLIT_LONG 4096L
+static uv2
+initialize_framebuffer(Framebuffer *fb, uv2 term_size)
+{
+ size cell_memory_size = sizeof(Cell) * term_size.h * term_size.w;
+ size rows_memory_size = sizeof(Row) * term_size.h;
+
+ /* NOTE: make sure cell memory size is a multiple of pointer size */
+ cell_memory_size += (sizeof(void *) - cell_memory_size % sizeof(void *));
+
+ if (cell_memory_size + rows_memory_size >= fb->backing_store.size)
+ term_size.h = (fb->backing_store.size - cell_memory_size) / sizeof(Row);
+
+ fb->cells = fb->backing_store.memory;
+ fb->rows = fb->backing_store.memory + cell_memory_size;
+
+ for (i32 i = 0; i < term_size.h; i++)
+ fb->rows[i] = fb->cells + i * term_size.w;
+
+ return term_size;
+}
+
static Range
get_word_around_cell(Term *t, iv2 cell)
{
diff --git a/test.c b/test.c
@@ -374,8 +374,10 @@ main(void)
/* TODO: should probably be some odd size */
term.size = (uv2){.w = 80, .h = 24};
- os_alloc_framebuffer(&term.views[0].fb, term.size.h, term.size.w);
- os_alloc_framebuffer(&term.views[1].fb, term.size.h, term.size.w);
+ term.views[0].fb.backing_store = memory_block_from_arena(&memory, 2 * MEGABYTE);
+ term.views[1].fb.backing_store = memory_block_from_arena(&memory, 2 * MEGABYTE);
+ initialize_framebuffer(&term.views[0].fb, term.size);
+ initialize_framebuffer(&term.views[1].fb, term.size);
u32 max_name_len = 0;
#define X(name) if (sizeof(#name) - 1 > max_name_len) max_name_len = sizeof(#name) - 1;
diff --git a/util.c b/util.c
@@ -97,15 +97,6 @@ mem_clear(void *p_, u8 c, size len)
return p;
}
-static Arena
-arena_from_memory_block(MemoryBlock memory)
-{
- Arena result;
- result.beg = memory.memory;
- result.end = memory.memory + memory.size;
- return result;
-}
-
#define alloc(a, t, n) (t *)alloc_(a, sizeof(t), _Alignof(t), n)
static void *
alloc_(Arena *a, size len, size align, size count)
@@ -122,6 +113,24 @@ alloc_(Arena *a, size len, size align, size count)
}
static Arena
+arena_from_memory_block(MemoryBlock memory)
+{
+ Arena result;
+ result.beg = memory.memory;
+ result.end = memory.memory + memory.size;
+ return result;
+}
+
+static MemoryBlock
+memory_block_from_arena(Arena *a, size requested_size)
+{
+ MemoryBlock result;
+ result.memory = alloc_(a, requested_size, 64, 1);
+ result.size = requested_size;
+ return result;
+}
+
+static Arena
sub_arena(Arena *a, size size)
{
Arena result = {0};
diff --git a/util.h b/util.h
@@ -172,12 +172,8 @@ typedef Cell *Row;
typedef struct {
Cell *cells;
- size cells_count;
- size cells_alloc_size;
-
Row *rows;
- size rows_count;
- size rows_alloc_size;
+ MemoryBlock backing_store;
} Framebuffer;
/* NOTE: virtual memory ring buffer */
diff --git a/vtgl.c b/vtgl.c
@@ -275,8 +275,8 @@ resize(Term *t, iv2 window_size)
}
if (!equal_uv2(old_size, t->size)) {
- os_alloc_framebuffer(&t->views[0].fb, t->size.h, t->size.w);
- os_alloc_framebuffer(&t->views[1].fb, t->size.h, t->size.w);
+ t->size = initialize_framebuffer(&t->views[0].fb, t->size);
+ initialize_framebuffer(&t->views[1].fb, t->size);
gl->flags |= NEEDS_FULL_REFILL;
u32 buffer_size = t->size.w * t->size.h * sizeof(RenderCell);
@@ -961,6 +961,9 @@ DEBUG_EXPORT VTGL_INITIALIZE_FN(vtgl_initialize)
memory->platform_api.allocate_ring_buffer(&t->views[1].log, ALT_BACKLOG_SIZE);
line_buf_alloc(&t->views[1].lines, &a, t->views[1].log.buf, t->cursor.style, ALT_BACKLOG_LINES);
+ t->views[0].fb.backing_store = memory_block_from_arena(&a, 2 * MEGABYTE);
+ t->views[1].fb.backing_store = memory_block_from_arena(&a, 2 * MEGABYTE);
+
t->gl.glyph_bitmap_dim = monitor_size;
init_fonts(&t->fa, &a, t->gl.glyph_bitmap_dim);
selection_clear(&t->selection);
@@ -970,6 +973,10 @@ DEBUG_EXPORT VTGL_INITIALIZE_FN(vtgl_initialize)
.y = cs.y * requested_cells.y + 2 * g_term_margin.y,
};
+ t->size = (uv2){.x = 1, .y = 1};
+ initialize_framebuffer(&t->views[0].fb, t->size);
+ initialize_framebuffer(&t->views[1].fb, t->size);
+
shader_reload_ctx *shader_ctxs = alloc(&a, shader_reload_ctx, SHADER_COUNT);
s8 shader_infos[SHADER_COUNT] = {
@@ -994,7 +1001,6 @@ DEBUG_EXPORT VTGL_INITIALIZE_FN(vtgl_initialize)
a.beg = path.buf + path.widx;
}
- t->size = (uv2){.x = 1, .y = 1};
t->error_stream = stream_alloc(&a, MEGABYTE / 4);
t->saved_title = stream_alloc(&a, 16 * KILOBYTE);
t->arena_for_frame = a;