renderer: separate update frame data from draw

This commit is contained in:
Mitchell Hashimoto
2023-11-14 14:13:39 -08:00
parent 0230222c0d
commit 0e92f68228
2 changed files with 39 additions and 22 deletions

View File

@ -76,6 +76,10 @@ background_color: terminal.color.RGB,
/// by a terminal application /// by a terminal application
cursor_color: ?terminal.color.RGB, cursor_color: ?terminal.color.RGB,
/// The current frame background color. This is only updated during
/// the updateFrame method.
current_background_color: terminal.color.RGB,
/// The current set of cells to render. This is rebuilt on every frame /// The current set of cells to render. This is rebuilt on every frame
/// but we keep this around so that we don't reallocate. Each set of /// but we keep this around so that we don't reallocate. Each set of
/// cells goes into a separate shader. /// cells goes into a separate shader.
@ -271,6 +275,7 @@ pub fn init(alloc: Allocator, options: renderer.Options) !Metal {
.foreground_color = options.config.foreground, .foreground_color = options.config.foreground,
.background_color = options.config.background, .background_color = options.config.background,
.cursor_color = options.config.cursor_color, .cursor_color = options.config.cursor_color,
.current_background_color = options.config.background,
// Render state // Render state
.cells_bg = .{}, .cells_bg = .{},
@ -448,8 +453,8 @@ pub fn setFontSize(self: *Metal, size: font.face.DesiredSize) !void {
}, .{ .forever = {} }); }, .{ .forever = {} });
} }
/// The primary render callback that is completely thread-safe. /// Update the frame data.
pub fn render( pub fn updateFrame(
self: *Metal, self: *Metal,
surface: *apprt.Surface, surface: *apprt.Surface,
state: *renderer.State, state: *renderer.State,
@ -535,10 +540,6 @@ pub fn render(
}; };
defer critical.screen.deinit(); defer critical.screen.deinit();
// @autoreleasepool {}
const pool = objc.AutoreleasePool.init();
defer pool.deinit();
// Build our GPU cells // Build our GPU cells
try self.rebuildCells( try self.rebuildCells(
critical.selection, critical.selection,
@ -547,18 +548,8 @@ pub fn render(
critical.cursor_style, critical.cursor_style,
); );
// Get our drawable (CAMetalDrawable) // Update our background color
const drawable = self.swapchain.msgSend(objc.Object, objc.sel("nextDrawable"), .{}); self.current_background_color = critical.bg;
// If our font atlas changed, sync the texture data
if (self.font_group.atlas_greyscale.modified) {
try syncAtlasTexture(self.device, &self.font_group.atlas_greyscale, &self.texture_greyscale);
self.font_group.atlas_greyscale.modified = false;
}
if (self.font_group.atlas_color.modified) {
try syncAtlasTexture(self.device, &self.font_group.atlas_color, &self.texture_color);
self.font_group.atlas_color.modified = false;
}
// Go through our images and see if we need to setup any textures. // Go through our images and see if we need to setup any textures.
{ {
@ -580,6 +571,26 @@ pub fn render(
} }
} }
} }
}
/// Draw the frame to the screen.
pub fn drawFrame(self: *Metal) !void {
// @autoreleasepool {}
const pool = objc.AutoreleasePool.init();
defer pool.deinit();
// Get our drawable (CAMetalDrawable)
const drawable = self.swapchain.msgSend(objc.Object, objc.sel("nextDrawable"), .{});
// If our font atlas changed, sync the texture data
if (self.font_group.atlas_greyscale.modified) {
try syncAtlasTexture(self.device, &self.font_group.atlas_greyscale, &self.texture_greyscale);
self.font_group.atlas_greyscale.modified = false;
}
if (self.font_group.atlas_color.modified) {
try syncAtlasTexture(self.device, &self.font_group.atlas_color, &self.texture_color);
self.font_group.atlas_color.modified = false;
}
// Command buffer (MTLCommandBuffer) // Command buffer (MTLCommandBuffer)
const buffer = self.queue.msgSend(objc.Object, objc.sel("commandBuffer"), .{}); const buffer = self.queue.msgSend(objc.Object, objc.sel("commandBuffer"), .{});
@ -612,9 +623,9 @@ pub fn render(
attachment.setProperty("storeAction", @intFromEnum(mtl.MTLStoreAction.store)); attachment.setProperty("storeAction", @intFromEnum(mtl.MTLStoreAction.store));
attachment.setProperty("texture", texture); attachment.setProperty("texture", texture);
attachment.setProperty("clearColor", mtl.MTLClearColor{ attachment.setProperty("clearColor", mtl.MTLClearColor{
.red = @as(f32, @floatFromInt(critical.bg.r)) / 255, .red = @as(f32, @floatFromInt(self.current_background_color.r)) / 255,
.green = @as(f32, @floatFromInt(critical.bg.g)) / 255, .green = @as(f32, @floatFromInt(self.current_background_color.g)) / 255,
.blue = @as(f32, @floatFromInt(critical.bg.b)) / 255, .blue = @as(f32, @floatFromInt(self.current_background_color.b)) / 255,
.alpha = self.config.background_opacity, .alpha = self.config.background_opacity,
}); });
} }

View File

@ -346,7 +346,8 @@ fn renderCallback(
_ = t.app_mailbox.push(.{ .redraw_inspector = t.surface }, .{ .instant = {} }); _ = t.app_mailbox.push(.{ .redraw_inspector = t.surface }, .{ .instant = {} });
} }
t.renderer.render( // Update our frame data
t.renderer.updateFrame(
t.surface, t.surface,
t.state, t.state,
t.flags.cursor_blink_visible, t.flags.cursor_blink_visible,
@ -359,8 +360,13 @@ fn renderCallback(
renderer.OpenGL.single_threaded_draw) renderer.OpenGL.single_threaded_draw)
{ {
_ = t.app_mailbox.push(.{ .redraw_surface = t.surface }, .{ .instant = {} }); _ = t.app_mailbox.push(.{ .redraw_surface = t.surface }, .{ .instant = {} });
return .disarm;
} }
// Draw
t.renderer.drawFrame() catch |err|
log.warn("error drawing err={}", .{err});
return .disarm; return .disarm;
} }