diff options
| author | Nathan Reiner <nathan@nathanreiner.xyz> | 2025-02-02 16:00:15 +0100 |
|---|---|---|
| committer | Nathan Reiner <nathan@nathanreiner.xyz> | 2025-02-02 16:00:15 +0100 |
| commit | 8d062a90b1ffbe9e00334fa3e9e939406bd32141 (patch) | |
| tree | 20951bba89bbcdc3090e24d99eb9f91c0043f28e /src/screen/drm | |
| parent | 0b6ee849722002a8bc7cc5374e3136bee4be2ccd (diff) | |
screen: add vsync and double buffering
Diffstat (limited to 'src/screen/drm')
| -rw-r--r-- | src/screen/drm/card.zig | 26 | ||||
| -rw-r--r-- | src/screen/drm/crtc/root.zig | 32 | ||||
| -rw-r--r-- | src/screen/drm/event.zig | 31 | ||||
| -rw-r--r-- | src/screen/drm/frame-buffer/page-flip.zig | 8 | ||||
| -rw-r--r-- | src/screen/drm/frame-buffer/root.zig | 41 | ||||
| -rw-r--r-- | src/screen/drm/request.zig | 2 |
6 files changed, 135 insertions, 5 deletions
diff --git a/src/screen/drm/card.zig b/src/screen/drm/card.zig index d66a5f1..6147cf2 100644 --- a/src/screen/drm/card.zig +++ b/src/screen/drm/card.zig @@ -7,7 +7,8 @@ const Resources = @import("resources.zig").Resources; const Connector = @import("connector/root.zig").Connector; const Encoder = @import("encoder/root.zig").Encoder; const Crtc = @import("crtc/root.zig").Crtc; -const FrameBuffer = @import("frame-buffer/root.zig").FrameBuffer; +const DoubleBuffer = @import("frame-buffer/root.zig").DoubleBuffer; +const Event = @import("event.zig").Event; pub const Card = struct { @@ -25,6 +26,7 @@ pub const Card = struct { .mode = .read_write, .lock_nonblocking = true, }), + .allocator = allocator, }; } @@ -54,7 +56,25 @@ pub const Card = struct { return Crtc.init(self, id); } - pub fn create_frame_buffer(self: *Card, width: u32, height: u32, bpp: u32) !FrameBuffer { - return FrameBuffer.init(self, width, height, bpp); + pub fn create_double_buffer(self: *Card, width: u32, height: u32, bpp: u32) !DoubleBuffer { + return DoubleBuffer.init(self, width, height, bpp); + } + + pub fn poll_event(self: *Card, timeout: i32) !?Event { + var pollfd = os.pollfd { + .fd = self.file.handle, + .events = os.POLL.IN, + .revents = 0 + }; + + try cerror.from_usize(os.poll(@ptrCast(&pollfd), 1, timeout)); + + if ((pollfd.revents & os.POLL.IN) != 0) { + var event = std.mem.zeroes(Event); + try cerror.from_usize(os.read(self.file.handle, @ptrCast(&event), @sizeOf(Event))); + return event; + } + + return null; } }; diff --git a/src/screen/drm/crtc/root.zig b/src/screen/drm/crtc/root.zig index 3c9d6f9..f1f1d5c 100644 --- a/src/screen/drm/crtc/root.zig +++ b/src/screen/drm/crtc/root.zig @@ -2,7 +2,9 @@ const std = @import("std"); const Card = @import("../card.zig").Card; const Drm = @import("../request.zig").Drm; const Connector = @import("../connector/root.zig").Connector; -const FrameBuffer = @import("../frame-buffer/root.zig").FrameBuffer; +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 { @@ -17,6 +19,22 @@ pub const RawCrtc = extern struct { 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(); @@ -65,8 +83,18 @@ pub const Crtc = struct { }; 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 }), + }); - std.debug.print("crtc = {any}\n", .{self}); + try Drm.page_flip.request(self.card.file.handle, PageFlip, &flip); } pub fn detach(self: *Self) void { diff --git a/src/screen/drm/event.zig b/src/screen/drm/event.zig new file mode 100644 index 0000000..201ced3 --- /dev/null +++ b/src/screen/drm/event.zig @@ -0,0 +1,31 @@ + +pub const EventType = enum(u32) { + vblank = 1, + page_flip_complete = 2, + crtc_sequence = 3, +}; + +pub const VBlankEvent = extern struct { + user_data: u64, + tv_sec: u32, + tv_usec: u32, + sequence: u32, + crtc_id: u32, +}; + +pub const CrtcSequenceEvent = extern struct { + user_data: u64, + time_ns: i64, + sequence: u64, +}; + +pub const EventPayload = extern union { + vblank: VBlankEvent, + crtc_sequence: CrtcSequenceEvent, +}; + +pub const Event = extern struct { + type: EventType, + length: u32, + payload: EventPayload, +}; diff --git a/src/screen/drm/frame-buffer/page-flip.zig b/src/screen/drm/frame-buffer/page-flip.zig new file mode 100644 index 0000000..2e41e61 --- /dev/null +++ b/src/screen/drm/frame-buffer/page-flip.zig @@ -0,0 +1,8 @@ + +pub const PageFlip = packed struct(u32) { + event: bool, + is_async: bool, + absolute: bool, + relative: bool, + _padding: u28, +} diff --git a/src/screen/drm/frame-buffer/root.zig b/src/screen/drm/frame-buffer/root.zig index eb7b47b..0083711 100644 --- a/src/screen/drm/frame-buffer/root.zig +++ b/src/screen/drm/frame-buffer/root.zig @@ -33,6 +33,43 @@ const MapDumb = extern struct { offset: i64, }; +pub const DoubleBuffer = struct { + const Self = @This(); + + back: FrameBuffer, + front: FrameBuffer, + + pub fn init(card: *Card, width: u32, height: u32, bpp: u32) !Self { + return .{ + .back = try FrameBuffer.init(card, width, height, bpp), + .front = try FrameBuffer.init(card, width, height, bpp), + }; + } + + pub fn swap(self: *Self) void { + const back_data = self.back.data; + self.back.data = self.front.data; + self.front.data = back_data; + + const back_id = self.back.id; + self.back.id = self.front.id; + self.front.id = back_id; + } + + pub fn deinit(self: *Self) void { + self.back.deinit(); + self.front.deinit(); + } + + pub fn buffer(self: *Self) *FrameBuffer { + return &self.back; + } + + pub fn crtc_buffer(self: *Self) *FrameBuffer { + return &self.front; + } +}; + pub const Pixel = packed struct(u32) { blue: u8, green: u8, @@ -127,6 +164,10 @@ pub const FrameBuffer = struct { self.data[x + self.width * y] = pixel; } + pub fn fill(self: *Self, pixel: Pixel) void { + @memset(self.data[0..self.canvas_size], pixel); + } + pub fn deinit(self: *Self) void { cerror.from_usize( os.munmap(@ptrCast(@volatileCast(self.data)), self.data_size) diff --git a/src/screen/drm/request.zig b/src/screen/drm/request.zig index 9e0a045..5daf92f 100644 --- a/src/screen/drm/request.zig +++ b/src/screen/drm/request.zig @@ -15,6 +15,8 @@ pub const Drm = enum(u8) { get_encoder = 0xa6, get_connector = 0xa7, remove_frame_buffer = 0xaf, + page_flip = 0xb0, + dirty_frame_buffer = 0xb1, create_dumb = 0xb2, map_dumb = 0xb3, destroy_dumb = 0xb4, |