diff --git a/src/Surface.zig b/src/Surface.zig index 7710f387b..732b8565b 100644 --- a/src/Surface.zig +++ b/src/Surface.zig @@ -397,20 +397,6 @@ pub fn init( .right = padding_right, }; - // Create our terminal grid with the initial size - const app_mailbox: App.Mailbox = .{ .rt_app = rt_app, .mailbox = &app.mailbox }; - var renderer_impl = try Renderer.init(alloc, .{ - .config = try Renderer.DerivedConfig.init(alloc, config), - .font_grid = font_grid, - .padding = .{ - .explicit = padding, - .balance = config.@"window-padding-balance", - }, - .surface_mailbox = .{ .surface = self, .app = app_mailbox }, - .rt_surface = rt_surface, - }); - errdefer renderer_impl.deinit(); - // Build our size struct which has all the sizes we need. const size: renderer.Size = size: { var size: renderer.Size = .{ @@ -433,6 +419,17 @@ pub fn init( break :size size; }; + // Create our terminal grid with the initial size + const app_mailbox: App.Mailbox = .{ .rt_app = rt_app, .mailbox = &app.mailbox }; + var renderer_impl = try Renderer.init(alloc, .{ + .config = try Renderer.DerivedConfig.init(alloc, config), + .font_grid = font_grid, + .size = size, + .surface_mailbox = .{ .surface = self, .app = app_mailbox }, + .rt_surface = rt_surface, + }); + errdefer renderer_impl.deinit(); + // The mutex used to protect our renderer state. const mutex = try alloc.create(std.Thread.Mutex); mutex.* = .{}; diff --git a/src/renderer/Metal.zig b/src/renderer/Metal.zig index 742dfbcd4..aebbc5c39 100644 --- a/src/renderer/Metal.zig +++ b/src/renderer/Metal.zig @@ -70,12 +70,8 @@ surface_mailbox: apprt.surface.Mailbox, /// Current font metrics defining our grid. grid_metrics: font.face.Metrics, -/// Current screen size dimensions for this grid. This is set on the first -/// resize event, and is not immediately available. -screen_size: ?renderer.ScreenSize, - -/// Explicit padding. -padding: renderer.Options.Padding, +/// The size of everything. +size: renderer.Size, /// True if the window is focused focused: bool, @@ -631,8 +627,7 @@ pub fn init(alloc: Allocator, options: renderer.Options) !Metal { .config = options.config, .surface_mailbox = options.surface_mailbox, .grid_metrics = font_critical.metrics, - .screen_size = null, - .padding = options.padding, + .size = options.size, .focused = true, .foreground_color = options.config.foreground, .background_color = options.config.background, @@ -796,19 +791,6 @@ pub fn hasVsync(self: *const Metal) bool { return display_link.isRunning(); } -/// Returns the grid size for a given screen size. This is safe to call -/// on any thread. -fn gridSize(self: *Metal) ?renderer.GridSize { - const screen_size = self.screen_size orelse return null; - return renderer.GridSize.init( - screen_size.subPadding(self.padding.explicit), - .{ - .width = self.grid_metrics.cell_width, - .height = self.grid_metrics.cell_height, - }, - ); -} - /// Callback when the focus changes for the terminal this is rendering. /// /// Must be called on the render thread. @@ -878,15 +860,13 @@ pub fn setFontGrid(self: *Metal, grid: *font.SharedGrid) void { // // If the screen size isn't set, it will be eventually so that'll call // the setScreenSize automatically. - if (self.screen_size) |size| { - self.setScreenSize(size, self.padding.explicit) catch |err| { - // The setFontGrid function can't fail but resizing our cell - // buffer definitely can fail. If it does, our renderer is probably - // screwed but let's just log it and continue until we can figure - // out a better way to handle this. - log.err("error resizing cells buffer err={}", .{err}); - }; - } + self.setScreenSize(self.size) catch |err| { + // The setFontGrid function can't fail but resizing our cell + // buffer definitely can fail. If it does, our renderer is probably + // screwed but let's just log it and continue until we can figure + // out a better way to handle this. + log.err("error resizing cells buffer err={}", .{err}); + }; } /// Update the frame data. @@ -898,9 +878,6 @@ pub fn updateFrame( ) !void { _ = surface; - // If we don't have a screen size yet then we can't render anything. - if (self.screen_size == null) return; - // Data we extract out of the critical area. const Critical = struct { bg: terminal.color.RGB, @@ -1116,9 +1093,6 @@ pub fn updateFrame( pub fn drawFrame(self: *Metal, surface: *apprt.Surface) !void { _ = surface; - // If we don't have a screen size yet then we can't render anything. - if (self.screen_size == null) return; - // If we have no cells rebuilt we can usually skip drawing since there // is no changed data. However, if we have active animations we still // need to draw so that we can update the time uniform and render the @@ -1972,38 +1946,19 @@ pub fn changeConfig(self: *Metal, config: *DerivedConfig) !void { /// Resize the screen. pub fn setScreenSize( self: *Metal, - dim: renderer.ScreenSize, - pad: renderer.Padding, + size: renderer.Size, ) !void { // Store our sizes - self.screen_size = dim; - self.padding.explicit = pad; - - // Recalculate the rows/columns. This can't fail since we just set - // the screen size above. - const grid_size = self.gridSize().?; - - // Determine if we need to pad the window. For "auto" padding, we take - // the leftover amounts on the right/bottom that don't fit a full grid cell - // and we split them equal across all boundaries. - const padding = if (self.padding.balance) - renderer.Padding.balanced( - dim, - grid_size, - .{ - .width = self.grid_metrics.cell_width, - .height = self.grid_metrics.cell_height, - }, - ) - else - self.padding.explicit; - const padded_dim = dim.subPadding(padding); + self.size = size; + const grid_size = size.grid(); + const terminal_size = size.terminal(); // Blank space around the grid. - const blank: renderer.Padding = dim.blankPadding(padding, grid_size, .{ - .width = self.grid_metrics.cell_width, - .height = self.grid_metrics.cell_height, - }).add(padding); + const blank: renderer.Padding = size.screen.blankPadding( + size.padding, + grid_size, + size.cell, + ).add(size.padding); var padding_extend = self.uniforms.padding_extend; switch (self.config.padding_color) { @@ -2030,18 +1985,18 @@ pub fn setScreenSize( // Set the size of the drawable surface to the bounds self.layer.setProperty("drawableSize", macos.graphics.Size{ - .width = @floatFromInt(dim.width), - .height = @floatFromInt(dim.height), + .width = @floatFromInt(size.screen.width), + .height = @floatFromInt(size.screen.height), }); // Setup our uniforms const old = self.uniforms; self.uniforms = .{ .projection_matrix = math.ortho2d( - -1 * @as(f32, @floatFromInt(padding.left)), - @floatFromInt(padded_dim.width + padding.right), - @floatFromInt(padded_dim.height + padding.bottom), - -1 * @as(f32, @floatFromInt(padding.top)), + -1 * @as(f32, @floatFromInt(size.padding.left)), + @floatFromInt(terminal_size.width + size.padding.right), + @floatFromInt(terminal_size.height + size.padding.bottom), + -1 * @as(f32, @floatFromInt(size.padding.top)), ), .cell_size = .{ @floatFromInt(self.grid_metrics.cell_width), @@ -2082,8 +2037,8 @@ pub fn setScreenSize( } state.uniforms.resolution = .{ - @floatFromInt(dim.width), - @floatFromInt(dim.height), + @floatFromInt(size.screen.width), + @floatFromInt(size.screen.height), 1, }; @@ -2097,8 +2052,8 @@ pub fn setScreenSize( break :init id_init; }; desc.setProperty("pixelFormat", @intFromEnum(mtl.MTLPixelFormat.bgra8unorm)); - desc.setProperty("width", @as(c_ulong, @intCast(dim.width))); - desc.setProperty("height", @as(c_ulong, @intCast(dim.height))); + desc.setProperty("width", @as(c_ulong, @intCast(size.screen.width))); + desc.setProperty("height", @as(c_ulong, @intCast(size.screen.height))); desc.setProperty( "usage", @intFromEnum(mtl.MTLTextureUsage.render_target) | @@ -2127,8 +2082,8 @@ pub fn setScreenSize( break :init id_init; }; desc.setProperty("pixelFormat", @intFromEnum(mtl.MTLPixelFormat.bgra8unorm)); - desc.setProperty("width", @as(c_ulong, @intCast(dim.width))); - desc.setProperty("height", @as(c_ulong, @intCast(dim.height))); + desc.setProperty("width", @as(c_ulong, @intCast(size.screen.width))); + desc.setProperty("height", @as(c_ulong, @intCast(size.screen.height))); desc.setProperty( "usage", @intFromEnum(mtl.MTLTextureUsage.render_target) | @@ -2148,7 +2103,7 @@ pub fn setScreenSize( }; } - log.debug("screen size screen={} grid={}, cell_width={} cell_height={}", .{ dim, grid_size, self.grid_metrics.cell_width, self.grid_metrics.cell_height }); + log.debug("screen size size={}", .{size}); } /// Convert the terminal state to GPU cells stored in CPU memory. These diff --git a/src/renderer/Options.zig b/src/renderer/Options.zig index 8c68affe8..d1f0f7996 100644 --- a/src/renderer/Options.zig +++ b/src/renderer/Options.zig @@ -11,8 +11,8 @@ config: renderer.Renderer.DerivedConfig, /// The font grid that should be used along with the key for deref-ing. font_grid: *font.SharedGrid, -/// Padding options for the viewport. -padding: Padding, +/// The size of everything. +size: renderer.Size, /// The mailbox for sending the surface messages. This is only valid /// once the thread has started and should not be used outside of the thread. diff --git a/src/renderer/Thread.zig b/src/renderer/Thread.zig index 8c4be3c60..91e355480 100644 --- a/src/renderer/Thread.zig +++ b/src/renderer/Thread.zig @@ -371,10 +371,7 @@ fn drainMailbox(self: *Thread) !void { self.renderer.markDirty(); }, - .resize => |v| try self.renderer.setScreenSize( - v.screen, - v.padding, - ), + .resize => |v| try self.renderer.setScreenSize(v), .change_config => |config| { defer config.alloc.destroy(config.thread);