summaryrefslogtreecommitdiff
path: root/src/screen/drm/buffer/raw.zig
blob: c5a04f31aa47ae366e93759d4e5c5f427b1b051e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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,
	stride: u32,
	handle: u32,
	bytes: []volatile u8,

	pub fn init(card: drm.Card, width: u32, height: u32) !Self {
		var create_dumb = std.mem.zeroInit(drm.request.CreateDumb, .{
			.width = width,
			.height = height,
			.bpp = 32,
		});
		try card.request(
			.create_dumb,
			&create_dumb
		);

		var fb = Self {
			.id = 0,
			.width = create_dumb.width,
			.height = create_dumb.height,
			.stride = create_dumb.pitch,
			.handle = create_dumb.handle,
			.bytes = 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,
			create_dumb.size,
			os.PROT.READ | os.PROT.WRITE,
			.{ .TYPE = os.MAP_TYPE.SHARED },
			card.file.handle,
			map_dumb.offset
		);

		try cerror.from_usize(address);

		fb.bytes = @as([*]volatile u8, @ptrFromInt(address))[0..create_dumb.size];

		return fb;
	}

	pub fn deinit(self: *Self) void {
		cerror.from_usize(
			os.munmap(@ptrCast(@volatileCast(self.bytes)), self.bytes.len)
		) 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");
	}
};