diff options
| author | Nathan Reiner <nathan@nathanreiner.xyz> | 2025-02-02 09:04:45 +0100 |
|---|---|---|
| committer | Nathan Reiner <nathan@nathanreiner.xyz> | 2025-02-02 09:04:45 +0100 |
| commit | 0b6ee849722002a8bc7cc5374e3136bee4be2ccd (patch) | |
| tree | 729e99b7e87d8cd298f3b62cd2b97f362b863216 /src/screen/drm/frame-buffer | |
| parent | 88aa2940b27044794d4dcb49c924a5df17cc0055 (diff) | |
screen: add frame-buffer
Diffstat (limited to 'src/screen/drm/frame-buffer')
| -rw-r--r-- | src/screen/drm/frame-buffer/pixelformat.zig | 11 | ||||
| -rw-r--r-- | src/screen/drm/frame-buffer/root.zig | 147 |
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"); + } +}; |