mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-22 19:56:08 +03:00
renderer: use a DerivedConfig to avoid the main Config pointer
This commit is contained in:
@ -322,7 +322,7 @@ pub fn init(
|
|||||||
|
|
||||||
// Create our terminal grid with the initial size
|
// Create our terminal grid with the initial size
|
||||||
var renderer_impl = try Renderer.init(alloc, .{
|
var renderer_impl = try Renderer.init(alloc, .{
|
||||||
.config = config,
|
.config = try Renderer.DerivedConfig.init(alloc, config),
|
||||||
.font_group = font_group,
|
.font_group = font_group,
|
||||||
.padding = .{
|
.padding = .{
|
||||||
.explicit = padding,
|
.explicit = padding,
|
||||||
|
@ -11,6 +11,7 @@ const objc = @import("objc");
|
|||||||
const macos = @import("macos");
|
const macos = @import("macos");
|
||||||
const imgui = @import("imgui");
|
const imgui = @import("imgui");
|
||||||
const apprt = @import("../apprt.zig");
|
const apprt = @import("../apprt.zig");
|
||||||
|
const configpkg = @import("../config.zig");
|
||||||
const font = @import("../font/main.zig");
|
const font = @import("../font/main.zig");
|
||||||
const terminal = @import("../terminal/main.zig");
|
const terminal = @import("../terminal/main.zig");
|
||||||
const renderer = @import("../renderer.zig");
|
const renderer = @import("../renderer.zig");
|
||||||
@ -31,6 +32,9 @@ const log = std.log.scoped(.metal);
|
|||||||
/// Allocator that can be used
|
/// Allocator that can be used
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
|
|
||||||
|
/// The configuration we need derived from the main config.
|
||||||
|
config: DerivedConfig,
|
||||||
|
|
||||||
/// The mailbox for communicating with the window.
|
/// The mailbox for communicating with the window.
|
||||||
surface_mailbox: apprt.surface.Mailbox,
|
surface_mailbox: apprt.surface.Mailbox,
|
||||||
|
|
||||||
@ -51,17 +55,6 @@ focused: bool,
|
|||||||
/// blinking.
|
/// blinking.
|
||||||
cursor_visible: bool,
|
cursor_visible: bool,
|
||||||
cursor_style: renderer.CursorStyle,
|
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
|
/// 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
|
||||||
@ -117,6 +110,48 @@ const GPUCellMode = enum(u8) {
|
|||||||
strikethrough = 8,
|
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
|
/// Returns the hints that we want for this
|
||||||
pub fn glfwWindowHints() glfw.Window.Hints {
|
pub fn glfwWindowHints() glfw.Window.Hints {
|
||||||
return .{
|
return .{
|
||||||
@ -233,6 +268,7 @@ pub fn init(alloc: Allocator, options: renderer.Options) !Metal {
|
|||||||
|
|
||||||
return Metal{
|
return Metal{
|
||||||
.alloc = alloc,
|
.alloc = alloc,
|
||||||
|
.config = options.config,
|
||||||
.surface_mailbox = options.surface_mailbox,
|
.surface_mailbox = options.surface_mailbox,
|
||||||
.cell_size = .{ .width = metrics.cell_width, .height = metrics.cell_height },
|
.cell_size = .{ .width = metrics.cell_width, .height = metrics.cell_height },
|
||||||
.screen_size = null,
|
.screen_size = null,
|
||||||
@ -240,17 +276,6 @@ pub fn init(alloc: Allocator, options: renderer.Options) !Metal {
|
|||||||
.focused = true,
|
.focused = true,
|
||||||
.cursor_visible = true,
|
.cursor_visible = true,
|
||||||
.cursor_style = .box,
|
.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
|
// Render state
|
||||||
.cells_bg = .{},
|
.cells_bg = .{},
|
||||||
@ -286,6 +311,8 @@ pub fn deinit(self: *Metal) void {
|
|||||||
self.font_shaper.deinit();
|
self.font_shaper.deinit();
|
||||||
self.alloc.free(self.font_shaper.cell_buf);
|
self.alloc.free(self.font_shaper.cell_buf);
|
||||||
|
|
||||||
|
self.config.deinit();
|
||||||
|
|
||||||
deinitMTLResource(self.buf_cells_bg);
|
deinitMTLResource(self.buf_cells_bg);
|
||||||
deinitMTLResource(self.buf_cells);
|
deinitMTLResource(self.buf_cells);
|
||||||
deinitMTLResource(self.buf_instance);
|
deinitMTLResource(self.buf_instance);
|
||||||
@ -482,15 +509,15 @@ pub fn render(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Swap bg/fg if the terminal is reversed
|
// Swap bg/fg if the terminal is reversed
|
||||||
const bg = self.background;
|
const bg = self.config.background;
|
||||||
const fg = self.foreground;
|
const fg = self.config.foreground;
|
||||||
defer {
|
defer {
|
||||||
self.background = bg;
|
self.config.background = bg;
|
||||||
self.foreground = fg;
|
self.config.foreground = fg;
|
||||||
}
|
}
|
||||||
if (state.terminal.modes.reverse_colors) {
|
if (state.terminal.modes.reverse_colors) {
|
||||||
self.background = fg;
|
self.config.background = fg;
|
||||||
self.foreground = bg;
|
self.config.foreground = bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We used to share terminal state, but we've since learned through
|
// We used to share terminal state, but we've since learned through
|
||||||
@ -516,7 +543,7 @@ pub fn render(
|
|||||||
null;
|
null;
|
||||||
|
|
||||||
break :critical .{
|
break :critical .{
|
||||||
.bg = self.background,
|
.bg = self.config.background,
|
||||||
.devmode = if (state.devmode) |dm| dm.visible else false,
|
.devmode = if (state.devmode) |dm| dm.visible else false,
|
||||||
.selection = selection,
|
.selection = selection,
|
||||||
.screen = screen_copy,
|
.screen = screen_copy,
|
||||||
@ -878,8 +905,8 @@ pub fn updateCell(
|
|||||||
// If we are selected, we our colors are just inverted fg/bg
|
// If we are selected, we our colors are just inverted fg/bg
|
||||||
if (sel.contains(screen_point)) {
|
if (sel.contains(screen_point)) {
|
||||||
break :colors BgFg{
|
break :colors BgFg{
|
||||||
.bg = self.selection_background orelse self.foreground,
|
.bg = self.config.selection_background orelse self.config.foreground,
|
||||||
.fg = self.selection_foreground orelse self.background,
|
.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
|
// In normal mode, background and fg match the cell. We
|
||||||
// un-optionalize the fg by defaulting to our fg color.
|
// un-optionalize the fg by defaulting to our fg color.
|
||||||
.bg = if (cell.attrs.has_bg) cell.bg else null,
|
.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 .{
|
} else .{
|
||||||
// In inverted mode, the background MUST be set to something
|
// In inverted mode, the background MUST be set to something
|
||||||
// (is never null) so it is either the fg or default fg. The
|
// (is never null) so it is either the fg or default fg. The
|
||||||
// fg is either the bg or default background.
|
// fg is either the bg or default background.
|
||||||
.bg = if (cell.attrs.has_fg) cell.fg else self.foreground,
|
.bg = if (cell.attrs.has_fg) cell.fg else self.config.foreground,
|
||||||
.fg = if (cell.attrs.has_bg) cell.bg else self.background,
|
.fg = if (cell.attrs.has_bg) cell.bg else self.config.background,
|
||||||
};
|
};
|
||||||
break :colors res;
|
break :colors res;
|
||||||
};
|
};
|
||||||
@ -988,7 +1015,7 @@ fn addCursor(self: *Metal, screen: *terminal.Screen) void {
|
|||||||
screen.cursor.x,
|
screen.cursor.x,
|
||||||
);
|
);
|
||||||
|
|
||||||
const color = self.cursor_color orelse terminal.color.RGB{
|
const color = self.config.cursor_color orelse terminal.color.RGB{
|
||||||
.r = 0xFF,
|
.r = 0xFF,
|
||||||
.g = 0xFF,
|
.g = 0xFF,
|
||||||
.b = 0xFF,
|
.b = 0xFF,
|
||||||
|
@ -8,6 +8,7 @@ const assert = std.debug.assert;
|
|||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const apprt = @import("../apprt.zig");
|
const apprt = @import("../apprt.zig");
|
||||||
|
const configpkg = @import("../config.zig");
|
||||||
const font = @import("../font/main.zig");
|
const font = @import("../font/main.zig");
|
||||||
const imgui = @import("imgui");
|
const imgui = @import("imgui");
|
||||||
const renderer = @import("../renderer.zig");
|
const renderer = @import("../renderer.zig");
|
||||||
@ -43,6 +44,9 @@ const drawMutexZero = if (DrawMutex == void) void{} else .{};
|
|||||||
|
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
|
|
||||||
|
/// The configuration we need derived from the main config.
|
||||||
|
config: DerivedConfig,
|
||||||
|
|
||||||
/// Current cell dimensions for this grid.
|
/// Current cell dimensions for this grid.
|
||||||
cell_size: renderer.CellSize,
|
cell_size: renderer.CellSize,
|
||||||
|
|
||||||
@ -84,17 +88,6 @@ font_shaper: font.Shaper,
|
|||||||
/// blinking.
|
/// blinking.
|
||||||
cursor_visible: bool,
|
cursor_visible: bool,
|
||||||
cursor_style: renderer.CursorStyle,
|
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
|
/// True if the window is focused
|
||||||
focused: bool,
|
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 {
|
pub fn init(alloc: Allocator, options: renderer.Options) !OpenGL {
|
||||||
// Create the initial font shaper
|
// Create the initial font shaper
|
||||||
var shape_buf = try alloc.alloc(font.shape.Cell, 1);
|
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{
|
return OpenGL{
|
||||||
.alloc = alloc,
|
.alloc = alloc,
|
||||||
|
.config = options.config,
|
||||||
.cells_bg = .{},
|
.cells_bg = .{},
|
||||||
.cells = .{},
|
.cells = .{},
|
||||||
.cells_lru = CellsLRU.init(0),
|
.cells_lru = CellsLRU.init(0),
|
||||||
@ -369,18 +405,7 @@ pub fn init(alloc: Allocator, options: renderer.Options) !OpenGL {
|
|||||||
.font_shaper = shaper,
|
.font_shaper = shaper,
|
||||||
.cursor_visible = true,
|
.cursor_visible = true,
|
||||||
.cursor_style = .box,
|
.cursor_style = .box,
|
||||||
.cursor_color = if (options.config.@"cursor-color") |col| col.toTerminalRGB() else null,
|
.draw_background = options.config.background,
|
||||||
.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,
|
|
||||||
.focused = true,
|
.focused = true,
|
||||||
.padding = options.padding,
|
.padding = options.padding,
|
||||||
.surface_mailbox = options.surface_mailbox,
|
.surface_mailbox = options.surface_mailbox,
|
||||||
@ -404,6 +429,9 @@ pub fn deinit(self: *OpenGL) void {
|
|||||||
|
|
||||||
self.cells.deinit(self.alloc);
|
self.cells.deinit(self.alloc);
|
||||||
self.cells_bg.deinit(self.alloc);
|
self.cells_bg.deinit(self.alloc);
|
||||||
|
|
||||||
|
self.config.deinit();
|
||||||
|
|
||||||
self.* = undefined;
|
self.* = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -673,15 +701,15 @@ pub fn render(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Swap bg/fg if the terminal is reversed
|
// Swap bg/fg if the terminal is reversed
|
||||||
const bg = self.background;
|
const bg = self.config.background;
|
||||||
const fg = self.foreground;
|
const fg = self.config.foreground;
|
||||||
defer {
|
defer {
|
||||||
self.background = bg;
|
self.config.background = bg;
|
||||||
self.foreground = fg;
|
self.config.foreground = fg;
|
||||||
}
|
}
|
||||||
if (state.terminal.modes.reverse_colors) {
|
if (state.terminal.modes.reverse_colors) {
|
||||||
self.background = fg;
|
self.config.background = fg;
|
||||||
self.foreground = bg;
|
self.config.foreground = bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build our devmode draw data
|
// Build our devmode draw data
|
||||||
@ -723,7 +751,7 @@ pub fn render(
|
|||||||
null;
|
null;
|
||||||
|
|
||||||
break :critical .{
|
break :critical .{
|
||||||
.gl_bg = self.background,
|
.gl_bg = self.config.background,
|
||||||
.devmode_data = devmode_data,
|
.devmode_data = devmode_data,
|
||||||
.active_screen = state.terminal.active_screen,
|
.active_screen = state.terminal.active_screen,
|
||||||
.selection = selection,
|
.selection = selection,
|
||||||
@ -944,7 +972,7 @@ fn addCursor(self: *OpenGL, screen: *terminal.Screen) void {
|
|||||||
screen.cursor.x,
|
screen.cursor.x,
|
||||||
);
|
);
|
||||||
|
|
||||||
const color = self.cursor_color orelse terminal.color.RGB{
|
const color = self.config.cursor_color orelse terminal.color.RGB{
|
||||||
.r = 0xFF,
|
.r = 0xFF,
|
||||||
.g = 0xFF,
|
.g = 0xFF,
|
||||||
.b = 0xFF,
|
.b = 0xFF,
|
||||||
@ -1031,8 +1059,8 @@ pub fn updateCell(
|
|||||||
// If we are selected, we use the selection colors
|
// If we are selected, we use the selection colors
|
||||||
if (sel.contains(screen_point)) {
|
if (sel.contains(screen_point)) {
|
||||||
break :colors BgFg{
|
break :colors BgFg{
|
||||||
.bg = self.selection_background orelse self.foreground,
|
.bg = self.config.selection_background orelse self.config.foreground,
|
||||||
.fg = self.selection_foreground orelse self.background,
|
.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
|
// In normal mode, background and fg match the cell. We
|
||||||
// un-optionalize the fg by defaulting to our fg color.
|
// un-optionalize the fg by defaulting to our fg color.
|
||||||
.bg = if (cell.attrs.has_bg) cell.bg else null,
|
.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 .{
|
} else .{
|
||||||
// In inverted mode, the background MUST be set to something
|
// In inverted mode, the background MUST be set to something
|
||||||
// (is never null) so it is either the fg or default fg. The
|
// (is never null) so it is either the fg or default fg. The
|
||||||
// fg is either the bg or default background.
|
// fg is either the bg or default background.
|
||||||
.bg = if (cell.attrs.has_fg) cell.fg else self.foreground,
|
.bg = if (cell.attrs.has_fg) cell.fg else self.config.foreground,
|
||||||
.fg = if (cell.attrs.has_bg) cell.bg else self.background,
|
.fg = if (cell.attrs.has_bg) cell.bg else self.config.background,
|
||||||
};
|
};
|
||||||
break :colors res;
|
break :colors res;
|
||||||
};
|
};
|
||||||
|
@ -5,10 +5,8 @@ const font = @import("../font/main.zig");
|
|||||||
const renderer = @import("../renderer.zig");
|
const renderer = @import("../renderer.zig");
|
||||||
const Config = @import("../config.zig").Config;
|
const Config = @import("../config.zig").Config;
|
||||||
|
|
||||||
/// The app configuration. This must NOT be stored by any termio implementation.
|
/// The derived configuration for this renderer implementation.
|
||||||
/// The memory it points to is NOT stable after the init call so any values
|
config: renderer.Renderer.DerivedConfig,
|
||||||
/// in here must be copied.
|
|
||||||
config: *const Config,
|
|
||||||
|
|
||||||
/// The font group that should be used.
|
/// The font group that should be used.
|
||||||
font_group: *font.GroupCache,
|
font_group: *font.GroupCache,
|
||||||
|
Reference in New Issue
Block a user