renderer/metal: use new size struct

This commit is contained in:
Mitchell Hashimoto
2024-11-14 13:43:56 -08:00
parent 6f62944b9c
commit b3b5e15e96
4 changed files with 46 additions and 97 deletions

View File

@ -397,20 +397,6 @@ pub fn init(
.right = padding_right, .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. // Build our size struct which has all the sizes we need.
const size: renderer.Size = size: { const size: renderer.Size = size: {
var size: renderer.Size = .{ var size: renderer.Size = .{
@ -433,6 +419,17 @@ pub fn init(
break :size size; 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. // The mutex used to protect our renderer state.
const mutex = try alloc.create(std.Thread.Mutex); const mutex = try alloc.create(std.Thread.Mutex);
mutex.* = .{}; mutex.* = .{};

View File

@ -70,12 +70,8 @@ surface_mailbox: apprt.surface.Mailbox,
/// Current font metrics defining our grid. /// Current font metrics defining our grid.
grid_metrics: font.face.Metrics, grid_metrics: font.face.Metrics,
/// Current screen size dimensions for this grid. This is set on the first /// The size of everything.
/// resize event, and is not immediately available. size: renderer.Size,
screen_size: ?renderer.ScreenSize,
/// Explicit padding.
padding: renderer.Options.Padding,
/// True if the window is focused /// True if the window is focused
focused: bool, focused: bool,
@ -631,8 +627,7 @@ pub fn init(alloc: Allocator, options: renderer.Options) !Metal {
.config = options.config, .config = options.config,
.surface_mailbox = options.surface_mailbox, .surface_mailbox = options.surface_mailbox,
.grid_metrics = font_critical.metrics, .grid_metrics = font_critical.metrics,
.screen_size = null, .size = options.size,
.padding = options.padding,
.focused = true, .focused = true,
.foreground_color = options.config.foreground, .foreground_color = options.config.foreground,
.background_color = options.config.background, .background_color = options.config.background,
@ -796,19 +791,6 @@ pub fn hasVsync(self: *const Metal) bool {
return display_link.isRunning(); 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. /// Callback when the focus changes for the terminal this is rendering.
/// ///
/// Must be called on the render thread. /// Must be called on the render thread.
@ -878,8 +860,7 @@ pub fn setFontGrid(self: *Metal, grid: *font.SharedGrid) void {
// //
// If the screen size isn't set, it will be eventually so that'll call // If the screen size isn't set, it will be eventually so that'll call
// the setScreenSize automatically. // the setScreenSize automatically.
if (self.screen_size) |size| { self.setScreenSize(self.size) catch |err| {
self.setScreenSize(size, self.padding.explicit) catch |err| {
// The setFontGrid function can't fail but resizing our cell // The setFontGrid function can't fail but resizing our cell
// buffer definitely can fail. If it does, our renderer is probably // buffer definitely can fail. If it does, our renderer is probably
// screwed but let's just log it and continue until we can figure // screwed but let's just log it and continue until we can figure
@ -887,7 +868,6 @@ pub fn setFontGrid(self: *Metal, grid: *font.SharedGrid) void {
log.err("error resizing cells buffer err={}", .{err}); log.err("error resizing cells buffer err={}", .{err});
}; };
} }
}
/// Update the frame data. /// Update the frame data.
pub fn updateFrame( pub fn updateFrame(
@ -898,9 +878,6 @@ pub fn updateFrame(
) !void { ) !void {
_ = surface; _ = 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. // Data we extract out of the critical area.
const Critical = struct { const Critical = struct {
bg: terminal.color.RGB, bg: terminal.color.RGB,
@ -1116,9 +1093,6 @@ pub fn updateFrame(
pub fn drawFrame(self: *Metal, surface: *apprt.Surface) !void { pub fn drawFrame(self: *Metal, surface: *apprt.Surface) !void {
_ = surface; _ = 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 // 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 // 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 // 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. /// Resize the screen.
pub fn setScreenSize( pub fn setScreenSize(
self: *Metal, self: *Metal,
dim: renderer.ScreenSize, size: renderer.Size,
pad: renderer.Padding,
) !void { ) !void {
// Store our sizes // Store our sizes
self.screen_size = dim; self.size = size;
self.padding.explicit = pad; const grid_size = size.grid();
const terminal_size = size.terminal();
// 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);
// Blank space around the grid. // Blank space around the grid.
const blank: renderer.Padding = dim.blankPadding(padding, grid_size, .{ const blank: renderer.Padding = size.screen.blankPadding(
.width = self.grid_metrics.cell_width, size.padding,
.height = self.grid_metrics.cell_height, grid_size,
}).add(padding); size.cell,
).add(size.padding);
var padding_extend = self.uniforms.padding_extend; var padding_extend = self.uniforms.padding_extend;
switch (self.config.padding_color) { switch (self.config.padding_color) {
@ -2030,18 +1985,18 @@ pub fn setScreenSize(
// Set the size of the drawable surface to the bounds // Set the size of the drawable surface to the bounds
self.layer.setProperty("drawableSize", macos.graphics.Size{ self.layer.setProperty("drawableSize", macos.graphics.Size{
.width = @floatFromInt(dim.width), .width = @floatFromInt(size.screen.width),
.height = @floatFromInt(dim.height), .height = @floatFromInt(size.screen.height),
}); });
// Setup our uniforms // Setup our uniforms
const old = self.uniforms; const old = self.uniforms;
self.uniforms = .{ self.uniforms = .{
.projection_matrix = math.ortho2d( .projection_matrix = math.ortho2d(
-1 * @as(f32, @floatFromInt(padding.left)), -1 * @as(f32, @floatFromInt(size.padding.left)),
@floatFromInt(padded_dim.width + padding.right), @floatFromInt(terminal_size.width + size.padding.right),
@floatFromInt(padded_dim.height + padding.bottom), @floatFromInt(terminal_size.height + size.padding.bottom),
-1 * @as(f32, @floatFromInt(padding.top)), -1 * @as(f32, @floatFromInt(size.padding.top)),
), ),
.cell_size = .{ .cell_size = .{
@floatFromInt(self.grid_metrics.cell_width), @floatFromInt(self.grid_metrics.cell_width),
@ -2082,8 +2037,8 @@ pub fn setScreenSize(
} }
state.uniforms.resolution = .{ state.uniforms.resolution = .{
@floatFromInt(dim.width), @floatFromInt(size.screen.width),
@floatFromInt(dim.height), @floatFromInt(size.screen.height),
1, 1,
}; };
@ -2097,8 +2052,8 @@ pub fn setScreenSize(
break :init id_init; break :init id_init;
}; };
desc.setProperty("pixelFormat", @intFromEnum(mtl.MTLPixelFormat.bgra8unorm)); desc.setProperty("pixelFormat", @intFromEnum(mtl.MTLPixelFormat.bgra8unorm));
desc.setProperty("width", @as(c_ulong, @intCast(dim.width))); desc.setProperty("width", @as(c_ulong, @intCast(size.screen.width)));
desc.setProperty("height", @as(c_ulong, @intCast(dim.height))); desc.setProperty("height", @as(c_ulong, @intCast(size.screen.height)));
desc.setProperty( desc.setProperty(
"usage", "usage",
@intFromEnum(mtl.MTLTextureUsage.render_target) | @intFromEnum(mtl.MTLTextureUsage.render_target) |
@ -2127,8 +2082,8 @@ pub fn setScreenSize(
break :init id_init; break :init id_init;
}; };
desc.setProperty("pixelFormat", @intFromEnum(mtl.MTLPixelFormat.bgra8unorm)); desc.setProperty("pixelFormat", @intFromEnum(mtl.MTLPixelFormat.bgra8unorm));
desc.setProperty("width", @as(c_ulong, @intCast(dim.width))); desc.setProperty("width", @as(c_ulong, @intCast(size.screen.width)));
desc.setProperty("height", @as(c_ulong, @intCast(dim.height))); desc.setProperty("height", @as(c_ulong, @intCast(size.screen.height)));
desc.setProperty( desc.setProperty(
"usage", "usage",
@intFromEnum(mtl.MTLTextureUsage.render_target) | @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 /// Convert the terminal state to GPU cells stored in CPU memory. These

View File

@ -11,8 +11,8 @@ config: renderer.Renderer.DerivedConfig,
/// The font grid that should be used along with the key for deref-ing. /// The font grid that should be used along with the key for deref-ing.
font_grid: *font.SharedGrid, font_grid: *font.SharedGrid,
/// Padding options for the viewport. /// The size of everything.
padding: Padding, size: renderer.Size,
/// The mailbox for sending the surface messages. This is only valid /// 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. /// once the thread has started and should not be used outside of the thread.

View File

@ -371,10 +371,7 @@ fn drainMailbox(self: *Thread) !void {
self.renderer.markDirty(); self.renderer.markDirty();
}, },
.resize => |v| try self.renderer.setScreenSize( .resize => |v| try self.renderer.setScreenSize(v),
v.screen,
v.padding,
),
.change_config => |config| { .change_config => |config| {
defer config.alloc.destroy(config.thread); defer config.alloc.destroy(config.thread);