summaryrefslogtreecommitdiff
path: root/src/screen/drm/crtc/root.zig
blob: f1f1d5c20f86f40c5b0dcc5d99b97c07a734e6ae (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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
const std = @import("std");
const Card = @import("../card.zig").Card;
const Drm = @import("../request.zig").Drm;
const Connector = @import("../connector/root.zig").Connector;
const fb = @import("../frame-buffer/root.zig");
const FrameBuffer = fb.FrameBuffer;
const DoubleBuffer = fb.DoubleBuffer;
const Mode = @import("../connector/mode.zig").Mode;

pub const RawCrtc = extern struct {
    connector_ids: ?*u32,
    count_connectors: u32,
    id: u32,
    buffer_id: u32,
    x: u32,
    y: u32,
    gamma_size: u32,
    mode_valid: u32,
    mode: Mode,
};

const PageFlipEvent = packed struct(u32) {
    event: bool,
    is_async: bool,
    absolute: bool,
    relative: bool,
    __padding: u28,
};

const PageFlip = extern struct {
    crtc_id: u32,
    buffer_id: u32,
    flags: PageFlipEvent,
    __reserved: u32,
    user_data: u64,
};

pub const Crtc = struct {
    const Self = @This();

    connector_ids: ?*u32,
    count_connectors: u32,
    id: u32,
    buffer_id: u32,
    x: u32,
    y: u32,
    mode: Mode,
    mode_valid: u32,
    gamma_size: u32,
    card: *Card,

    pub fn init(card: *Card, id: u32) !Self {
        var raw = std.mem.zeroInit(RawCrtc, .{ .id = id });
        try Drm.get_crtc.request(card.file.handle, RawCrtc, &raw);
        return .{
            .connector_ids = raw.connector_ids,
            .count_connectors = raw.count_connectors,
            .id = raw.id,
            .buffer_id = raw.buffer_id,
            .x = raw.x,
            .y = raw.y,
            .mode = raw.mode,
            .mode_valid = raw.mode_valid,
            .gamma_size = raw.gamma_size,
            .card = card,
        };
    }

    pub fn attach(self: *Self, frame_buffer: *FrameBuffer, connector: *Connector, mode: Mode) !void {
        self.connector_ids = &connector.id;
        self.count_connectors = 1;

        var crtc = RawCrtc {
            .id = self.id,
            .x = self.x,
            .y = self.y,
            .buffer_id = frame_buffer.id,
            .connector_ids = self.connector_ids,
            .count_connectors = self.count_connectors,
            .mode = mode,
            .mode_valid = 1,
            .gamma_size = self.gamma_size,
        };

        try Drm.set_crtc.request(self.card.file.handle, RawCrtc, &crtc);
    }

    pub fn page_flip(self: *Self, double_buffer: *DoubleBuffer) !void {
        double_buffer.swap();

        var flip = std.mem.zeroInit(PageFlip, .{
            .buffer_id = double_buffer.crtc_buffer().id,
            .crtc_id = self.id,
            .flags = std.mem.zeroInit(PageFlipEvent, .{ .event = true }),
        });

        try Drm.page_flip.request(self.card.file.handle, PageFlip, &flip);
    }

    pub fn detach(self: *Self) void {
        var crtc = RawCrtc {
            .id = self.id,
            .x = self.x,
            .y = self.y,
            .buffer_id = self.buffer_id,
            .connector_ids = self.connector_ids,
            .count_connectors = self.count_connectors,
            .mode = self.mode,
            .mode_valid = self.mode_valid,
            .gamma_size = self.gamma_size,
        };

        Drm.set_crtc.request(
            self.card.file.handle,
            RawCrtc,
            &crtc
        ) catch |err| std.debug.panic("set crtc failed on detach: {}", .{err});
    }
};