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"); } };