summaryrefslogtreecommitdiff
path: root/src/screen/drm/buffer
diff options
context:
space:
mode:
Diffstat (limited to 'src/screen/drm/buffer')
-rw-r--r--src/screen/drm/buffer/raw.zig109
-rw-r--r--src/screen/drm/buffer/root.zig32
2 files changed, 141 insertions, 0 deletions
diff --git a/src/screen/drm/buffer/raw.zig b/src/screen/drm/buffer/raw.zig
new file mode 100644
index 0000000..e4674eb
--- /dev/null
+++ b/src/screen/drm/buffer/raw.zig
@@ -0,0 +1,109 @@
+const std = @import("std");
+const os = std.os.linux;
+const drm = @import("../root.zig");
+const cerror = @import("../../cerror.zig");
+
+pub const Raw = struct {
+ const Self = @This();
+
+ card: *drm.Card,
+ id: u32,
+ width: u32,
+ height: u32,
+ bpp: u32,
+ stride: u32,
+ data_size: u64,
+ canvas_size: u64,
+ handle: u32,
+ data: [*]volatile drm.Pixel,
+
+ pub fn init(card: *drm.Card, width: u32, height: u32, bpp: u32) !Self {
+ var create_dumb = std.mem.zeroInit(drm.request.CreateDumb, .{
+ .width = width,
+ .height = height,
+ .bpp = bpp,
+ });
+ try card.request(
+ .create_dumb,
+ &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 = drm.request.FrameBufferCmd2 {
+ .id = 0,
+ .width = fb.width,
+ .height = fb.height,
+ .pixel_format = drm.Pixel.Format.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 card.request(
+ .add_frame_buffer2,
+ &buffer_cmd
+ );
+
+ fb.id = buffer_cmd.id;
+
+ var map_dumb = std.mem.zeroInit(drm.request.MapDumb, .{ .handle = fb.handle });
+
+ try card.request(
+ .map_dumb,
+ &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, p: drm.Pixel) void {
+ self.data[x + self.width * y] = p;
+ }
+
+ pub fn fill(self: *Self, p: drm.Pixel) void {
+ @memset(self.data[0..self.canvas_size], p);
+ }
+
+ 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});
+
+ self.card.request(
+ .remove_frame_buffer,
+ &self.id
+ ) catch @panic("failed to remove frame-buffer");
+
+ self.card.request(
+ .destroy_dumb,
+ &self.handle
+ ) catch @panic("failed to destroy dumb-buffer");
+ }
+};
diff --git a/src/screen/drm/buffer/root.zig b/src/screen/drm/buffer/root.zig
new file mode 100644
index 0000000..e967d51
--- /dev/null
+++ b/src/screen/drm/buffer/root.zig
@@ -0,0 +1,32 @@
+const drm = @import("../root.zig");
+
+pub const Buffer = struct {
+ const Self = @This();
+ pub const Raw = @import("raw.zig").Raw;
+
+ current: Raw,
+ crtc: Raw,
+
+ pub fn init(card: *drm.Card, width: u32, height: u32, bpp: u32) !Self {
+ return .{
+ .current = try Raw.init(card, width, height, bpp),
+ .crtc = try Raw.init(card, width, height, bpp),
+ };
+ }
+
+ pub fn swap(self: *Self) void {
+ const data = self.current.data;
+ self.current.data = self.crtc.data;
+ self.crtc.data = data;
+
+ const id = self.current.id;
+ self.current.id = self.crtc.id;
+ self.crtc.id = id;
+ }
+
+ pub fn deinit(self: *Self) void {
+ self.current.deinit();
+ self.crtc.deinit();
+ }
+};
+