mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 00:06:09 +03:00
prepare our render state on the window
This commit is contained in:
@ -56,6 +56,9 @@ focused: bool,
|
|||||||
/// The renderer for this window.
|
/// The renderer for this window.
|
||||||
renderer: renderer.OpenGL,
|
renderer: renderer.OpenGL,
|
||||||
|
|
||||||
|
/// The render state
|
||||||
|
renderer_state: renderer.State,
|
||||||
|
|
||||||
/// The underlying pty for this window.
|
/// The underlying pty for this window.
|
||||||
pty: Pty,
|
pty: Pty,
|
||||||
|
|
||||||
@ -455,6 +458,10 @@ pub fn create(alloc: Allocator, loop: libuv.Loop, config: *const Config) !*Windo
|
|||||||
var io_arena = std.heap.ArenaAllocator.init(alloc);
|
var io_arena = std.heap.ArenaAllocator.init(alloc);
|
||||||
errdefer io_arena.deinit();
|
errdefer io_arena.deinit();
|
||||||
|
|
||||||
|
// The mutex used to protect our renderer state.
|
||||||
|
var mutex = try alloc.create(std.Thread.Mutex);
|
||||||
|
errdefer alloc.destroy(mutex);
|
||||||
|
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.alloc = alloc,
|
.alloc = alloc,
|
||||||
.alloc_io_arena = io_arena,
|
.alloc_io_arena = io_arena,
|
||||||
@ -464,6 +471,16 @@ pub fn create(alloc: Allocator, loop: libuv.Loop, config: *const Config) !*Windo
|
|||||||
.cursor = cursor,
|
.cursor = cursor,
|
||||||
.focused = false,
|
.focused = false,
|
||||||
.renderer = renderer_impl,
|
.renderer = renderer_impl,
|
||||||
|
.renderer_state = .{
|
||||||
|
.mutex = mutex,
|
||||||
|
.cursor = .{
|
||||||
|
.style = .blinking_block,
|
||||||
|
.visible = true,
|
||||||
|
.blink = false,
|
||||||
|
},
|
||||||
|
.terminal = &self.terminal,
|
||||||
|
.devmode = if (!DevMode.enabled) null else &DevMode.instance,
|
||||||
|
},
|
||||||
.pty = pty,
|
.pty = pty,
|
||||||
.command = cmd,
|
.command = cmd,
|
||||||
.mouse = .{},
|
.mouse = .{},
|
||||||
@ -591,6 +608,7 @@ pub fn destroy(self: *Window) void {
|
|||||||
self.font_lib.deinit();
|
self.font_lib.deinit();
|
||||||
|
|
||||||
self.alloc_io_arena.deinit();
|
self.alloc_io_arena.deinit();
|
||||||
|
self.alloc.destroy(self.renderer_state.mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shouldClose(self: Window) bool {
|
pub fn shouldClose(self: Window) bool {
|
||||||
@ -1632,7 +1650,7 @@ fn renderTimerCallback(t: *libuv.Timer) void {
|
|||||||
log.err("error calling updateCells in render timer err={}", .{err});
|
log.err("error calling updateCells in render timer err={}", .{err});
|
||||||
|
|
||||||
// Render the grid
|
// Render the grid
|
||||||
win.renderer.render() catch |err| {
|
win.renderer.draw() catch |err| {
|
||||||
log.err("error rendering grid: {}", .{err});
|
log.err("error rendering grid: {}", .{err});
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
pub const OpenGL = @import("renderer/OpenGL.zig");
|
pub const OpenGL = @import("renderer/OpenGL.zig");
|
||||||
pub const Thread = @import("renderer/Thread.zig");
|
pub const Thread = @import("renderer/Thread.zig");
|
||||||
|
pub const State = @import("renderer/State.zig");
|
||||||
|
|
||||||
test {
|
test {
|
||||||
@import("std").testing.refAllDecls(@This());
|
@import("std").testing.refAllDecls(@This());
|
||||||
|
@ -9,6 +9,8 @@ const testing = std.testing;
|
|||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const Atlas = @import("../Atlas.zig");
|
const Atlas = @import("../Atlas.zig");
|
||||||
const font = @import("../font/main.zig");
|
const font = @import("../font/main.zig");
|
||||||
|
const imgui = @import("imgui");
|
||||||
|
const renderer = @import("../renderer.zig");
|
||||||
const terminal = @import("../terminal/main.zig");
|
const terminal = @import("../terminal/main.zig");
|
||||||
const Terminal = terminal.Terminal;
|
const Terminal = terminal.Terminal;
|
||||||
const gl = @import("../opengl.zig");
|
const gl = @import("../opengl.zig");
|
||||||
@ -353,6 +355,62 @@ pub fn threadExit() void {
|
|||||||
glfw.makeContextCurrent(null) catch {};
|
glfw.makeContextCurrent(null) catch {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The primary render callback that is completely thread-safe.
|
||||||
|
pub fn render(
|
||||||
|
self: *OpenGL,
|
||||||
|
window: glfw.Window,
|
||||||
|
state: renderer.State,
|
||||||
|
) !void {
|
||||||
|
// Update all our data as tightly as possible within the mutex.
|
||||||
|
var gl_bg = self.background;
|
||||||
|
{
|
||||||
|
state.mutex.lock();
|
||||||
|
defer state.mutex.unlock();
|
||||||
|
|
||||||
|
// Setup our cursor state
|
||||||
|
self.cursor_visible = state.cursor.visible and !state.cursor.blink;
|
||||||
|
self.cursor_style = CursorStyle.fromTerminal(state.cursor.style) orelse .box;
|
||||||
|
|
||||||
|
// Swap bg/fg if the terminal is reversed
|
||||||
|
const bg = self.background;
|
||||||
|
const fg = self.foreground;
|
||||||
|
defer {
|
||||||
|
self.background = bg;
|
||||||
|
self.foreground = fg;
|
||||||
|
}
|
||||||
|
if (state.terminal.modes.reverse_colors) {
|
||||||
|
gl_bg = fg;
|
||||||
|
self.background = fg;
|
||||||
|
self.foreground = bg;
|
||||||
|
}
|
||||||
|
|
||||||
|
try self.rebuildCells(state.terminal);
|
||||||
|
try self.finalizeCells(state.terminal);
|
||||||
|
if (state.devmode) |dm| try dm.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the surface
|
||||||
|
gl.clearColor(
|
||||||
|
@intToFloat(f32, self.background.r) / 255,
|
||||||
|
@intToFloat(f32, self.background.g) / 255,
|
||||||
|
@intToFloat(f32, self.background.b) / 255,
|
||||||
|
1.0,
|
||||||
|
);
|
||||||
|
gl.clear(gl.c.GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
// We're out of the critical path now. Let's first render our terminal.
|
||||||
|
try self.draw();
|
||||||
|
|
||||||
|
// If we have devmode, then render that
|
||||||
|
if (state.devmode) |dm| {
|
||||||
|
const data = try dm.render();
|
||||||
|
imgui.ImplOpenGL3.renderDrawData(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swap our window buffers
|
||||||
|
try window.swapBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
/// rebuildCells rebuilds all the GPU cells from our CPU state. This is a
|
/// rebuildCells rebuilds all the GPU cells from our CPU state. This is a
|
||||||
/// slow operation but ensures that the GPU state exactly matches the CPU state.
|
/// slow operation but ensures that the GPU state exactly matches the CPU state.
|
||||||
/// In steady-state operation, we use some GPU tricks to send down stale data
|
/// In steady-state operation, we use some GPU tricks to send down stale data
|
||||||
@ -830,7 +888,7 @@ fn flushAtlas(self: *OpenGL) !void {
|
|||||||
|
|
||||||
/// Render renders the current cell state. This will not modify any of
|
/// Render renders the current cell state. This will not modify any of
|
||||||
/// the cells.
|
/// the cells.
|
||||||
pub fn render(self: *OpenGL) !void {
|
pub fn draw(self: *OpenGL) !void {
|
||||||
const t = trace(@src());
|
const t = trace(@src());
|
||||||
defer t.end();
|
defer t.end();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user