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);
|
const WRITE_REQ_PREALLOC = std.math.pow(usize, 2, 5);
|
||||||
|
|
||||||
// The renderer implementation to use.
|
// The renderer implementation to use.
|
||||||
const Renderer = renderer.OpenGL;
|
const Renderer = renderer.Renderer;
|
||||||
|
|
||||||
/// Allocator
|
/// Allocator
|
||||||
alloc: Allocator,
|
alloc: Allocator,
|
||||||
|
@ -7,11 +7,21 @@
|
|||||||
//! APIs. The renderers in this package assume that the renderer is already
|
//! APIs. The renderers in this package assume that the renderer is already
|
||||||
//! setup (OpenGL has a context, Vulkan has a surface, etc.)
|
//! setup (OpenGL has a context, Vulkan has a surface, etc.)
|
||||||
|
|
||||||
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
pub usingnamespace @import("renderer/size.zig");
|
pub usingnamespace @import("renderer/size.zig");
|
||||||
|
pub const Metal = @import("renderer/Metal.zig");
|
||||||
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");
|
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 {
|
test {
|
||||||
@import("std").testing.refAllDecls(@This());
|
@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,
|
window: glfw.Window,
|
||||||
|
|
||||||
/// The underlying renderer implementation.
|
/// The underlying renderer implementation.
|
||||||
renderer: *renderer.OpenGL,
|
renderer: *renderer.Renderer,
|
||||||
|
|
||||||
/// Pointer to the shared state that is used to generate the final render.
|
/// Pointer to the shared state that is used to generate the final render.
|
||||||
state: *renderer.State,
|
state: *renderer.State,
|
||||||
@ -42,7 +42,7 @@ state: *renderer.State,
|
|||||||
pub fn init(
|
pub fn init(
|
||||||
alloc: Allocator,
|
alloc: Allocator,
|
||||||
window: glfw.Window,
|
window: glfw.Window,
|
||||||
renderer_impl: *renderer.OpenGL,
|
renderer_impl: *renderer.Renderer,
|
||||||
state: *renderer.State,
|
state: *renderer.State,
|
||||||
) !Thread {
|
) !Thread {
|
||||||
// We always store allocator pointer on the loop data so that
|
// 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 {
|
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
|
// Run our thread start/end callbacks. This is important because some
|
||||||
// renderers have to do per-thread setup. For example, OpenGL has to set
|
// renderers have to do per-thread setup. For example, OpenGL has to set
|
||||||
// some thread-local state since that is how it works.
|
// some thread-local state since that is how it works.
|
||||||
const Renderer = RendererType();
|
try self.renderer.threadEnter(self.window);
|
||||||
if (@hasDecl(Renderer, "threadEnter")) try self.renderer.threadEnter(self.window);
|
defer self.renderer.threadExit();
|
||||||
defer if (@hasDecl(Renderer, "threadExit")) self.renderer.threadExit();
|
|
||||||
|
|
||||||
// Set up our async handler to support rendering
|
// Set up our async handler to support rendering
|
||||||
self.wakeup.setData(self);
|
self.wakeup.setData(self);
|
||||||
@ -199,14 +194,3 @@ fn renderCallback(h: *libuv.Timer) void {
|
|||||||
fn stopCallback(h: *libuv.Async) void {
|
fn stopCallback(h: *libuv.Async) void {
|
||||||
h.loop().stop();
|
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