summaryrefslogtreecommitdiff
path: root/src/screen/drm/frame-buffer
diff options
context:
space:
mode:
authorNathan Reiner <nathan@nathanreiner.xyz>2025-02-02 09:04:45 +0100
committerNathan Reiner <nathan@nathanreiner.xyz>2025-02-02 09:04:45 +0100
commit0b6ee849722002a8bc7cc5374e3136bee4be2ccd (patch)
tree729e99b7e87d8cd298f3b62cd2b97f362b863216 /src/screen/drm/frame-buffer
parent88aa2940b27044794d4dcb49c924a5df17cc0055 (diff)
screen: add frame-buffer
Diffstat (limited to 'src/screen/drm/frame-buffer')
-rw-r--r--src/screen/drm/frame-buffer/pixelformat.zig11
-rw-r--r--src/screen/drm/frame-buffer/root.zig147
2 files changed, 158 insertions, 0 deletions
diff --git a/src/screen/drm/frame-buffer/pixelformat.zig b/src/screen/drm/frame-buffer/pixelformat.zig
new file mode 100644
index 0000000..a4b3f9a
--- /dev/null
+++ b/src/screen/drm/frame-buffer/pixelformat.zig
@@ -0,0 +1,11 @@
+
+fn pixel_format_code(comptime a: u8, comptime b: u8, comptime c: u8, comptime d: u8) u32 {
+ return @as(u32, @intCast(a)) |
+ (@as(u32, @intCast(b)) << 8) |
+ (@as(u32, @intCast(c)) << 16) |
+ (@as(u32, @intCast(d)) << 24);
+}
+
+pub const PixelFormat = enum(u32) {
+ xrgb8888 = pixel_format_code('X', 'R', '2', '4'),
+};
diff --git a/src/screen/drm/frame-buffer/root.zig b/src/screen/drm/frame-buffer/root.zig
new file mode 100644
index 0000000..eb7b47b
--- /dev/null
+++ b/src/screen/drm/frame-buffer/root.zig
@@ -0,0 +1,147 @@
+const std = @import("std");
+const os = std.os.linux;
+const Card = @import("../card.zig").Card;
+const Drm = @import("../request.zig").Drm;
+const PixelFormat = @import("pixelformat.zig").PixelFormat;
+const cerror = @import("../../cerror.zig");
+
+const CreateDumb = extern struct {
+ height: u32,
+ width: u32,
+ bpp: u32,
+ flags: u32,
+ handle: u32,
+ pitch: u32,
+ size: u32,
+};
+
+const FrameBufferCmd2 = extern struct {
+ id: u32,
+ width: u32,
+ height: u32,
+ pixel_format: PixelFormat,
+ flags: u32,
+ handles: [4]u32,
+ pitches: [4]u32,
+ offsets: [4]u32,
+ modifier: [4]u32,
+};
+
+const MapDumb = extern struct {
+ handle: u32,
+ __padding: u32,
+ offset: i64,
+};
+
+pub const Pixel = packed struct(u32) {
+ blue: u8,
+ green: u8,
+ red: u8,
+ _padding: u8 = 0x0,
+};
+
+pub const FrameBuffer = struct {
+ const Self = @This();
+
+ card: *Card,
+ id: u32,
+ width: u32,
+ height: u32,
+ bpp: u32,
+ stride: u32,
+ data_size: u64,
+ canvas_size: u64,
+ handle: u32,
+ data: [*]volatile Pixel,
+
+ pub fn init(card: *Card, width: u32, height: u32, bpp: u32) !Self {
+ var create_dumb = std.mem.zeroInit(CreateDumb, .{
+ .width = width,
+ .height = height,
+ .bpp = bpp,
+ });
+ try Drm.create_dumb.request(
+ card.file.handle,
+ CreateDumb,
+ &create_dumb
+ );
+
+ var fb = Self {
+ .id = 0,
+ .width = create_dumb.width,
+ .height = create_dumb.height,
+ .bpp = create_dumb.bpp,
+ .stride = create_dumb.pitch,
+ .data_size = create_dumb.size,
+ .canvas_size = create_dumb.size / (bpp / 8),
+ .handle = create_dumb.handle,
+ .data = undefined,
+ .card = card,
+ };
+
+ var buffer_cmd = FrameBufferCmd2 {
+ .id = 0,
+ .width = fb.width,
+ .height = fb.height,
+ .pixel_format = PixelFormat.xrgb8888,
+ .flags = 0,
+ .handles = [_] u32 { fb.handle, 0, 0, 0 },
+ .pitches = [_] u32 { fb.stride, 0, 0, 0 },
+ .offsets = [_] u32 { 0, 0, 0, 0 },
+ .modifier = [_] u32 { 0, 0, 0, 0 },
+ };
+
+ try Drm.add_frame_buffer2.request(
+ card.file.handle,
+ FrameBufferCmd2,
+ &buffer_cmd
+ );
+
+ fb.id = buffer_cmd.id;
+
+ var map_dumb = std.mem.zeroInit(MapDumb, .{ .handle = fb.handle });
+
+ try Drm.map_dumb.request(
+ card.file.handle,
+ MapDumb,
+ &map_dumb
+ );
+
+ const address = os.mmap(
+ null,
+ fb.data_size,
+ os.PROT.READ | os.PROT.WRITE,
+ .{ .TYPE = os.MAP_TYPE.SHARED },
+ card.file.handle,
+ map_dumb.offset
+ );
+
+ try cerror.from_usize(address);
+
+ fb.data = @ptrFromInt(address);
+
+ return fb;
+ }
+
+ pub fn set(self: *Self, x: u32, y: u32, pixel: Pixel) void {
+ self.data[x + self.width * y] = pixel;
+ }
+
+ pub fn deinit(self: *Self) void {
+ cerror.from_usize(
+ os.munmap(@ptrCast(@volatileCast(self.data)), self.data_size)
+ ) catch |err| std.debug.panic("munmap failed in frame-buffer: {}", .{err});
+
+ Drm.remove_frame_buffer.request(
+ self.card.file.handle,
+ u32,
+ &self.id
+ ) catch @panic("failed to remove frame-buffer");
+
+ Drm.destroy_dumb.request(
+ self.card.file.handle,
+ u32,
+ &self.handle
+ ) catch @panic("failed to destroy dumb-buffer");
+ }
+};