ce21fd10
Honor wl_output buffer scale in terminal render loop
a73x 2026-04-09 13:24
Commit message
src/main.zig
| Old | New | ||
|---|---|---|---|
| @@ -102,9 +102,19 @@ fn runTerminal(alloc: std.mem.Allocator) !void { | |||
| 102 | var face = try font.Face.init(alloc, font_lookup.path, font_lookup.index, font_size); | 102 | var face = try font.Face.init(alloc, font_lookup.path, font_lookup.index, font_size); |
| 103 | defer face.deinit(); | 103 | defer face.deinit(); |
| 104 | 104 | ||
| 105 | const cell_w = face.cellWidth(); | 105 | var geom: ScaledGeometry = .{ |
| 106 | const cell_h = face.cellHeight(); | 106 | .buffer_scale = 1, |
| 107 | const baseline = face.baseline(); | 107 | .px_size = font_size, |
| 108 | .cell_w_px = face.cellWidth(), | ||
| 109 | .cell_h_px = face.cellHeight(), | ||
| 110 | .baseline_px = face.baseline(), | ||
| 111 | }; | ||
| 112 | // Mutable aliases so the scale-change path inside the main loop can | ||
| 113 | // refresh them after a rebuildFaceForScale call without renaming every | ||
| 114 | // downstream reference. | ||
| 115 | var cell_w = geom.cell_w_px; | ||
| 116 | var cell_h = geom.cell_h_px; | ||
| 117 | var baseline = geom.baseline_px; | ||
| 108 | 118 | ||
| 109 | // === grid size === | 119 | // === grid size === |
| 110 | const initial_grid: GridSize = .{ .cols = 80, .rows = 24 }; | 120 | const initial_grid: GridSize = .{ .cols = 80, .rows = 24 }; |
| @@ -196,6 +206,7 @@ fn runTerminal(alloc: std.mem.Allocator) !void { | |||
| 196 | var key_buf: [32]u8 = undefined; | 206 | var key_buf: [32]u8 = undefined; |
| 197 | var last_window_w = window.width; | 207 | var last_window_w = window.width; |
| 198 | var last_window_h = window.height; | 208 | var last_window_h = window.height; |
| 209 | var last_scale: i32 = geom.buffer_scale; | ||
| 199 | var render_pending = true; | 210 | var render_pending = true; |
| 200 | 211 | ||
| 201 | while (!window.should_close and p.isChildAlive()) { | 212 | while (!window.should_close and p.isChildAlive()) { |
| @@ -252,11 +263,48 @@ fn runTerminal(alloc: std.mem.Allocator) !void { | |||
| 252 | } | 263 | } |
| 253 | keyboard.event_queue.clearRetainingCapacity(); | 264 | keyboard.event_queue.clearRetainingCapacity(); |
| 254 | 265 | ||
| 266 | const current_scale = window.bufferScale(); | ||
| 267 | if (current_scale != last_scale) { | ||
| 268 | _ = try ctx.vkd.deviceWaitIdle(ctx.device); | ||
| 269 | |||
| 270 | geom = try rebuildFaceForScale( | ||
| 271 | &face, | ||
| 272 | &atlas, | ||
| 273 | font_lookup.path, | ||
| 274 | font_lookup.index, | ||
| 275 | font_size, | ||
| 276 | current_scale, | ||
| 277 | ); | ||
| 278 | cell_w = geom.cell_w_px; | ||
| 279 | cell_h = geom.cell_h_px; | ||
| 280 | baseline = geom.baseline_px; | ||
| 281 | |||
| 282 | // Wipe all cached row instances + mark the terminal fully dirty so that | ||
| 283 | // every glyph gets re-inserted into the freshly reset atlas next frame. | ||
| 284 | render_cache.invalidateAfterResize(); | ||
| 285 | term.render_state.dirty = .full; | ||
| 286 | |||
| 287 | window.surface.setBufferScale(geom.buffer_scale); | ||
| 288 | |||
| 289 | const buf_w = window.width * @as(u32, @intCast(geom.buffer_scale)); | ||
| 290 | const buf_h = window.height * @as(u32, @intCast(geom.buffer_scale)); | ||
| 291 | try ctx.recreateSwapchain(buf_w, buf_h); | ||
| 292 | |||
| 293 | last_scale = current_scale; | ||
| 294 | render_pending = true; | ||
| 295 | } | ||
| 296 | |||
| 255 | if (window.width != last_window_w or window.height != last_window_h) { | 297 | if (window.width != last_window_w or window.height != last_window_h) { |
| 256 | const new_grid = gridSizeForWindow(window.width, window.height, cell_w, cell_h); | 298 | // Grid is sized in surface coordinates. cell_w/cell_h are in buffer |
| 299 | // pixels, so divide by buffer_scale to get surface-pixel cell dims. | ||
| 300 | const surf_cell_w = cell_w / @as(u32, @intCast(geom.buffer_scale)); | ||
| 301 | const surf_cell_h = cell_h / @as(u32, @intCast(geom.buffer_scale)); | ||
| 302 | const new_grid = gridSizeForWindow(window.width, window.height, surf_cell_w, surf_cell_h); | ||
| 303 | const buf_w = window.width * @as(u32, @intCast(geom.buffer_scale)); | ||
| 304 | const buf_h = window.height * @as(u32, @intCast(geom.buffer_scale)); | ||
| 257 | if (new_grid.cols != cols or new_grid.rows != rows) { | 305 | if (new_grid.cols != cols or new_grid.rows != rows) { |
| 258 | _ = try ctx.vkd.deviceWaitIdle(ctx.device); | 306 | _ = try ctx.vkd.deviceWaitIdle(ctx.device); |
| 259 | try ctx.recreateSwapchain(window.width, window.height); | 307 | try ctx.recreateSwapchain(buf_w, buf_h); |
| 260 | try term.resize(new_grid.cols, new_grid.rows); | 308 | try term.resize(new_grid.cols, new_grid.rows); |
| 261 | try p.resize(new_grid.cols, new_grid.rows); | 309 | try p.resize(new_grid.cols, new_grid.rows); |
| 262 | cols = new_grid.cols; | 310 | cols = new_grid.cols; |
| @@ -269,7 +317,7 @@ fn runTerminal(alloc: std.mem.Allocator) !void { | |||
| 269 | }); | 317 | }); |
| 270 | } else { | 318 | } else { |
| 271 | _ = try ctx.vkd.deviceWaitIdle(ctx.device); | 319 | _ = try ctx.vkd.deviceWaitIdle(ctx.device); |
| 272 | try ctx.recreateSwapchain(window.width, window.height); | 320 | try ctx.recreateSwapchain(buf_w, buf_h); |
| 273 | } | 321 | } |
| 274 | last_window_w = window.width; | 322 | last_window_w = window.width; |
| 275 | last_window_h = window.height; | 323 | last_window_h = window.height; |
| @@ -445,7 +493,9 @@ fn runTerminal(alloc: std.mem.Allocator) !void { | |||
| 445 | ) catch |err| switch (err) { | 493 | ) catch |err| switch (err) { |
| 446 | error.OutOfDateKHR => { | 494 | error.OutOfDateKHR => { |
| 447 | _ = try ctx.vkd.deviceWaitIdle(ctx.device); | 495 | _ = try ctx.vkd.deviceWaitIdle(ctx.device); |
| 448 | try ctx.recreateSwapchain(window.width, window.height); | 496 | const buf_w = window.width * @as(u32, @intCast(geom.buffer_scale)); |
| 497 | const buf_h = window.height * @as(u32, @intCast(geom.buffer_scale)); | ||
| 498 | try ctx.recreateSwapchain(buf_w, buf_h); | ||
| 449 | render_pending = true; | 499 | render_pending = true; |
| 450 | continue; | 500 | continue; |
| 451 | }, | 501 | }, |