mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 00:06:09 +03:00
Initial metal abstraction (noop)
This commit is contained in:
@ -36,7 +36,7 @@ const log = std.log.scoped(.window);
|
||||
const WRITE_REQ_PREALLOC = std.math.pow(usize, 2, 5);
|
||||
|
||||
// The renderer implementation to use.
|
||||
const Renderer = renderer.OpenGL;
|
||||
const Renderer = renderer.Renderer;
|
||||
|
||||
/// Allocator
|
||||
alloc: Allocator,
|
||||
|
@ -7,11 +7,21 @@
|
||||
//! APIs. The renderers in this package assume that the renderer is already
|
||||
//! setup (OpenGL has a context, Vulkan has a surface, etc.)
|
||||
|
||||
const builtin = @import("builtin");
|
||||
|
||||
pub usingnamespace @import("renderer/size.zig");
|
||||
pub const Metal = @import("renderer/Metal.zig");
|
||||
pub const OpenGL = @import("renderer/OpenGL.zig");
|
||||
pub const Thread = @import("renderer/Thread.zig");
|
||||
pub const State = @import("renderer/State.zig");
|
||||
|
||||
/// The implementation to use for the renderer. This is comptime chosen
|
||||
/// so that every build has exactly one renderer implementation.
|
||||
pub const Renderer = switch (builtin.os.tag) {
|
||||
.macos => Metal,
|
||||
else => OpenGL,
|
||||
};
|
||||
|
||||
test {
|
||||
@import("std").testing.refAllDecls(@This());
|
||||
}
|
||||
|
86
src/renderer/Metal.zig
Normal file
86
src/renderer/Metal.zig
Normal file
@ -0,0 +1,86 @@
|
||||
//! Renderer implementation for Metal.
|
||||
pub const Metal = @This();
|
||||
|
||||
const std = @import("std");
|
||||
const glfw = @import("glfw");
|
||||
const font = @import("../font/main.zig");
|
||||
const terminal = @import("../terminal/main.zig");
|
||||
const renderer = @import("../renderer.zig");
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const log = std.log.scoped(.metal);
|
||||
|
||||
/// Current cell dimensions for this grid.
|
||||
cell_size: renderer.CellSize,
|
||||
|
||||
/// Default foreground color
|
||||
foreground: terminal.color.RGB,
|
||||
|
||||
/// Default background color
|
||||
background: terminal.color.RGB,
|
||||
|
||||
/// Returns the hints that we want for this
|
||||
pub fn windowHints() glfw.Window.Hints {
|
||||
return .{
|
||||
.client_api = .no_api,
|
||||
// .cocoa_graphics_switching = builtin.os.tag == .macos,
|
||||
// .cocoa_retina_framebuffer = true,
|
||||
};
|
||||
}
|
||||
|
||||
/// This is called early right after window creation to setup our
|
||||
/// window surface as necessary.
|
||||
pub fn windowInit(window: glfw.Window) !void {
|
||||
_ = window;
|
||||
}
|
||||
|
||||
pub fn init(alloc: Allocator, font_group: *font.GroupCache) !Metal {
|
||||
// Get our cell metrics based on a regular font ascii 'M'. Why 'M'?
|
||||
// Doesn't matter, any normal ASCII will do we're just trying to make
|
||||
// sure we use the regular font.
|
||||
const metrics = metrics: {
|
||||
const index = (try font_group.indexForCodepoint(alloc, 'M', .regular, .text)).?;
|
||||
const face = try font_group.group.faceFromIndex(index);
|
||||
break :metrics face.metrics;
|
||||
};
|
||||
log.debug("cell dimensions={}", .{metrics});
|
||||
|
||||
return Metal{
|
||||
.cell_size = .{ .width = metrics.cell_width, .height = metrics.cell_height },
|
||||
.background = .{ .r = 0, .g = 0, .b = 0 },
|
||||
.foreground = .{ .r = 255, .g = 255, .b = 255 },
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Metal) void {
|
||||
self.* = undefined;
|
||||
}
|
||||
|
||||
/// This is called just prior to spinning up the renderer thread for
|
||||
/// final main thread setup requirements.
|
||||
pub fn finalizeInit(self: *const Metal, window: glfw.Window) !void {
|
||||
_ = self;
|
||||
_ = window;
|
||||
}
|
||||
|
||||
/// Callback called by renderer.Thread when it begins.
|
||||
pub fn threadEnter(self: *const Metal, window: glfw.Window) !void {
|
||||
_ = self;
|
||||
_ = window;
|
||||
}
|
||||
|
||||
/// Callback called by renderer.Thread when it exits.
|
||||
pub fn threadExit(self: *const Metal) void {
|
||||
_ = self;
|
||||
}
|
||||
|
||||
/// The primary render callback that is completely thread-safe.
|
||||
pub fn render(
|
||||
self: *Metal,
|
||||
window: glfw.Window,
|
||||
state: *renderer.State,
|
||||
) !void {
|
||||
_ = self;
|
||||
_ = window;
|
||||
_ = state;
|
||||
}
|
@ -31,7 +31,7 @@ render_h: libuv.Timer,
|
||||
window: glfw.Window,
|
||||
|
||||
/// The underlying renderer implementation.
|
||||
renderer: *renderer.OpenGL,
|
||||
renderer: *renderer.Renderer,
|
||||
|
||||
/// Pointer to the shared state that is used to generate the final render.
|
||||
state: *renderer.State,
|
||||
@ -42,7 +42,7 @@ state: *renderer.State,
|
||||
pub fn init(
|
||||
alloc: Allocator,
|
||||
window: glfw.Window,
|
||||
renderer_impl: *renderer.OpenGL,
|
||||
renderer_impl: *renderer.Renderer,
|
||||
state: *renderer.State,
|
||||
) !Thread {
|
||||
// We always store allocator pointer on the loop data so that
|
||||
@ -143,16 +143,11 @@ pub fn threadMain(self: *Thread) void {
|
||||
}
|
||||
|
||||
fn threadMain_(self: *Thread) !void {
|
||||
// Get a copy to our allocator
|
||||
// const alloc_ptr = self.loop.getData(Allocator).?;
|
||||
// const alloc = alloc_ptr.*;
|
||||
|
||||
// Run our thread start/end callbacks. This is important because some
|
||||
// renderers have to do per-thread setup. For example, OpenGL has to set
|
||||
// some thread-local state since that is how it works.
|
||||
const Renderer = RendererType();
|
||||
if (@hasDecl(Renderer, "threadEnter")) try self.renderer.threadEnter(self.window);
|
||||
defer if (@hasDecl(Renderer, "threadExit")) self.renderer.threadExit();
|
||||
try self.renderer.threadEnter(self.window);
|
||||
defer self.renderer.threadExit();
|
||||
|
||||
// Set up our async handler to support rendering
|
||||
self.wakeup.setData(self);
|
||||
@ -199,14 +194,3 @@ fn renderCallback(h: *libuv.Timer) void {
|
||||
fn stopCallback(h: *libuv.Async) void {
|
||||
h.loop().stop();
|
||||
}
|
||||
|
||||
// This is unnecessary right now but is logic we'll need for when we
|
||||
// abstract renderers out.
|
||||
fn RendererType() type {
|
||||
const self: Thread = undefined;
|
||||
return switch (@typeInfo(@TypeOf(self.renderer))) {
|
||||
.Pointer => |p| p.child,
|
||||
.Struct => |s| s,
|
||||
else => unreachable,
|
||||
};
|
||||
}
|
||||
|
Reference in New Issue
Block a user