diff options
Diffstat (limited to '')
| -rw-r--r-- | src/config.zig | 27 | ||||
| -rw-r--r-- | src/main.zig | 56 | ||||
| -rw-r--r-- | src/output.zig | 67 | ||||
| -rw-r--r-- | src/tsv.zig | 34 |
4 files changed, 128 insertions, 56 deletions
diff --git a/src/config.zig b/src/config.zig index f1410d4..795c564 100644 --- a/src/config.zig +++ b/src/config.zig @@ -5,6 +5,7 @@ const build_config = @import("build_config"); pub const OutputConfig = union(enum) { window: out.WindowOutput.Config, + stdout: out.StdoutOutput.Config, texture_share_vk: if (build_config.have_tsv) @import("tsv.zig").TSVOutput.Config else void, const default: OutputConfig = .{ .window = .default }; @@ -41,6 +42,8 @@ pub const Config = struct { _ = it.skip(); + var outputs = std.ArrayList(OutputConfig).empty; + while (it.next()) |arg| { if (std.mem.eql(u8, arg, "--width")) { config.width = try parseInt(&it, i32); @@ -48,23 +51,27 @@ pub const Config = struct { config.height = try parseInt(&it, i32); } else if (std.mem.eql(u8, arg, "--osc")) { config.osc = try parseString(&it, allocator); + } else if (std.mem.eql(u8, arg, "--window")) { + var window: OutputConfig = .{ .window = .default }; + window.window.width = config.width; + window.window.height = config.height; + try outputs.append(allocator, window); + } else if (std.mem.eql(u8, arg, "--stdout")) { + try outputs.append(allocator, .{ .stdout = .default }); } else { return error.invalidArgument; } - // @TODO: output config } - if (config.outputs.len == 0) { - const num = 1; - const outputs = try allocator.alloc(OutputConfig, num); - for (0..num) |i| { - outputs[i] = .{ .window = .default }; - outputs[i].window.width = config.width; - outputs[i].window.height = config.height; - } - config.outputs = outputs; + if (outputs.items.len == 0) { + var window: OutputConfig = .{ .window = .default }; + window.window.width = config.width; + window.window.height = config.height; + try outputs.append(allocator, window); } + config.outputs = try outputs.toOwnedSlice(allocator); + return config; } }; diff --git a/src/main.zig b/src/main.zig index 9b09945..0bf4cfc 100644 --- a/src/main.zig +++ b/src/main.zig @@ -120,14 +120,6 @@ pub fn main() !void { var loops: u8 = 0; - const stdout = std.fs.File.stdout(); - var tex_buffer: ?[]u8 = null; - - if (!stdout.isTty()) { - tex_buffer = try allocator.alloc(u8, @intCast(config.width * config.height * 4)); - } - defer if (tex_buffer) |buf| allocator.free(buf); - while (c.glfwWindowShouldClose(window) == c.GL_FALSE) { c.glfwMakeContextCurrent(window); @@ -145,24 +137,20 @@ pub fn main() !void { // control.reload_requested = false; // } - if (control.dirty) { + const is_fresh = if (control.dirty) blk: { c.glFinish(); var timer = try std.time.Timer.start(); - fbo.bind(); - c.glClear(c.GL_COLOR_BUFFER_BIT); + { + fbo.bind(); + defer fbo.unbind(); - main_program.bind(); - constants.normalized_quad.draw(); + c.glClear(c.GL_COLOR_BUFFER_BIT); - if (tex_buffer) |buf| { - fbo.read(config.width, config.height, buf); - std.debug.print("writing {} bytes\n", .{buf.len}); - _ = try stdout.write(buf); + main_program.bind(); + constants.normalized_quad.draw(); } - fbo.unbind(); - c.glFinish(); const fps = timer.read(); // ns loops = (loops + 1) % 64; @@ -171,18 +159,36 @@ pub fn main() !void { } control.dirty = false; - } + break :blk true; + } else false; + + var keep_running = false; + var i: usize = outputs.items.len; + while (i > 0) { + i -= 1; + const output = outputs.items[i]; + + var close_output = false; + if (output.update(fbo, is_fresh)) |res| { + if (res) |close| { + if (close) { + close_output = true; + } else { + keep_running = true; + } + } + } else |err| { + std.debug.print("Output {} closing due to error: {}\n", .{ output, err }); + close_output = true; + } - for (outputs.items, 0..) |output, i| { - const close = output.update(fbo.texture_id); - if (close) { + if (close_output) { const removed = outputs.swapRemove(i); removed.destroy(cfg_allocator); - break; } } - if (outputs.items.len == 0) + if (!keep_running) break; c.glfwMakeContextCurrent(window); diff --git a/src/output.zig b/src/output.zig index d15c0d4..e9785d2 100644 --- a/src/output.zig +++ b/src/output.zig @@ -5,7 +5,7 @@ const cfg = @import("config.zig"); const gl = @import("gl.zig"); pub const Output = struct { - update_fn: *const fn (output: *Output, texture_id: c.GLuint) bool, + update_fn: *const fn (output: *Output, fbo: gl.FramebufferObject, fresh: bool) anyerror!?bool, destroy_fn: *const fn (output: *Output, allocator: std.mem.Allocator) void, pub fn create( @@ -22,8 +22,8 @@ pub const Output = struct { } } - pub fn update(self: *Output, texture_id: c.GLuint) bool { - return self.update_fn(self, texture_id); + pub fn update(self: *Output, fbo: gl.FramebufferObject, fresh: bool) anyerror!?bool { + return self.update_fn(self, fbo, fresh); } pub fn destroy(self: *Output, allocator: std.mem.Allocator) void { @@ -112,7 +112,7 @@ pub const WindowOutput = struct { resized: bool = false, - fn update(output: *Output, texture_id: c.GLuint) bool { + fn update(output: *Output, fbo: gl.FramebufferObject, _: bool) !?bool { const self: *WindowOutput = @fieldParentPtr("output", output); if (c.glfwWindowShouldClose(self.window) == c.GL_TRUE) @@ -152,7 +152,7 @@ pub const WindowOutput = struct { ); } - c.glBindTexture(c.GL_TEXTURE_2D, texture_id); + c.glBindTexture(c.GL_TEXTURE_2D, fbo.texture_id); c.glDrawArrays(c.GL_TRIANGLE_STRIP, 0, 4); self.constants.texture_shader.bind(); @@ -210,3 +210,60 @@ pub const WindowOutput = struct { _ = height; } }; + +pub const StdoutOutput = struct { + pub const Config = struct { + pub const default: Config = .{}; + + pub fn create( + _: *const Config, + allocator: std.mem.Allocator, + constants: *gl.Constants, + ) !*Output { + const self = allocator.create(StdoutOutput) catch unreachable; + + const buffer = try allocator.alloc(u8, @intCast(constants.config.width * constants.config.height * 4)); + errdefer allocator.free(buffer); + + const stdout = std.fs.File.stdout(); + + self.* = .{ + .output = .{ + .update_fn = update, + .destroy_fn = destroy, + }, + .config = constants.config, + .buffer = buffer, + .file = stdout, + }; + + return &self.output; + } + }; + + output: Output, + config: *cfg.Config, + buffer: []u8, + file: std.fs.File, + + fn update(output: *Output, fbo: gl.FramebufferObject, fresh: bool) !?bool { + const self: *StdoutOutput = @fieldParentPtr("output", output); + + if (fresh) { + fbo.bind(); + defer fbo.unbind(); + + fbo.read(self.config.width, self.config.height, self.buffer); + _ = try self.file.write(self.buffer); + } + + return null; + } + + fn destroy(output: *Output, allocator: std.mem.Allocator) void { + const self: *StdoutOutput = @fieldParentPtr("output", output); + + allocator.free(self.buffer); + allocator.destroy(self); + } +}; diff --git a/src/tsv.zig b/src/tsv.zig index fb5db96..6381998 100644 --- a/src/tsv.zig +++ b/src/tsv.zig @@ -174,27 +174,29 @@ pub const TSVOutput = struct { output: Output, config: *const Config, - fn update(output: *Output, texture_id: c.GLuint) bool { + fn update(output: *Output, fbo: gl.FramebufferObject, fresh: bool) !?bool { const self: *TSVOutput = @fieldParentPtr("output", output); - var fbo: c.GLint = undefined; - c.glGetIntegerv(c.GL_DRAW_FRAMEBUFFER_BINDING, &fbo); + if (fresh) { + var prev_fbo: c.GLint = undefined; + c.glGetIntegerv(c.GL_DRAW_FRAMEBUFFER_BINDING, &prev_fbo); - switch (c.gl_client_send_image( - get_or_init_client(), - self.config.name, - texture_id, - c.GL_TEXTURE_2D, - false, - @intCast(fbo), - null, - )) { - 1 => {}, - 0 => std.debug.print("tsv send: no remote image\n", .{}), - else => |e| std.debug.print("tsv send: error {}\n", .{e}), + switch (c.gl_client_send_image( + get_or_init_client(), + self.config.name, + fbo.texture_id, + c.GL_TEXTURE_2D, + false, + @intCast(prev_fbo), + null, + )) { + 1 => {}, + 0 => std.debug.print("tsv send: no remote image\n", .{}), + else => |e| std.debug.print("tsv send: error {}\n", .{e}), + } } - return false; + return null; } fn destroy(output: *Output, allocator: std.mem.Allocator) void { |
