diff options
Diffstat (limited to 'src/output.zig')
| -rw-r--r-- | src/output.zig | 203 |
1 files changed, 189 insertions, 14 deletions
diff --git a/src/output.zig b/src/output.zig index 459bedb..960c8ae 100644 --- a/src/output.zig +++ b/src/output.zig @@ -1,31 +1,202 @@ -const c = @import("c.zig"); const std = @import("std"); +const c = @import("c.zig"); +const build_config = @import("build_config"); const cfg = @import("config.zig"); const gl = @import("gl.zig"); +const yaml = @import("yaml.zig"); pub const Output = struct { - update: *const fn (*Output, c.GLuint) bool, - destroy: *const fn (*Output) void, + update_fn: *const fn (output: *Output, texture_id: c.GLuint) bool, + destroy_fn: *const fn (output: *Output, allocator: std.mem.Allocator) void, - fn init(update: *const fn (*Output, c.GLuint) bool, destroy: *const fn (*Output) void) Output { - return Output{ - .update = update, - .destroy = destroy, + pub fn create( + allocator: std.mem.Allocator, + config: *const cfg.OutputConfig, + constants: *gl.Constants, + ) *Output { + return switch (config.*) { + .window => |*con| WindowOutput.create(allocator, con, constants), + .texture_share_vk => |*con| if (build_config.have_tsv) TSVOutput.create(allocator, con, constants) else unreachable, }; } + pub fn update(self: *Output, texture_id: c.GLuint) bool { + return self.update_fn(self, texture_id); + } + + pub fn destroy(self: *Output, allocator: std.mem.Allocator) void { + return self.destroy_fn(self, allocator); + } +}; + +pub const TSVOutput = struct { + pub const Config = struct { + name: [:0]const u8, + + pub const default: Config = .{ + .name = "glsl-view", + }; + + pub fn parse(parser: *c.yaml_parser_t, allocator: std.mem.Allocator) !Config { + var self: Config = .default; + + while (true) { + var event: c.yaml_event_t = undefined; + if (c.yaml_parser_parse(parser, &event) != 1) + return error.YAMLParserError; + defer c.yaml_event_delete(&event); + + switch (event.type) { + c.YAML_MAPPING_END_EVENT => break, + c.YAML_SCALAR_EVENT => { + const data = event.data.scalar; + const key: []const u8 = data.value[0..data.length]; + + if (std.mem.eql(u8, key, "name")) { + self.name = try yaml.parseStringZ(parser, allocator); + } else { + std.debug.print("unknown key: '{s}'\n", .{key}); + try yaml.skipAny(parser); + } + }, + else => { + std.debug.print("unexpected event: {}\n", .{event.type}); + return error.InvalidConfiguration; + }, + } + } + + return self; + } + }; + + output: Output, + config: *const Config, + client: *c.GlClient, + image_size: c.GlImageExtent, + pub fn create( allocator: std.mem.Allocator, - config: cfg.OutputConfig, + config: *const Config, constants: *gl.Constants, ) *Output { - return switch (config.type) { - .window => WindowOutput.create(allocator, config, constants), + 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, + config.name, + @intCast(constants.config.width), + @intCast(constants.config.height), + c.R8G8B8A8, + true, + ); + + return &self.output; + } + + fn update(output: *Output, texture_id: c.GLuint) bool { + const self: *TSVOutput = @fieldParentPtr("output", output); + + var fbo: c.GLint = undefined; + c.glGetIntegerv(c.GL_DRAW_FRAMEBUFFER_BINDING, &fbo); + + _ = c.gl_client_send_image( + self.client, + self.config.name, + texture_id, + c.GL_TEXTURE_2D, + false, + @intCast(fbo), + &self.image_size, + ); + return false; + } + + fn destroy(output: *Output, allocator: std.mem.Allocator) void { + const self: *TSVOutput = @fieldParentPtr("output", output); + + allocator.destroy(self); } }; pub const WindowOutput = struct { + pub const Config = struct { + const FilterMode = enum(c.GLuint) { + nearest = c.GL_NEAREST, + linear = c.GL_LINEAR, + }; + + width: i32, + height: i32, + filter: FilterMode, + + monitor: []const u8, + fullscreen: bool, + + pub const default: Config = .{ + .width = 800, + .height = 600, + .filter = .linear, + .monitor = "", + .fullscreen = false, + }; + + pub fn parse(parser: *c.yaml_parser_t, allocator: std.mem.Allocator) !Config { + var self: Config = .default; + + while (true) { + var event: c.yaml_event_t = undefined; + if (c.yaml_parser_parse(parser, &event) != 1) + return error.YAMLParserError; + defer c.yaml_event_delete(&event); + + switch (event.type) { + c.YAML_MAPPING_END_EVENT => break, + c.YAML_SCALAR_EVENT => { + const data = event.data.scalar; + const key: []const u8 = data.value[0..data.length]; + + if (std.mem.eql(u8, key, "width")) { + self.width = try yaml.parseInt(parser, i32); + } else if (std.mem.eql(u8, key, "height")) { + self.height = try yaml.parseInt(parser, i32); + } else if (std.mem.eql(u8, key, "filter")) { + self.filter = try yaml.parseEnum(parser, FilterMode); + } else if (std.mem.eql(u8, key, "monitor")) { + self.monitor = try yaml.parseString(parser, allocator); + } else if (std.mem.eql(u8, key, "fullscreen")) { + self.fullscreen = try yaml.parseBool(parser); + } else { + std.debug.print("unknown key: '{s}'\n", .{key}); + try yaml.skipAny(parser); + } + }, + else => { + std.debug.print("unexpected event: {}\n", .{event.type}); + return error.InvalidConfiguration; + }, + } + } + + return self; + } + }; + output: Output, window: *c.GLFWwindow, constants: *gl.Constants, @@ -34,16 +205,19 @@ pub const WindowOutput = struct { pub fn create( allocator: std.mem.Allocator, - config: cfg.OutputConfig, + config: *const Config, constants: *gl.Constants, ) *Output { const self = allocator.create(WindowOutput) catch unreachable; c.glfwDefaultWindowHints(); - self.* = WindowOutput{ + self.* = .{ .constants = constants, - .output = Output.init(update, destroy), + .output = .{ + .update_fn = update, + .destroy_fn = destroy, + }, .window = c.glfwCreateWindow( config.width, config.height, @@ -108,10 +282,11 @@ pub const WindowOutput = struct { return false; } - fn destroy(output: *Output) void { + fn destroy(output: *Output, allocator: std.mem.Allocator) void { const self: *WindowOutput = @fieldParentPtr("output", output); c.glfwDestroyWindow(self.window); + allocator.destroy(self); } fn keyCallback( |
