diff --git a/build.zig b/build.zig index ce870e27c..24a58d14c 100644 --- a/build.zig +++ b/build.zig @@ -83,6 +83,11 @@ pub fn build(b: *std.build.Builder) !void { // Exe { + if (target.isDarwin()) { + // See the comment in this file + exe.addCSourceFile("src/renderer/metal_workaround.c", &.{}); + } + exe.setTarget(target); exe.setBuildMode(mode); exe.addOptions("build_options", exe_options); diff --git a/src/renderer/Metal.zig b/src/renderer/Metal.zig index 5321729c3..21b68726c 100644 --- a/src/renderer/Metal.zig +++ b/src/renderer/Metal.zig @@ -963,25 +963,55 @@ fn syncAtlasTexture(device: objc.Object, atlas: *const Atlas, texture: *objc.Obj texture.* = try initAtlasTexture(device, atlas); } - texture.msgSend( - void, - objc.sel("replaceRegion:mipmapLevel:withBytes:bytesPerRow:"), - .{ - MTLRegion{ - .origin = .{ .x = 0, .y = 0, .z = 0 }, - .size = .{ - .width = @intCast(c_ulong, atlas.size), - .height = @intCast(c_ulong, atlas.size), - .depth = 1, - }, + // Workaround for: https://github.com/ziglang/zig/issues/13598 + ghostty_metal_replaceregion( + texture.value, + objc.sel("replaceRegion:mipmapLevel:withBytes:bytesPerRow:").value, + MTLRegion{ + .origin = .{ .x = 0, .y = 0, .z = 0 }, + .size = .{ + .width = @intCast(c_ulong, atlas.size), + .height = @intCast(c_ulong, atlas.size), + .depth = 1, }, - @as(c_ulong, 0), - atlas.data.ptr, - @as(c_ulong, atlas.format.depth() * atlas.size), }, + @as(c_ulong, 0), + atlas.data.ptr, + @as(c_ulong, atlas.format.depth() * atlas.size), ); + + // Once the above linked issue is fixed, this is what we actually + // want to do: + // + // texture.msgSend( + // void, + // objc.sel("replaceRegion:mipmapLevel:withBytes:bytesPerRow:"), + // .{ + // MTLRegion{ + // .origin = .{ .x = 0, .y = 0, .z = 0 }, + // .size = .{ + // .width = @intCast(c_ulong, atlas.size), + // .height = @intCast(c_ulong, atlas.size), + // .depth = 1, + // }, + // }, + // @as(c_ulong, 0), + // atlas.data.ptr, + // @as(c_ulong, atlas.format.depth() * atlas.size), + // }, + // ); + } +extern "c" fn ghostty_metal_replaceregion( + objc.c.id, + objc.c.SEL, + MTLRegion, + c_ulong, + *anyopaque, + c_ulong, +) void; + /// Initialize the shader library. fn initLibrary(device: objc.Object, data: []const u8) !objc.Object { const source = try macos.foundation.String.createWithBytes( diff --git a/src/renderer/metal_workaround.c b/src/renderer/metal_workaround.c new file mode 100644 index 000000000..018fbe61b --- /dev/null +++ b/src/renderer/metal_workaround.c @@ -0,0 +1,35 @@ +// Workaround for: +// https://github.com/ziglang/zig/issues/13598 + +#include +#include + +// From Metal.h +typedef struct Origin { + unsigned long x; + unsigned long y; + unsigned long z; +} Origin; + +typedef struct Size { + unsigned long width; + unsigned long height; + unsigned long depth; +} Size; + +typedef struct MTLRegion { + Origin origin; + Size size; +} MTLRegion; + +void ghostty_metal_replaceregion( + id target, + SEL sel, + MTLRegion region, + unsigned long offset, + void *ptr, + unsigned long len +) { + void (*replaceRegion)(id, SEL, MTLRegion, unsigned long, void *, unsigned long) = (void (*)(id, SEL, MTLRegion, unsigned long, void *, unsigned long)) objc_msgSend; + replaceRegion(target, sel, region, offset, ptr, len); +}