aboutsummaryrefslogtreecommitdiff
path: root/vendor/libghostty-vt/src/renderer/opengl/RenderPass.zig
diff options
context:
space:
mode:
authorCan Celik <ogulcancelik@gmail.com>2026-04-04 19:22:04 +0300
committerCan Celik <ogulcancelik@gmail.com>2026-04-05 01:23:06 +0300
commit41dd733ca7123c9ac4bfc6c781697a660e95b052 (patch)
tree3fc91815ca139ef2e0b281bba0abda4ef15175f4 /vendor/libghostty-vt/src/renderer/opengl/RenderPass.zig
parent55c138263e190a1e79d4b997bfb9397306c0ec1f (diff)
feat: finish ghostty pane backend integration
Diffstat (limited to 'vendor/libghostty-vt/src/renderer/opengl/RenderPass.zig')
-rw-r--r--vendor/libghostty-vt/src/renderer/opengl/RenderPass.zig144
1 files changed, 144 insertions, 0 deletions
diff --git a/vendor/libghostty-vt/src/renderer/opengl/RenderPass.zig b/vendor/libghostty-vt/src/renderer/opengl/RenderPass.zig
new file mode 100644
index 00000000..18066494
--- /dev/null
+++ b/vendor/libghostty-vt/src/renderer/opengl/RenderPass.zig
@@ -0,0 +1,144 @@
+//! Wrapper for handling render passes.
+const Self = @This();
+
+const std = @import("std");
+const Allocator = std.mem.Allocator;
+const gl = @import("opengl");
+
+const Sampler = @import("Sampler.zig");
+const Target = @import("Target.zig");
+const Texture = @import("Texture.zig");
+const Pipeline = @import("Pipeline.zig");
+const Buffer = @import("buffer.zig").Buffer;
+
+/// Options for beginning a render pass.
+pub const Options = struct {
+ /// Color attachments for this render pass.
+ attachments: []const Attachment,
+
+ /// Describes a color attachment.
+ pub const Attachment = struct {
+ target: union(enum) {
+ texture: Texture,
+ target: Target,
+ },
+ clear_color: ?[4]f32 = null,
+ };
+};
+
+/// Describes a step in a render pass.
+pub const Step = struct {
+ pipeline: Pipeline,
+ uniforms: ?gl.Buffer = null,
+ buffers: []const ?gl.Buffer = &.{},
+ textures: []const ?Texture = &.{},
+ samplers: []const ?Sampler = &.{},
+ draw: Draw,
+
+ /// Describes the draw call for this step.
+ pub const Draw = struct {
+ type: gl.Primitive,
+ vertex_count: usize,
+ instance_count: usize = 1,
+ };
+};
+
+attachments: []const Options.Attachment,
+
+step_number: usize = 0,
+
+/// Begin a render pass.
+pub fn begin(
+ opts: Options,
+) Self {
+ return .{
+ .attachments = opts.attachments,
+ };
+}
+
+/// Add a step to this render pass.
+///
+/// TODO: Errors are silently ignored in this function, maybe they shouldn't be?
+pub fn step(self: *Self, s: Step) void {
+ if (s.draw.instance_count == 0) return;
+
+ const pbind = s.pipeline.program.use() catch return;
+ defer pbind.unbind();
+
+ const vaobind = s.pipeline.vao.bind() catch return;
+ defer vaobind.unbind();
+
+ const fbobind = switch (self.attachments[0].target) {
+ .target => |t| t.framebuffer.bind(.framebuffer) catch return,
+ .texture => |t| bind: {
+ const fbobind = s.pipeline.fbo.bind(.framebuffer) catch return;
+ fbobind.texture2D(.color0, t.target, t.texture, 0) catch {
+ fbobind.unbind();
+ return;
+ };
+ break :bind fbobind;
+ },
+ };
+ defer fbobind.unbind();
+
+ defer self.step_number += 1;
+
+ // If we have a clear color and this is the
+ // first step in the pass, go ahead and clear.
+ if (self.step_number == 0) if (self.attachments[0].clear_color) |c| {
+ gl.clearColor(c[0], c[1], c[2], c[3]);
+ gl.clear(gl.c.GL_COLOR_BUFFER_BIT);
+ };
+
+ // Bind the uniform buffer we bind at index 1 to align with Metal.
+ if (s.uniforms) |ubo| {
+ _ = ubo.bindBase(.uniform, 1) catch return;
+ }
+
+ // Bind relevant texture units.
+ for (s.textures, 0..) |t, i| if (t) |tex| {
+ gl.Texture.active(@intCast(i)) catch return;
+ _ = tex.texture.bind(tex.target) catch return;
+ };
+
+ // Bind relevant samplers.
+ for (s.samplers, 0..) |s_, i| if (s_) |sampler| {
+ _ = sampler.sampler.bind(@intCast(i)) catch return;
+ };
+
+ // Bind 0th buffer as the vertex buffer,
+ // and bind the rest as storage buffers.
+ if (s.buffers.len > 0) {
+ if (s.buffers[0]) |vbo| vaobind.bindVertexBuffer(
+ 0,
+ vbo.id,
+ 0,
+ @intCast(s.pipeline.stride),
+ ) catch return;
+
+ for (s.buffers[1..], 1..) |b, i| if (b) |buf| {
+ _ = buf.bindBase(.storage, @intCast(i)) catch return;
+ };
+ }
+
+ if (s.pipeline.blending_enabled) {
+ gl.enable(gl.c.GL_BLEND) catch return;
+ gl.blendFunc(gl.c.GL_ONE, gl.c.GL_ONE_MINUS_SRC_ALPHA) catch return;
+ } else {
+ gl.disable(gl.c.GL_BLEND) catch return;
+ }
+
+ gl.drawArraysInstanced(
+ s.draw.type,
+ 0,
+ @intCast(s.draw.vertex_count),
+ @intCast(s.draw.instance_count),
+ ) catch return;
+}
+
+/// Complete this render pass.
+/// This struct can no longer be used after calling this.
+pub fn complete(self: *const Self) void {
+ _ = self;
+ gl.flush();
+}