mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-09-19 20:18:07 +00:00
This migrates all remaining uses of cImport (and addTranslateC for good measure) to using translate-c for C translation, ensuring that we are ready for when cImport is removed from the language, and also that all sources of C translation are using the same snapshot of the external package (when can then be updated when we need to fix something). A couple of notes: * A few options have been added to support the new translations, namely the ability to link libraries (passed through to linkLibrary on the Translator side) and whether or not to initialize default values (looks like cImport did this without a way to control it, but translate-c does not do it by default). * Using the new library linking option actually simplifies the process of translating a number of the C packages as we have been shipping the necessary headers for these packages already with the applicable libraries. For some of the more complex translation processes though, we still include the appropriate directories directly.
138 lines
3.7 KiB
Zig
138 lines
3.7 KiB
Zig
const Program = @This();
|
|
|
|
const std = @import("std");
|
|
const assert = std.debug.assert;
|
|
const log = std.log.scoped(.opengl);
|
|
|
|
const c = @import("opengl_c");
|
|
const Shader = @import("Shader.zig");
|
|
const errors = @import("errors.zig");
|
|
const glad = @import("glad.zig");
|
|
|
|
id: c.GLuint,
|
|
|
|
pub const Binding = struct {
|
|
pub fn unbind(_: Binding) void {
|
|
glad.context.UseProgram.?(0);
|
|
}
|
|
};
|
|
|
|
pub fn create() !Program {
|
|
const id = glad.context.CreateProgram.?();
|
|
if (id == 0) try errors.mustError();
|
|
log.debug("program created id={}", .{id});
|
|
return .{ .id = id };
|
|
}
|
|
|
|
/// Create a program from a vertex and fragment shader source. This will
|
|
/// compile and link the vertex and fragment shader.
|
|
pub fn createVF(vsrc: [:0]const u8, fsrc: [:0]const u8) !Program {
|
|
const vs = try Shader.create(c.GL_VERTEX_SHADER);
|
|
try vs.setSourceAndCompile(vsrc);
|
|
defer vs.destroy();
|
|
|
|
const fs = try Shader.create(c.GL_FRAGMENT_SHADER);
|
|
try fs.setSourceAndCompile(fsrc);
|
|
defer fs.destroy();
|
|
|
|
const p = try create();
|
|
try p.attachShader(vs);
|
|
try p.attachShader(fs);
|
|
try p.link();
|
|
|
|
return p;
|
|
}
|
|
|
|
pub fn destroy(p: Program) void {
|
|
assert(p.id != 0);
|
|
glad.context.DeleteProgram.?(p.id);
|
|
log.debug("program destroyed id={}", .{p.id});
|
|
}
|
|
|
|
pub fn attachShader(p: Program, s: Shader) !void {
|
|
glad.context.AttachShader.?(p.id, s.id);
|
|
try errors.getError();
|
|
}
|
|
|
|
pub fn link(p: Program) !void {
|
|
glad.context.LinkProgram.?(p.id);
|
|
|
|
// Check if linking succeeded
|
|
var success: c_int = undefined;
|
|
glad.context.GetProgramiv.?(p.id, c.GL_LINK_STATUS, &success);
|
|
if (success == c.GL_TRUE) {
|
|
log.debug("program linked id={}", .{p.id});
|
|
return;
|
|
}
|
|
|
|
log.err("program link failure id={} message={s}", .{
|
|
p.id,
|
|
std.mem.sliceTo(&p.getInfoLog(), 0),
|
|
});
|
|
return error.CompileFailed;
|
|
}
|
|
|
|
pub fn use(p: Program) !Binding {
|
|
glad.context.UseProgram.?(p.id);
|
|
try errors.getError();
|
|
return .{};
|
|
}
|
|
|
|
pub fn uniformBlockBinding(
|
|
self: Program,
|
|
index: c.GLuint,
|
|
binding: c.GLuint,
|
|
) !void {
|
|
glad.context.UniformBlockBinding.?(self.id, index, binding);
|
|
try errors.getError();
|
|
}
|
|
|
|
/// Requires the program is currently in use.
|
|
pub fn setUniform(
|
|
p: Program,
|
|
n: [:0]const u8,
|
|
value: anytype,
|
|
) !void {
|
|
const loc = glad.context.GetUniformLocation.?(
|
|
p.id,
|
|
@ptrCast(n.ptr),
|
|
);
|
|
if (loc < 0) {
|
|
return error.UniformNameInvalid;
|
|
}
|
|
try errors.getError();
|
|
|
|
// Perform the correct call depending on the type of the value.
|
|
switch (@TypeOf(value)) {
|
|
bool => glad.context.Uniform1i.?(loc, if (value) 1 else 0),
|
|
comptime_int => glad.context.Uniform1i.?(loc, value),
|
|
f32 => glad.context.Uniform1f.?(loc, value),
|
|
@Vector(2, f32) => glad.context.Uniform2f.?(loc, value[0], value[1]),
|
|
@Vector(3, f32) => glad.context.Uniform3f.?(loc, value[0], value[1], value[2]),
|
|
@Vector(4, f32) => glad.context.Uniform4f.?(loc, value[0], value[1], value[2], value[3]),
|
|
[4]@Vector(4, f32) => glad.context.UniformMatrix4fv.?(
|
|
loc,
|
|
1,
|
|
c.GL_FALSE,
|
|
@ptrCast(&value),
|
|
),
|
|
else => {
|
|
log.warn("unsupported uniform type {}", .{@TypeOf(value)});
|
|
unreachable;
|
|
},
|
|
}
|
|
try errors.getError();
|
|
}
|
|
|
|
/// getInfoLog returns the info log for this program. This attempts to
|
|
/// keep the log fully stack allocated and is therefore limited to a max
|
|
/// amount of elements.
|
|
//
|
|
// NOTE(mitchellh): we can add a dynamic version that uses an allocator
|
|
// if we ever need it.
|
|
pub fn getInfoLog(s: Program) [512]u8 {
|
|
var msg: [512]u8 = undefined;
|
|
glad.context.GetProgramInfoLog.?(s.id, msg.len, null, &msg);
|
|
return msg;
|
|
}
|