aboutsummaryrefslogtreecommitdiffstats
path: root/src/output.zig
blob: be3b3dd0caae48fdd9d0f83458b741782487cde7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
const c = @import("c.zig");
const std = @import("std");
const cfg = @import("config.zig");
const gl = @import("gl.zig");

pub const Output = struct {
    update: fn (*Output, c.GLuint) bool,
    destroy: fn (*Output) void,

    fn init(update: fn (*Output, c.GLuint) bool, destroy: fn (*Output) void) Output {
        return Output{
            .update = update,
            .destroy = destroy,
        };
    }

    pub fn create(allocator: *std.mem.Allocator, config: cfg.OutputConfig, constants: *gl.Constants) *Output {
        return switch (config.type) {
            cfg.OutputType.window => WindowOutput.create(allocator, config, constants),
            else => unreachable,
        };
    }
};

pub const WindowOutput = struct {
    output: Output,
    window: *c.GLFWwindow,
    constants: *gl.Constants,

    pub fn create(allocator: *std.mem.Allocator, config: cfg.OutputConfig, constants: *gl.Constants) *Output {
        const self = allocator.create(WindowOutput) catch unreachable;

        c.glfwDefaultWindowHints();

        self.* = WindowOutput{
            .constants = constants,
            .output = Output.init(update, destroy),
            .window = c.glfwCreateWindow(config.width, config.height, "glsl-view output", null, constants.main_window) orelse {
                std.debug.panic("unable to create output window\n", .{});
            },
        };

        c.glfwSetWindowUserPointer(self.*.window, @ptrCast(*c_void, self));
        _ = c.glfwSetKeyCallback(self.*.window, keyCallback);

        c.glfwMakeContextCurrent(self.*.window);
        constants.normalizedQuad.bind(0);

        return &self.*.output;
    }

    fn update(output: *Output, texture_id: c.GLuint) bool {
        const self = @fieldParentPtr(WindowOutput, "output", output);

        if (c.glfwWindowShouldClose(self.*.window) == c.GL_TRUE)
            return true;

        c.glfwMakeContextCurrent(self.*.window);
        c.glClear(c.GL_COLOR_BUFFER_BIT);

        c.glBindTexture(c.GL_TEXTURE_2D, texture_id);
        c.glDrawArrays(c.GL_TRIANGLE_STRIP, 0, 4);

        self.constants.textureShader.bind();
        self.constants.normalizedQuad.draw();
        
        c.glfwSwapBuffers(self.*.window);
        return false;
    }

    fn destroy(output: *Output) void {
        const self = @fieldParentPtr(WindowOutput, "output", output);

        c.glfwDestroyWindow(self.*.window);
    }

    extern fn keyCallback(win: ?*c.GLFWwindow, key: c_int, scancode: c_int, action: c_int, mods: c_int) callconv(.C) void {
        if (action != c.GLFW_PRESS) return;
        const self = @ptrCast(*WindowOutput, @alignCast(@alignOf(WindowOutput), c.glfwGetWindowUserPointer(win).?));

        std.debug.warn("key pressed: {}\n", .{ key });
        switch (key) {
            //        c.GLFW_KEY_F => // toggle fullscreen
            //        c.GLFW_KEY_LEFT => // cycle through monitors
            //        c.GLFW_KEY_RIGHT => // cycle through monitors
            else => {},
        }
    }
};