summaryrefslogtreecommitdiff
path: root/src/screen/drm/connector/root.zig
blob: 362881749b58292075bc947bc9b0cc64b601d369 (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
const std = @import("std");
const os = std.os.linux;
const drm = @import("../root.zig");

pub const Connector = struct {
	pub const Status = @import("status.zig").Status;
	pub const Mode = @import("mode.zig").Mode;
	pub const Kind = @import("kind.zig").Kind;

	const Self = @This();

	card: drm.Card,

	encoder_ids: []u32,
	modes: []Mode,
	prop_ids: []u32,
	prop_value_ids: []u64,
	encoder_id: u32,
	id: u32,
	kind: Kind,
	type_id: u32,
	connection: Status,
	mm_width: u32,
	mm_height: u32,
	subpixel: u32,
	pad: u32,

	pub fn raw_without_ids(card: drm.Card, id: u32) !drm.request.Connector {
		var result = std.mem.zeroInit(drm.request.Connector, .{ .id = id });
		try card.request(.get_connector, &result);
		return result;
	}

	// NOTE: This function does not take in account
	//       that there might be some hot-plugging going
	//       on. This might have to change in the future.
	pub fn init(card: drm.Card, id: u32) !Self {
		var raw = try Self.raw_without_ids(card, id);
		const resources = .{
			.encoder_ids = try card.allocator.alloc(u32, raw.count_encoders),
			.modes = try card.allocator.alloc(Mode, raw.count_modes),
			.prop_ids = try card.allocator.alloc(u32, raw.count_props),
			.prop_value_ids = try card.allocator.alloc(u64, raw.count_props),
			.encoder_id = raw.encoder_id,
			.id = raw.id,
			.kind = raw.type,
			.type_id = raw.type_id,
			.connection = raw.connection,
			.mm_width = raw.mm_width,
			.mm_height = raw.mm_height,
			.subpixel = raw.subpixel,
			.pad = raw.pad,
			.card = card,
	};

		@memset(resources.encoder_ids, 0);
		@memset(resources.modes, std.mem.zeroes(Mode));
		@memset(resources.prop_ids, 0);
		@memset(resources.prop_value_ids, 0);

		raw.encoder_ids = @ptrCast(resources.encoder_ids);
		raw.modes = @ptrCast(resources.modes);
		raw.prop_ids = @ptrCast(resources.prop_ids);
		raw.prop_value_ids = @ptrCast(resources.prop_value_ids);

		try card.request(.get_connector, &raw);

		return resources;
	}

	pub fn deinit(self: *Self) void {
		self.card.allocator.free(self.encoder_ids);
		self.card.allocator.free(self.modes);
		self.card.allocator.free(self.prop_ids);
	}

	pub fn compatible_crtc(self: *Self) ?usize {
		for (self.encoder_ids) |encoder_id| {
			var encoder = drm.Encoder.init(self.card, encoder_id) catch continue;
			defer encoder.deinit();

			for (0..32) |index| {
				if ((encoder.possible_crtcs & (@as(u32, 1) << @intCast(index))) != 0) {
					return index;
				}
			}
		}

		return null;
	}
};