aboutsummaryrefslogtreecommitdiffstats
path: root/src/tsv.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/tsv.zig')
-rw-r--r--src/tsv.zig103
1 files changed, 91 insertions, 12 deletions
diff --git a/src/tsv.zig b/src/tsv.zig
index 9f15f2f..33c8c92 100644
--- a/src/tsv.zig
+++ b/src/tsv.zig
@@ -1,8 +1,96 @@
const std = @import("std");
const c = @import("c.zig");
const gl = @import("gl.zig");
+const Source = gl.Source;
const Output = @import("output.zig").Output;
+var global_client: ?*c.GlClient = null;
+
+fn get_or_init_client() *c.GlClient {
+ if (global_client == null) {
+ _ = c.gl_client_initialize_external_gl();
+ global_client = c.gl_client_new_with_server_launch(
+ c.VK_SERVER_DEFAULT_SOCKET_PATH,
+ 1000,
+ c.VK_SERVER_EXECUTABLE,
+ c.VK_SERVER_DEFAULT_LOCKFILE_PATH,
+ c.VK_SERVER_DEFAULT_SOCKET_PATH,
+ c.VK_SERVER_DEFAULT_SHMEM_PREFIX,
+ 2000,
+ 2000,
+ 2000,
+ 2000,
+ 2000,
+ ) orelse unreachable;
+ }
+
+ return global_client.?;
+}
+
+pub const TSVSource = struct {
+ source: gl.Source,
+ name: [:0]const u8,
+
+ pub fn init(
+ allocator: std.mem.Allocator,
+ name: [*:0]const u8,
+ texture_type: gl.Texture.Type,
+ ) !*gl.Source {
+ const self = try allocator.create(TSVSource);
+ errdefer allocator.destroy(self);
+
+ self.* = .{
+ .source = .{
+ .texture = gl.Texture.create(texture_type),
+
+ .update_fn = update,
+ .deinit_fn = deinit,
+ },
+ .name = try allocator.dupeZ(u8, std.mem.span(name)),
+ };
+ errdefer allocator.free(self.name);
+
+ const guard = c.gl_client_find_image_data(get_or_init_client(), name, false) orelse return error.notFound;
+ defer c.gl_client_image_data_guard_destroy(guard);
+
+ const metadata = c.gl_client_image_data_guard_read(guard) orelse return error.tsvError;
+ self.source.texture.allocate(
+ @intCast(metadata.*.width),
+ @intCast(metadata.*.height),
+ 0,
+ c.GL_RGBA8,
+ );
+
+ self.source.update();
+
+ return &self.source;
+ }
+
+ fn deinit(source: *const gl.Source, allocator: std.mem.Allocator) void {
+ const self: *const TSVSource = @fieldParentPtr("source", source);
+
+ allocator.free(self.name);
+ allocator.destroy(self);
+ }
+
+ fn update(source: *const gl.Source) void {
+ const self: *const TSVSource = @fieldParentPtr("source", source);
+
+ var fbo: c.GLint = undefined;
+ c.glGetIntegerv(c.GL_DRAW_FRAMEBUFFER_BINDING, &fbo);
+
+ _ = c.gl_client_recv_image(
+ get_or_init_client(),
+ self.name.ptr,
+ self.source.texture.id,
+ @intFromEnum(self.source.texture.type),
+ false,
+ @intCast(fbo),
+ null,
+ );
+ }
+};
+
pub const TSVOutput = struct {
pub const Config = struct {
name: [:0]const u8,
@@ -18,23 +106,16 @@ pub const TSVOutput = struct {
) *Output {
const self = allocator.create(TSVOutput) catch unreachable;
- _ = c.gl_client_initialize_external_gl() or unreachable;
-
self.* = .{
.output = .{
.update_fn = update,
.destroy_fn = destroy,
},
.config = config,
- .client = c.gl_client_new(c.VK_SERVER_DEFAULT_SOCKET_PATH, 1000) orelse unreachable,
- .image_size = .{
- .top_left = .{ 0, 0 },
- .bottom_right = .{ constants.config.width, constants.config.height },
- },
};
_ = c.gl_client_init_image(
- self.client,
+ get_or_init_client(),
config.name,
@intCast(constants.config.width),
@intCast(constants.config.height),
@@ -48,8 +129,6 @@ pub const TSVOutput = struct {
output: Output,
config: *const Config,
- client: *c.GlClient,
- image_size: c.GlImageExtent,
fn update(output: *Output, texture_id: c.GLuint) bool {
const self: *TSVOutput = @fieldParentPtr("output", output);
@@ -58,13 +137,13 @@ pub const TSVOutput = struct {
c.glGetIntegerv(c.GL_DRAW_FRAMEBUFFER_BINDING, &fbo);
_ = c.gl_client_send_image(
- self.client,
+ get_or_init_client(),
self.config.name,
texture_id,
c.GL_TEXTURE_2D,
false,
@intCast(fbo),
- &self.image_size,
+ null,
);
return false;
}