renderer: use a DerivedConfig to avoid the main Config pointer

This commit is contained in:
Mitchell Hashimoto
2023-03-16 16:03:44 -07:00
parent b26e51d222
commit f34da17a11
4 changed files with 129 additions and 76 deletions

View File

@ -322,7 +322,7 @@ pub fn init(
// Create our terminal grid with the initial size
var renderer_impl = try Renderer.init(alloc, .{
.config = config,
.config = try Renderer.DerivedConfig.init(alloc, config),
.font_group = font_group,
.padding = .{
.explicit = padding,

View File

@ -11,6 +11,7 @@ const objc = @import("objc");
const macos = @import("macos");
const imgui = @import("imgui");
const apprt = @import("../apprt.zig");
const configpkg = @import("../config.zig");
const font = @import("../font/main.zig");
const terminal = @import("../terminal/main.zig");
const renderer = @import("../renderer.zig");
@ -31,6 +32,9 @@ const log = std.log.scoped(.metal);
/// Allocator that can be used
alloc: std.mem.Allocator,
/// The configuration we need derived from the main config.
config: DerivedConfig,
/// The mailbox for communicating with the window.
surface_mailbox: apprt.surface.Mailbox,
@ -51,17 +55,6 @@ focused: bool,
/// blinking.
cursor_visible: bool,
cursor_style: renderer.CursorStyle,
cursor_color: ?terminal.color.RGB,
/// Default foreground color
foreground: terminal.color.RGB,
/// Default background color
background: terminal.color.RGB,
/// Default selection color
selection_background: ?terminal.color.RGB,
selection_foreground: ?terminal.color.RGB,
/// 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
@ -117,6 +110,48 @@ const GPUCellMode = enum(u8) {
strikethrough = 8,
};
/// The configuration for this renderer that is derived from the main
/// configuration. This must be exported so that we don't need to
/// pass around Config pointers which makes memory management a pain.
pub const DerivedConfig = struct {
cursor_color: ?terminal.color.RGB,
background: terminal.color.RGB,
foreground: terminal.color.RGB,
selection_background: ?terminal.color.RGB,
selection_foreground: ?terminal.color.RGB,
pub fn init(
alloc_gpa: Allocator,
config: *const configpkg.Config,
) !DerivedConfig {
_ = alloc_gpa;
return .{
.cursor_color = if (config.@"cursor-color") |col|
col.toTerminalRGB()
else
null,
.background = config.background.toTerminalRGB(),
.foreground = config.foreground.toTerminalRGB(),
.selection_background = if (config.@"selection-background") |bg|
bg.toTerminalRGB()
else
null,
.selection_foreground = if (config.@"selection-foreground") |bg|
bg.toTerminalRGB()
else
null,
};
}
pub fn deinit(self: *DerivedConfig) void {
_ = self;
}
};
/// Returns the hints that we want for this
pub fn glfwWindowHints() glfw.Window.Hints {
return .{
@ -233,6 +268,7 @@ pub fn init(alloc: Allocator, options: renderer.Options) !Metal {
return Metal{
.alloc = alloc,
.config = options.config,
.surface_mailbox = options.surface_mailbox,
.cell_size = .{ .width = metrics.cell_width, .height = metrics.cell_height },
.screen_size = null,
@ -240,17 +276,6 @@ pub fn init(alloc: Allocator, options: renderer.Options) !Metal {
.focused = true,
.cursor_visible = true,
.cursor_style = .box,
.cursor_color = if (options.config.@"cursor-color") |col| col.toTerminalRGB() else null,
.background = options.config.background.toTerminalRGB(),
.foreground = options.config.foreground.toTerminalRGB(),
.selection_background = if (options.config.@"selection-background") |bg|
bg.toTerminalRGB()
else
null,
.selection_foreground = if (options.config.@"selection-foreground") |bg|
bg.toTerminalRGB()
else
null,
// Render state
.cells_bg = .{},
@ -286,6 +311,8 @@ pub fn deinit(self: *Metal) void {
self.font_shaper.deinit();
self.alloc.free(self.font_shaper.cell_buf);
self.config.deinit();
deinitMTLResource(self.buf_cells_bg);
deinitMTLResource(self.buf_cells);
deinitMTLResource(self.buf_instance);
@ -482,15 +509,15 @@ pub fn render(
}
// Swap bg/fg if the terminal is reversed
const bg = self.background;
const fg = self.foreground;
const bg = self.config.background;
const fg = self.config.foreground;
defer {
self.background = bg;
self.foreground = fg;
self.config.background = bg;
self.config.foreground = fg;
}
if (state.terminal.modes.reverse_colors) {
self.background = fg;
self.foreground = bg;
self.config.background = fg;
self.config.foreground = bg;
}
// We used to share terminal state, but we've since learned through
@ -516,7 +543,7 @@ pub fn render(
null;
break :critical .{
.bg = self.background,
.bg = self.config.background,
.devmode = if (state.devmode) |dm| dm.visible else false,
.selection = selection,
.screen = screen_copy,
@ -878,8 +905,8 @@ pub fn updateCell(
// If we are selected, we our colors are just inverted fg/bg
if (sel.contains(screen_point)) {
break :colors BgFg{
.bg = self.selection_background orelse self.foreground,
.fg = self.selection_foreground orelse self.background,
.bg = self.config.selection_background orelse self.config.foreground,
.fg = self.config.selection_foreground orelse self.config.background,
};
}
}
@ -888,13 +915,13 @@ pub fn updateCell(
// In normal mode, background and fg match the cell. We
// un-optionalize the fg by defaulting to our fg color.
.bg = if (cell.attrs.has_bg) cell.bg else null,
.fg = if (cell.attrs.has_fg) cell.fg else self.foreground,
.fg = if (cell.attrs.has_fg) cell.fg else self.config.foreground,
} else .{
// In inverted mode, the background MUST be set to something
// (is never null) so it is either the fg or default fg. The
// fg is either the bg or default background.
.bg = if (cell.attrs.has_fg) cell.fg else self.foreground,
.fg = if (cell.attrs.has_bg) cell.bg else self.background,
.bg = if (cell.attrs.has_fg) cell.fg else self.config.foreground,
.fg = if (cell.attrs.has_bg) cell.bg else self.config.background,
};
break :colors res;
};
@ -988,7 +1015,7 @@ fn addCursor(self: *Metal, screen: *terminal.Screen) void {
screen.cursor.x,
);
const color = self.cursor_color orelse terminal.color.RGB{
const color = self.config.cursor_color orelse terminal.color.RGB{
.r = 0xFF,
.g = 0xFF,
.b = 0xFF,

View File

@ -8,6 +8,7 @@ const assert = std.debug.assert;
const testing = std.testing;
const Allocator = std.mem.Allocator;
const apprt = @import("../apprt.zig");
const configpkg = @import("../config.zig");
const font = @import("../font/main.zig");
const imgui = @import("imgui");
const renderer = @import("../renderer.zig");
@ -43,6 +44,9 @@ const drawMutexZero = if (DrawMutex == void) void{} else .{};
alloc: std.mem.Allocator,
/// The configuration we need derived from the main config.
config: DerivedConfig,
/// Current cell dimensions for this grid.
cell_size: renderer.CellSize,
@ -84,17 +88,6 @@ font_shaper: font.Shaper,
/// blinking.
cursor_visible: bool,
cursor_style: renderer.CursorStyle,
cursor_color: ?terminal.color.RGB,
/// Default foreground color
foreground: terminal.color.RGB,
/// Default background color
background: terminal.color.RGB,
/// Default selection color
selection_background: ?terminal.color.RGB,
selection_foreground: ?terminal.color.RGB,
/// True if the window is focused
focused: bool,
@ -232,6 +225,48 @@ const GPUCellMode = enum(u8) {
}
};
/// The configuration for this renderer that is derived from the main
/// configuration. This must be exported so that we don't need to
/// pass around Config pointers which makes memory management a pain.
pub const DerivedConfig = struct {
cursor_color: ?terminal.color.RGB,
background: terminal.color.RGB,
foreground: terminal.color.RGB,
selection_background: ?terminal.color.RGB,
selection_foreground: ?terminal.color.RGB,
pub fn init(
alloc_gpa: Allocator,
config: *const configpkg.Config,
) !DerivedConfig {
_ = alloc_gpa;
return .{
.cursor_color = if (config.@"cursor-color") |col|
col.toTerminalRGB()
else
null,
.background = config.background.toTerminalRGB(),
.foreground = config.foreground.toTerminalRGB(),
.selection_background = if (config.@"selection-background") |bg|
bg.toTerminalRGB()
else
null,
.selection_foreground = if (config.@"selection-foreground") |bg|
bg.toTerminalRGB()
else
null,
};
}
pub fn deinit(self: *DerivedConfig) void {
_ = self;
}
};
pub fn init(alloc: Allocator, options: renderer.Options) !OpenGL {
// Create the initial font shaper
var shape_buf = try alloc.alloc(font.shape.Cell, 1);
@ -354,6 +389,7 @@ pub fn init(alloc: Allocator, options: renderer.Options) !OpenGL {
return OpenGL{
.alloc = alloc,
.config = options.config,
.cells_bg = .{},
.cells = .{},
.cells_lru = CellsLRU.init(0),
@ -369,18 +405,7 @@ pub fn init(alloc: Allocator, options: renderer.Options) !OpenGL {
.font_shaper = shaper,
.cursor_visible = true,
.cursor_style = .box,
.cursor_color = if (options.config.@"cursor-color") |col| col.toTerminalRGB() else null,
.background = options.config.background.toTerminalRGB(),
.foreground = options.config.foreground.toTerminalRGB(),
.draw_background = options.config.background.toTerminalRGB(),
.selection_background = if (options.config.@"selection-background") |bg|
bg.toTerminalRGB()
else
null,
.selection_foreground = if (options.config.@"selection-foreground") |bg|
bg.toTerminalRGB()
else
null,
.draw_background = options.config.background,
.focused = true,
.padding = options.padding,
.surface_mailbox = options.surface_mailbox,
@ -404,6 +429,9 @@ pub fn deinit(self: *OpenGL) void {
self.cells.deinit(self.alloc);
self.cells_bg.deinit(self.alloc);
self.config.deinit();
self.* = undefined;
}
@ -673,15 +701,15 @@ pub fn render(
}
// Swap bg/fg if the terminal is reversed
const bg = self.background;
const fg = self.foreground;
const bg = self.config.background;
const fg = self.config.foreground;
defer {
self.background = bg;
self.foreground = fg;
self.config.background = bg;
self.config.foreground = fg;
}
if (state.terminal.modes.reverse_colors) {
self.background = fg;
self.foreground = bg;
self.config.background = fg;
self.config.foreground = bg;
}
// Build our devmode draw data
@ -723,7 +751,7 @@ pub fn render(
null;
break :critical .{
.gl_bg = self.background,
.gl_bg = self.config.background,
.devmode_data = devmode_data,
.active_screen = state.terminal.active_screen,
.selection = selection,
@ -944,7 +972,7 @@ fn addCursor(self: *OpenGL, screen: *terminal.Screen) void {
screen.cursor.x,
);
const color = self.cursor_color orelse terminal.color.RGB{
const color = self.config.cursor_color orelse terminal.color.RGB{
.r = 0xFF,
.g = 0xFF,
.b = 0xFF,
@ -1031,8 +1059,8 @@ pub fn updateCell(
// If we are selected, we use the selection colors
if (sel.contains(screen_point)) {
break :colors BgFg{
.bg = self.selection_background orelse self.foreground,
.fg = self.selection_foreground orelse self.background,
.bg = self.config.selection_background orelse self.config.foreground,
.fg = self.config.selection_foreground orelse self.config.background,
};
}
}
@ -1041,13 +1069,13 @@ pub fn updateCell(
// In normal mode, background and fg match the cell. We
// un-optionalize the fg by defaulting to our fg color.
.bg = if (cell.attrs.has_bg) cell.bg else null,
.fg = if (cell.attrs.has_fg) cell.fg else self.foreground,
.fg = if (cell.attrs.has_fg) cell.fg else self.config.foreground,
} else .{
// In inverted mode, the background MUST be set to something
// (is never null) so it is either the fg or default fg. The
// fg is either the bg or default background.
.bg = if (cell.attrs.has_fg) cell.fg else self.foreground,
.fg = if (cell.attrs.has_bg) cell.bg else self.background,
.bg = if (cell.attrs.has_fg) cell.fg else self.config.foreground,
.fg = if (cell.attrs.has_bg) cell.bg else self.config.background,
};
break :colors res;
};

View File

@ -5,10 +5,8 @@ const font = @import("../font/main.zig");
const renderer = @import("../renderer.zig");
const Config = @import("../config.zig").Config;
/// The app configuration. This must NOT be stored by any termio implementation.
/// The memory it points to is NOT stable after the init call so any values
/// in here must be copied.
config: *const Config,
/// The derived configuration for this renderer implementation.
config: renderer.Renderer.DerivedConfig,
/// The font group that should be used.
font_group: *font.GroupCache,