refactor: working Card abstraction for drmModeGetResources.
This commit is contained in:
+178
@@ -0,0 +1,178 @@
|
||||
const std = @import("std");
|
||||
const format = @import("format.zig");
|
||||
const log = std.log.scoped(.drm);
|
||||
|
||||
pub const sys = @import("sys.zig");
|
||||
pub const Format = format.Format;
|
||||
pub const FormatModifiers = format.FormatModifiers;
|
||||
|
||||
pub const Card = struct {
|
||||
handle: std.Io.File,
|
||||
|
||||
pub fn openAuto(io: std.Io) !Card {
|
||||
const dir = try std.Io.Dir.openDirAbsolute(io, "/dev/dri", .{ .iterate = true });
|
||||
defer dir.close(io);
|
||||
|
||||
var it = dir.iterate();
|
||||
const handle = try while (try it.next(io)) |entry| {
|
||||
if (entry.kind == .character_device) {
|
||||
log.debug("Found device /dev/dri/{s}.", .{entry.name});
|
||||
break dir.openFile(io, entry.name, .{});
|
||||
}
|
||||
} else error.NoDevicesFound;
|
||||
|
||||
return Card{ .handle = handle };
|
||||
}
|
||||
|
||||
pub fn open(io: std.Io, path: []const u8) !Card {
|
||||
const handle = try if (std.Io.Dir.path.isAbsolute(path)) handle: {
|
||||
log.debug("Using device path {s}.", .{path});
|
||||
break :handle std.Io.Dir.openFileAbsolute(io, path, .{});
|
||||
} else handle: {
|
||||
const dir = try std.Io.Dir.openDirAbsolute(io, "/dev/dri", .{});
|
||||
defer dir.close(io);
|
||||
|
||||
log.debug("Using device path /dev/dri/{s}.", .{path});
|
||||
break :handle dir.openDir(io, path, .{});
|
||||
};
|
||||
|
||||
return Card{ .handle = handle };
|
||||
}
|
||||
|
||||
pub fn close(self: Card, io: std.Io) void {
|
||||
self.handle.close(io);
|
||||
}
|
||||
|
||||
pub const GetModeError = sys.IoctlError;
|
||||
|
||||
pub fn getModeAlloc(
|
||||
self: Card,
|
||||
gpa: std.mem.Allocator,
|
||||
) (GetModeError || std.mem.Allocator.Error)!ModeCard {
|
||||
return while (true) {
|
||||
var res = std.mem.zeroes(sys.mode.CardRes);
|
||||
try sys.ioctl(self.handle.handle, .mode_getresources, &res);
|
||||
|
||||
var ret = ModeCard{
|
||||
.handle = self.handle,
|
||||
.min_width = res.min_width,
|
||||
.max_width = res.max_width,
|
||||
.min_height = res.min_height,
|
||||
.max_height = res.max_height,
|
||||
.fbs = &.{},
|
||||
.crtcs = &.{},
|
||||
.connectors = &.{},
|
||||
.encoders = &.{},
|
||||
};
|
||||
|
||||
ret.fbs = try gpa.alloc(u32, res.count_fbs);
|
||||
errdefer gpa.free(ret.fbs);
|
||||
res.fb_id_ptr = @intFromPtr(ret.fbs.ptr);
|
||||
|
||||
ret.crtcs = try gpa.alloc(u32, res.count_crtcs);
|
||||
errdefer gpa.free(ret.crtcs);
|
||||
res.crtc_id_ptr = @intFromPtr(ret.crtcs.ptr);
|
||||
|
||||
ret.connectors = try gpa.alloc(u32, res.count_connectors);
|
||||
errdefer gpa.free(ret.connectors);
|
||||
res.connector_id_ptr = @intFromPtr(ret.connectors.ptr);
|
||||
|
||||
ret.encoders = try gpa.alloc(u32, res.count_encoders);
|
||||
errdefer gpa.free(ret.encoders);
|
||||
res.encoder_id_ptr = @intFromPtr(ret.encoders.ptr);
|
||||
|
||||
const cached = res;
|
||||
try sys.ioctl(self.handle.handle, .mode_getresources, &res);
|
||||
|
||||
if (cached.count_fbs < res.count_fbs or
|
||||
cached.count_crtcs < res.count_crtcs or
|
||||
cached.count_connectors < res.count_connectors or
|
||||
cached.count_encoders < res.count_encoders)
|
||||
{
|
||||
gpa.free(ret.encoders);
|
||||
gpa.free(ret.connectors);
|
||||
gpa.free(ret.crtcs);
|
||||
gpa.free(ret.fbs);
|
||||
continue;
|
||||
}
|
||||
|
||||
break ret;
|
||||
};
|
||||
}
|
||||
|
||||
pub fn getModeBuffered(
|
||||
self: Card,
|
||||
fbs: []u32,
|
||||
crtcs: []u32,
|
||||
connectors: []u32,
|
||||
encoders: []u32,
|
||||
) (GetModeError || error{
|
||||
TooManyFbs,
|
||||
TooManyCrtcs,
|
||||
TooManyConnectors,
|
||||
TooManyEncoders,
|
||||
})!ModeCard {
|
||||
return while (true) {
|
||||
var res = std.mem.zeroes(sys.mode.CardRes);
|
||||
try sys.ioctl(self.handle.handle, .mode_getresources, &res);
|
||||
|
||||
var ret = ModeCard{
|
||||
.handle = self.handle,
|
||||
.min_width = res.min_width,
|
||||
.max_width = res.max_width,
|
||||
.min_height = res.min_height,
|
||||
.max_height = res.max_height,
|
||||
.fbs = &.{},
|
||||
.crtcs = &.{},
|
||||
.connectors = &.{},
|
||||
.encoders = &.{},
|
||||
};
|
||||
|
||||
if (res.count_fbs > fbs.len) return error.TooManyFbs;
|
||||
ret.fbs = fbs[0..res.count_fbs];
|
||||
res.fb_id_ptr = @intFromPtr(ret.fbs.ptr);
|
||||
|
||||
if (res.count_crtcs > crtcs.len) return error.TooManyCrtcs;
|
||||
ret.crtcs = crtcs[0..res.count_crtcs];
|
||||
res.crtc_id_ptr = @intFromPtr(ret.crtcs.ptr);
|
||||
|
||||
if (res.count_connectors > connectors.len) return error.TooManyConnectors;
|
||||
ret.connectors = connectors[0..res.count_connectors];
|
||||
res.connector_id_ptr = @intFromPtr(ret.connectors.ptr);
|
||||
|
||||
if (res.count_encoders > encoders.len) return error.TooManyEncoders;
|
||||
ret.encoders = encoders[0..res.count_encoders];
|
||||
res.encoder_id_ptr = @intFromPtr(ret.encoders.ptr);
|
||||
|
||||
const cached = res;
|
||||
try sys.ioctl(self.handle.handle, .mode_getresources, &res);
|
||||
|
||||
if (cached.count_fbs < res.count_fbs or
|
||||
cached.count_crtcs < res.count_crtcs or
|
||||
cached.count_connectors < res.count_connectors or
|
||||
cached.count_encoders < res.count_encoders)
|
||||
continue;
|
||||
|
||||
break ret;
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub const ModeCard = struct {
|
||||
handle: std.Io.File,
|
||||
min_width: u32,
|
||||
max_width: u32,
|
||||
min_height: u32,
|
||||
max_height: u32,
|
||||
fbs: []const u32,
|
||||
crtcs: []const u32,
|
||||
connectors: []const u32,
|
||||
encoders: []const u32,
|
||||
|
||||
pub fn deinit(self: ModeCard, gpa: std.mem.Allocator) void {
|
||||
gpa.free(self.encoders);
|
||||
gpa.free(self.connectors);
|
||||
gpa.free(self.crtcs);
|
||||
gpa.free(self.fbs);
|
||||
}
|
||||
};
|
||||
+294
@@ -0,0 +1,294 @@
|
||||
pub const Format = enum(u32) {
|
||||
pub const big_endian: u32 = 1 << 31;
|
||||
|
||||
invalid = 0,
|
||||
|
||||
c1 = fourccCode('C', '1', ' ', ' '),
|
||||
c2 = fourccCode('C', '2', ' ', ' '),
|
||||
c4 = fourccCode('C', '4', ' ', ' '),
|
||||
c8 = fourccCode('C', '8', ' ', ' '),
|
||||
d1 = fourccCode('D', '1', ' ', ' '),
|
||||
d2 = fourccCode('D', '2', ' ', ' '),
|
||||
d4 = fourccCode('D', '4', ' ', ' '),
|
||||
d8 = fourccCode('D', '8', ' ', ' '),
|
||||
r1 = fourccCode('R', '1', ' ', ' '),
|
||||
r2 = fourccCode('R', '2', ' ', ' '),
|
||||
r4 = fourccCode('R', '4', ' ', ' '),
|
||||
r8 = fourccCode('R', '8', ' ', ' '),
|
||||
r10 = fourccCode('R', '1', '0', ' '),
|
||||
r12 = fourccCode('R', '1', '2', ' '),
|
||||
r16 = fourccCode('R', '1', '6', ' '),
|
||||
rg88 = fourccCode('R', 'G', '8', '8'),
|
||||
gr88 = fourccCode('G', 'R', '8', '8'),
|
||||
rg1616 = fourccCode('R', 'G', '3', '2'),
|
||||
gr1616 = fourccCode('G', 'R', '3', '2'),
|
||||
rgb332 = fourccCode('R', 'G', 'B', '8'),
|
||||
bgr233 = fourccCode('B', 'G', 'R', '8'),
|
||||
xrgb4444 = fourccCode('X', 'R', '1', '2'),
|
||||
xbgr4444 = fourccCode('X', 'B', '1', '2'),
|
||||
rgbx4444 = fourccCode('R', 'X', '1', '2'),
|
||||
bgrx4444 = fourccCode('B', 'X', '1', '2'),
|
||||
argb4444 = fourccCode('A', 'R', '1', '2'),
|
||||
abgr4444 = fourccCode('A', 'B', '1', '2'),
|
||||
rgba4444 = fourccCode('R', 'A', '1', '2'),
|
||||
bgra4444 = fourccCode('B', 'A', '1', '2'),
|
||||
xrgb1555 = fourccCode('X', 'R', '1', '5'),
|
||||
xbgr1555 = fourccCode('X', 'B', '1', '5'),
|
||||
rgbx5551 = fourccCode('R', 'X', '1', '5'),
|
||||
bgrx5551 = fourccCode('B', 'X', '1', '5'),
|
||||
argb1555 = fourccCode('A', 'R', '1', '5'),
|
||||
abgr1555 = fourccCode('A', 'B', '1', '5'),
|
||||
rgba5551 = fourccCode('R', 'A', '1', '5'),
|
||||
bgra5551 = fourccCode('B', 'A', '1', '5'),
|
||||
rgb565 = fourccCode('R', 'G', '1', '6'),
|
||||
bgr565 = fourccCode('B', 'G', '1', '6'),
|
||||
rgb888 = fourccCode('R', 'G', '2', '4'),
|
||||
bgr888 = fourccCode('B', 'G', '2', '4'),
|
||||
xrgb8888 = fourccCode('X', 'R', '2', '4'),
|
||||
xbgr8888 = fourccCode('X', 'B', '2', '4'),
|
||||
rgbx8888 = fourccCode('R', 'X', '2', '4'),
|
||||
bgrx8888 = fourccCode('B', 'X', '2', '4'),
|
||||
argb8888 = fourccCode('A', 'R', '2', '4'),
|
||||
abgr8888 = fourccCode('A', 'B', '2', '4'),
|
||||
rgba8888 = fourccCode('R', 'A', '2', '4'),
|
||||
bgra8888 = fourccCode('B', 'A', '2', '4'),
|
||||
xrgb2101010 = fourccCode('X', 'R', '3', '0'),
|
||||
xbgr2101010 = fourccCode('X', 'B', '3', '0'),
|
||||
rgbx1010102 = fourccCode('R', 'X', '3', '0'),
|
||||
bgrx1010102 = fourccCode('B', 'X', '3', '0'),
|
||||
argb2101010 = fourccCode('A', 'R', '3', '0'),
|
||||
abgr2101010 = fourccCode('A', 'B', '3', '0'),
|
||||
rgba1010102 = fourccCode('R', 'A', '3', '0'),
|
||||
bgra1010102 = fourccCode('B', 'A', '3', '0'),
|
||||
xrgb16161616 = fourccCode('X', 'R', '4', '8'),
|
||||
xbgr16161616 = fourccCode('X', 'B', '4', '8'),
|
||||
argb16161616 = fourccCode('A', 'R', '4', '8'),
|
||||
abgr16161616 = fourccCode('A', 'B', '4', '8'),
|
||||
xrgb16161616f = fourccCode('X', 'R', '4', 'H'),
|
||||
xbgr16161616f = fourccCode('X', 'B', '4', 'H'),
|
||||
argb16161616f = fourccCode('A', 'R', '4', 'H'),
|
||||
abgr16161616f = fourccCode('A', 'B', '4', 'H'),
|
||||
axbxgxrx106106106106 = fourccCode('A', 'B', '1', '0'),
|
||||
yuyv = fourccCode('Y', 'U', 'Y', 'V'),
|
||||
yvyu = fourccCode('Y', 'V', 'Y', 'U'),
|
||||
uyvy = fourccCode('U', 'Y', 'V', 'Y'),
|
||||
vyuy = fourccCode('V', 'Y', 'U', 'Y'),
|
||||
ayuv = fourccCode('A', 'Y', 'U', 'V'),
|
||||
avuy8888 = fourccCode('A', 'V', 'U', 'Y'),
|
||||
xyuv8888 = fourccCode('X', 'Y', 'U', 'V'),
|
||||
xvuy8888 = fourccCode('X', 'V', 'U', 'Y'),
|
||||
vuy888 = fourccCode('V', 'U', '2', '4'),
|
||||
vuy101010 = fourccCode('V', 'U', '3', '0'),
|
||||
y210 = fourccCode('Y', '2', '1', '0'),
|
||||
y212 = fourccCode('Y', '2', '1', '2'),
|
||||
y216 = fourccCode('Y', '2', '1', '6'),
|
||||
y410 = fourccCode('Y', '4', '1', '0'),
|
||||
y412 = fourccCode('Y', '4', '1', '2'),
|
||||
y416 = fourccCode('Y', '4', '1', '6'),
|
||||
xvyu2101010 = fourccCode('X', 'V', '3', '0'),
|
||||
xvyu12_16161616 = fourccCode('X', 'V', '3', '6'),
|
||||
xvyu16161616 = fourccCode('X', 'V', '4', '8'),
|
||||
y0l0 = fourccCode('Y', '0', 'L', '0'),
|
||||
x0l0 = fourccCode('X', '0', 'L', '0'),
|
||||
y0l2 = fourccCode('Y', '0', 'L', '2'),
|
||||
x0l2 = fourccCode('X', '0', 'L', '2'),
|
||||
yuv420_8bit = fourccCode('Y', 'U', '0', '8'),
|
||||
yuv420_10bit = fourccCode('Y', 'U', '1', '0'),
|
||||
xrgb8888_a8 = fourccCode('X', 'R', 'A', '8'),
|
||||
xbgr8888_a8 = fourccCode('X', 'B', 'A', '8'),
|
||||
rgbx8888_a8 = fourccCode('R', 'X', 'A', '8'),
|
||||
bgrx8888_a8 = fourccCode('B', 'X', 'A', '8'),
|
||||
rgb888_a8 = fourccCode('R', '8', 'A', '8'),
|
||||
bgr888_a8 = fourccCode('B', '8', 'A', '8'),
|
||||
rgb565_a8 = fourccCode('R', '5', 'A', '8'),
|
||||
bgr565_a8 = fourccCode('B', '5', 'A', '8'),
|
||||
nv12 = fourccCode('N', 'V', '1', '2'),
|
||||
nv21 = fourccCode('N', 'V', '2', '1'),
|
||||
nv16 = fourccCode('N', 'V', '1', '6'),
|
||||
nv61 = fourccCode('N', 'V', '6', '1'),
|
||||
nv24 = fourccCode('N', 'V', '2', '4'),
|
||||
nv42 = fourccCode('N', 'V', '4', '2'),
|
||||
nv15 = fourccCode('N', 'V', '1', '5'),
|
||||
nv20 = fourccCode('N', 'V', '2', '0'),
|
||||
nv30 = fourccCode('N', 'V', '3', '0'),
|
||||
p210 = fourccCode('P', '2', '1', '0'),
|
||||
p010 = fourccCode('P', '0', '1', '0'),
|
||||
p012 = fourccCode('P', '0', '1', '2'),
|
||||
p016 = fourccCode('P', '0', '1', '6'),
|
||||
p030 = fourccCode('P', '0', '3', '0'),
|
||||
q410 = fourccCode('Q', '4', '1', '0'),
|
||||
q401 = fourccCode('Q', '4', '0', '1'),
|
||||
yuv410 = fourccCode('Y', 'U', 'V', '9'),
|
||||
yvu410 = fourccCode('Y', 'V', 'U', '9'),
|
||||
yuv411 = fourccCode('Y', 'U', '1', '1'),
|
||||
yvu411 = fourccCode('Y', 'V', '1', '1'),
|
||||
yuv420 = fourccCode('Y', 'U', '1', '2'),
|
||||
yvu420 = fourccCode('Y', 'V', '1', '2'),
|
||||
yuv422 = fourccCode('Y', 'U', '1', '6'),
|
||||
yvu422 = fourccCode('Y', 'V', '1', '6'),
|
||||
yuv444 = fourccCode('Y', 'U', '2', '4'),
|
||||
yvu444 = fourccCode('Y', 'V', '2', '4'),
|
||||
|
||||
_, // Some formats involved with dmabuf aren't defined here
|
||||
|
||||
fn fourccCode(a: u8, b: u8, c: u8, d: u8) u32 {
|
||||
return @as(u32, a) | (@as(u32, b) << 8) | (@as(u32, c) << 16) | (@as(u32, d) << 24);
|
||||
}
|
||||
};
|
||||
|
||||
pub const FormatModifiers = packed struct(u64) {
|
||||
raw: u56,
|
||||
vendor: Vendor,
|
||||
|
||||
pub fn resolve(self: FormatModifiers) Resolved {
|
||||
return switch (self.vendor) {
|
||||
.none => .{ .none = .resolve(self.raw) },
|
||||
.intel => .{ .intel = self.raw }, // TODO
|
||||
.amd => .{ .amd = self.raw }, // TODO
|
||||
.nvidia => .{ .nvidia = .resolve(self.raw) },
|
||||
.samsung => .{ .samsung = self.raw }, // TODO
|
||||
.qualcomm => .{ .qualcomm = self.raw }, // TODO
|
||||
.vivante => .{ .vivante = self.raw }, // TODO
|
||||
.broadcom => .{ .broadcom = self.raw }, // TODO
|
||||
.arm => .{ .arm = self.raw }, // TODO
|
||||
.allwinner => .{ .allwinner = self.raw }, // TODO
|
||||
.amlogic => .{ .amlogic = self.raw }, // TODO
|
||||
.mtk => .{ .mtk = self.raw }, // TODO
|
||||
.apple => .{ .apple = self.raw }, // TODO
|
||||
};
|
||||
}
|
||||
|
||||
pub const Vendor = enum(u8) {
|
||||
none = 0,
|
||||
intel = 0x01,
|
||||
amd = 0x02,
|
||||
nvidia = 0x03,
|
||||
samsung = 0x04,
|
||||
qualcomm = 0x05,
|
||||
vivante = 0x06,
|
||||
broadcom = 0x07,
|
||||
arm = 0x08,
|
||||
allwinner = 0x09,
|
||||
amlogic = 0x0a,
|
||||
mtk = 0x0b,
|
||||
apple = 0x0c,
|
||||
};
|
||||
|
||||
pub const Resolved = union(Vendor) {
|
||||
none: None,
|
||||
intel: u56,
|
||||
amd: u56,
|
||||
nvidia: Nvidia,
|
||||
samsung: u56,
|
||||
qualcomm: u56,
|
||||
vivante: u56,
|
||||
broadcom: u56,
|
||||
arm: u56,
|
||||
allwinner: u56,
|
||||
amlogic: u56,
|
||||
mtk: u56,
|
||||
apple: u56,
|
||||
};
|
||||
|
||||
pub const None = union(enum) {
|
||||
invalid: void,
|
||||
unknown: u56,
|
||||
|
||||
pub fn resolve(raw: u56) None {
|
||||
return switch (raw) {
|
||||
0xffffffffffffff => .invalid,
|
||||
else => |val| .{ .unknown = val },
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub const Nvidia = union(enum) {
|
||||
tegra_tiled: void,
|
||||
block_linear_16bx2_1_gob: void,
|
||||
block_linear_16bx2_2_gob: void,
|
||||
block_linear_16bx2_4_gob: void,
|
||||
block_linear_16bx2_8_gob: void,
|
||||
block_linear_16bx2_16_gob: void,
|
||||
block_linear_16bx2_32_gob: void,
|
||||
block_linear_2d: BlockLinear2D,
|
||||
|
||||
pub fn resolve(raw: u56) Nvidia {
|
||||
return switch (raw) {
|
||||
1 => .tegra_tiled,
|
||||
bl2dCode(0) => .block_linear_16bx2_1_gob,
|
||||
bl2dCode(1) => .block_linear_16bx2_2_gob,
|
||||
bl2dCode(2) => .block_linear_16bx2_4_gob,
|
||||
bl2dCode(3) => .block_linear_16bx2_8_gob,
|
||||
bl2dCode(4) => .block_linear_16bx2_16_gob,
|
||||
bl2dCode(5) => .block_linear_16bx2_32_gob,
|
||||
else => |val| .{ .block_linear_2d = .fromRaw(val) },
|
||||
};
|
||||
}
|
||||
|
||||
pub const BlockLinear2D = struct {
|
||||
height: u16,
|
||||
page_kind: u8,
|
||||
gob_height: GobHeight,
|
||||
page_kind_generation: PageKindGeneration,
|
||||
sector_layout: SectorLayout,
|
||||
compression_type: CompressionType,
|
||||
|
||||
fn fromRaw(raw: u56) BlockLinear2D {
|
||||
const h: u4 = @intCast(raw & 0xf);
|
||||
const k: u8 = @intCast((raw >> 12) & 0xff);
|
||||
const g: u2 = @intCast((raw >> 20) & 0x3);
|
||||
const s: u1 = @intCast((raw >> 22) & 0x1);
|
||||
const c: u3 = @intCast((raw >> 23) & 0x7);
|
||||
|
||||
const height: u16 = @as(u16, 1) << h;
|
||||
const page_kind: u8 = k;
|
||||
const gob_height: GobHeight = switch (g) {
|
||||
1 => .@"4",
|
||||
0, 2 => .@"8",
|
||||
else => unreachable,
|
||||
};
|
||||
const page_kind_generation: PageKindGeneration = @enumFromInt(g);
|
||||
const sector_layout: SectorLayout = @enumFromInt(s);
|
||||
const compression_type: CompressionType = @enumFromInt(c);
|
||||
|
||||
return BlockLinear2D{
|
||||
.height = height,
|
||||
.page_kind = page_kind,
|
||||
.gob_height = gob_height,
|
||||
.page_kind_generation = page_kind_generation,
|
||||
.sector_layout = sector_layout,
|
||||
.compression_type = compression_type,
|
||||
};
|
||||
}
|
||||
|
||||
pub const GobHeight = enum {
|
||||
@"4",
|
||||
@"8",
|
||||
reserved,
|
||||
};
|
||||
|
||||
pub const PageKindGeneration = enum {
|
||||
@"Fermi - Volta, Tegra K1+",
|
||||
@"G80 - GT2XX",
|
||||
@"Turing+",
|
||||
};
|
||||
|
||||
pub const SectorLayout = enum {
|
||||
@"Tegra K1 - Tegra Parker/TX2",
|
||||
@"Desktop GPU and Tegra Xavier+",
|
||||
};
|
||||
|
||||
pub const CompressionType = enum {
|
||||
none,
|
||||
@"ROP/3D, layout 1",
|
||||
@"ROP/3D, layout 2",
|
||||
@"CDE horizontal",
|
||||
@"CDE vertical",
|
||||
};
|
||||
};
|
||||
|
||||
fn bl2dCode(h: u4) u56 {
|
||||
return @as(u56, h) | 0x10;
|
||||
}
|
||||
};
|
||||
};
|
||||
+554
@@ -0,0 +1,554 @@
|
||||
const std = @import("std");
|
||||
const IOCTL = std.os.linux.IOCTL;
|
||||
|
||||
pub const IoctlError = std.posix.UnexpectedError;
|
||||
|
||||
pub fn ioctl(fd: std.posix.fd_t, request: Request, arg: anytype) IoctlError!void {
|
||||
const casted: usize = switch (@typeInfo(@TypeOf(arg))) {
|
||||
.int => @intCast(arg),
|
||||
.@"enum" => @intCast(@intFromEnum(arg)),
|
||||
.pointer => @intFromPtr(arg),
|
||||
else => @compileError("Unsupported type: " ++ @typeName(@TypeOf(arg))),
|
||||
};
|
||||
|
||||
const rc = std.posix.system.ioctl(fd, @intCast(@intFromEnum(request)), casted);
|
||||
|
||||
return switch (std.posix.errno(rc)) {
|
||||
.SUCCESS => {},
|
||||
else => |err| std.posix.unexpectedErrno(err),
|
||||
};
|
||||
}
|
||||
|
||||
pub const Request = enum(u32) {
|
||||
version = drm_iowr(0x00, Version),
|
||||
get_unique = drm_iowr(0x01, Unique),
|
||||
get_magic = drm_ior(0x02, Auth),
|
||||
irq_busid = drm_iowr(0x03, IrqBusid),
|
||||
get_map = drm_iowr(0x04, Map),
|
||||
get_client = drm_iowr(0x05, Client),
|
||||
get_stats = drm_ior(0x06, Stats),
|
||||
set_version = drm_iowr(0x07, SetVersion),
|
||||
// modeset_ctl = drm_iow(0x08, drm_modeset_ctl),
|
||||
// gem_close = drm_iow(0x09, drm_gem_close),
|
||||
// gem_flink = drm_iowr(0x0a, drm_gem_flink),
|
||||
// gem_open = drm_iowr(0x0b, drm_gem_open),
|
||||
// get_cap = drm_iowr(0x0c, drm_get_cap),
|
||||
// set_client_cap = drm_iow(0x0d, drm_set_client_cap),
|
||||
set_unique = drm_iow(0x10, Unique),
|
||||
auth_magic = drm_iow(0x11, Auth),
|
||||
// block = drm_iowr(0x12, drm_block),
|
||||
// unblock = drm_iowr(0x13, drm_block),
|
||||
// control = drm_iow(0x14, drm_control),
|
||||
add_map = drm_iowr(0x15, Map),
|
||||
// add_bufs = drm_iowr(0x16, drm_buf_desc),
|
||||
// mark_bufs = drm_iow(0x17, drm_buf_desc),
|
||||
// info_bufs = drm_iowr(0x18, drm_buf_info),
|
||||
// map_bufs = drm_iowr(0x19, drm_buf_map),
|
||||
// free_bufs = drm_iow(0x1a, drm_buf_free),
|
||||
rm_map = drm_iow(0x1b, Map),
|
||||
// set_sarea_ctx = drm_iow(0x1c, drm_ctx_priv_map),
|
||||
// get_sarea_ctx = drm_iowr(0x1d, drm_ctx_priv_map),
|
||||
set_master = drm_io(0x1e),
|
||||
drop_master = drm_io(0x1f),
|
||||
add_ctx = drm_iowr(0x20, Ctx),
|
||||
rm_ctx = drm_iowr(0x21, Ctx),
|
||||
mod_ctx = drm_iow(0x22, Ctx),
|
||||
get_ctx = drm_iowr(0x23, Ctx),
|
||||
switch_ctx = drm_iow(0x24, Ctx),
|
||||
new_ctx = drm_iow(0x25, Ctx),
|
||||
res_ctx = drm_iowr(0x26, CtxRes),
|
||||
// add_draw = drm_iowr(0x27, drm_draw),
|
||||
// rm_draw = drm_iowr(0x28, drm_draw),
|
||||
// dma = drm_iowr(0x29, drm_dma),
|
||||
// lock = drm_iow(0x2a, drm_lock),
|
||||
// unlock = drm_iow(0x2b, drm_lock),
|
||||
// finish = drm_iow(0x2c, drm_lock),
|
||||
// prime_handle_to_fd = drm_iowr(0x2d, drm_prime_handle),
|
||||
// prime_fd_to_handle = drm_iowr(0x2e, drm_prime_handle),
|
||||
agp_acquire = drm_io(0x30),
|
||||
agp_release = drm_io(0x31),
|
||||
// agp_enable = drm_iow(0x32, drm_agp_mode),
|
||||
// agp_info = drm_ior(0x33, drm_agp_info),
|
||||
// agp_alloc = drm_iowr(0x34, drm_agp_buffer),
|
||||
// agp_free = drm_iow(0x35, drm_agp_buffer),
|
||||
// agp_bind = drm_iow(0x36, drm_agp_binding),
|
||||
// agp_unbind = drm_iow(0x37, drm_agp_binding),
|
||||
// sg_alloc = drm_iowr(0x38, drm_scatter_gather),
|
||||
// sg_free = drm_iow(0x39, drm_scatter_gather),
|
||||
// wait_vblank = drm_iowr(0x3a, drm_wait_vblank),
|
||||
// crtc_get_sequence = drm_iowr(0x3b, drm_crtc_get_sequence),
|
||||
// crtc_queue_sequence = drm_iowr(0x3c, drm_crtc_queue_sequence),
|
||||
// update_draw = drm_iow(0x3f, drm_update_draw),
|
||||
mode_getresources = drm_iowr(0xA0, mode.CardRes),
|
||||
mode_getcrtc = drm_iowr(0xA1, mode.Crtc),
|
||||
mode_setcrtc = drm_iowr(0xA2, mode.Crtc),
|
||||
mode_cursor = drm_iowr(0xA3, mode.Cursor),
|
||||
mode_getgamma = drm_iowr(0xA4, mode.Crtc.Lut),
|
||||
mode_setgamma = drm_iowr(0xA5, mode.Crtc.Lut),
|
||||
mode_getencoder = drm_iowr(0xA6, mode.GetEncoder),
|
||||
mode_getconnector = drm_iowr(0xA7, mode.GetConnector),
|
||||
mode_getproperty = drm_iowr(0xAA, mode.GetProperty),
|
||||
mode_setproperty = drm_iowr(0xAB, mode.ConnectorSetProperty),
|
||||
mode_getpropblob = drm_iowr(0xAC, mode.GetBlob),
|
||||
mode_getfb = drm_iowr(0xAD, mode.FbCmd),
|
||||
mode_addfb = drm_iowr(0xAE, mode.FbCmd),
|
||||
mode_rmfb = drm_iowr(0xAF, c_uint),
|
||||
mode_page_flip = drm_iowr(0xB0, mode.CrtcPageFlip),
|
||||
mode_dirtyfb = drm_iowr(0xB1, mode.FbDirtyCmd),
|
||||
mode_create_dumb = drm_iowr(0xB2, mode.CreateDumb),
|
||||
mode_map_dumb = drm_iowr(0xB3, mode.MapDumb),
|
||||
mode_destroy_dumb = drm_iowr(0xB4, mode.DestroyDumb),
|
||||
mode_getplaneresources = drm_iowr(0xB5, mode.GetPlaneRes),
|
||||
mode_getplane = drm_iowr(0xB6, mode.GetPlane),
|
||||
mode_setplane = drm_iowr(0xB7, mode.SetPlane),
|
||||
mode_addfb2 = drm_iowr(0xB8, mode.FbCmd2),
|
||||
mode_obj_getproperties = drm_iowr(0xB9, mode.ObjGetProperties),
|
||||
mode_obj_setproperty = drm_iowr(0xBA, mode.ObjSetProperty),
|
||||
mode_cursor2 = drm_iowr(0xBB, mode.Cursor2),
|
||||
mode_atomic = drm_iowr(0xBC, mode.Atomic),
|
||||
mode_createpropblob = drm_iowr(0xBD, mode.CreateBlob),
|
||||
mode_destroypropblob = drm_iowr(0xBE, mode.DestroyBlob),
|
||||
// syncobj_create = drm_iowr(0xBF, drm_syncobj_create),
|
||||
// syncobj_destroy = drm_iowr(0xC0, drm_syncobj_destroy),
|
||||
// syncobj_handle_to_fd = drm_iowr(0xC1, drm_syncobj_handle),
|
||||
// syncobj_fd_to_handle = drm_iowr(0xC2, drm_syncobj_handle),
|
||||
// syncobj_wait = drm_iowr(0xC3, drm_syncobj_wait),
|
||||
// syncobj_reset = drm_iowr(0xC4, drm_syncobj_array),
|
||||
// syncobj_signal = drm_iowr(0xC5, drm_syncobj_array),
|
||||
mode_create_lease = drm_iowr(0xC6, mode.CreateLease),
|
||||
mode_list_lessees = drm_iowr(0xC7, mode.ListLessees),
|
||||
mode_get_lease = drm_iowr(0xC8, mode.GetLease),
|
||||
mode_revoke_lease = drm_iowr(0xC9, mode.RevokeLease),
|
||||
// syncobj_timeline_wait = drm_iowr(0xCA, drm_syncobj_timeline_wait),
|
||||
// syncobj_query = drm_iowr(0xCB, drm_syncobj_timeline_array),
|
||||
// syncobj_transfer = drm_iowr(0xCC, drm_syncobj_transfer),
|
||||
// syncobj_timeline_signal = drm_iowr(0xCD, drm_syncobj_timeline_array),
|
||||
mode_getfb2 = drm_iowr(0xCE, mode.FbCmd2),
|
||||
// syncobj_eventfd = drm_iowr(0xCF, drm_syncobj_eventfd),
|
||||
mode_closefb = drm_iowr(0xD0, mode.CloseFb),
|
||||
// set_client_name = drm_iowr(0xD1, drm_set_client_name),
|
||||
// gem_change_handle = drm_iowr(0xD2, drm_gem_change_handle),
|
||||
|
||||
const io_type = 'd';
|
||||
|
||||
fn drm_io(nr: u8) u32 {
|
||||
return IOCTL.IO(io_type, nr);
|
||||
}
|
||||
|
||||
fn drm_ior(nr: u8, comptime T: type) u32 {
|
||||
return IOCTL.IOR(io_type, nr, T);
|
||||
}
|
||||
|
||||
fn drm_iow(nr: u8, comptime T: type) u32 {
|
||||
return IOCTL.IOW(io_type, nr, T);
|
||||
}
|
||||
|
||||
fn drm_iowr(nr: u8, comptime T: type) u32 {
|
||||
return IOCTL.IOWR(io_type, nr, T);
|
||||
}
|
||||
};
|
||||
|
||||
pub const Magic = c_uint;
|
||||
|
||||
pub const Context = c_ulong;
|
||||
|
||||
pub const Version = extern struct {
|
||||
version_major: c_int,
|
||||
version_minor: c_int,
|
||||
version_patch: c_int,
|
||||
name_len: c_ulong,
|
||||
name: [*:0]const u8,
|
||||
date_len: c_ulong,
|
||||
date: [*:0]const u8,
|
||||
desc_len: c_ulong,
|
||||
desc: [*:0]const u8,
|
||||
};
|
||||
|
||||
pub const Unique = extern struct {
|
||||
unique_len: c_ulong,
|
||||
unique: [*:0]const u8,
|
||||
};
|
||||
|
||||
pub const Auth = extern struct {
|
||||
magic: Magic,
|
||||
};
|
||||
|
||||
pub const IrqBusid = extern struct {
|
||||
irq: c_int,
|
||||
busnum: c_int,
|
||||
devnum: c_int,
|
||||
funcnum: c_int,
|
||||
};
|
||||
|
||||
pub const Map = extern struct {
|
||||
offset: c_ulong,
|
||||
size: c_ulong,
|
||||
type: Type,
|
||||
flags: Flags,
|
||||
handle: *anyopaque,
|
||||
mtrr: c_int,
|
||||
|
||||
pub const Type = enum(c_int) {
|
||||
frame_buffer = 0,
|
||||
registers = 1,
|
||||
shm = 2,
|
||||
agp = 3,
|
||||
scatter_gather = 4,
|
||||
consistent = 5,
|
||||
};
|
||||
|
||||
pub const Flags = packed struct(c_int) {
|
||||
restricted: bool = false,
|
||||
read_only: bool = false,
|
||||
locked: bool = false,
|
||||
kernel: bool = false,
|
||||
write_combining: bool = false,
|
||||
contains_lock: bool = false,
|
||||
removable: bool = false,
|
||||
driver: bool = false,
|
||||
_: @Int(.signed, @bitSizeOf(c_int) - 8) = 0,
|
||||
};
|
||||
};
|
||||
|
||||
pub const Client = extern struct {
|
||||
idx: c_int,
|
||||
auth: c_int,
|
||||
pid: c_ulong,
|
||||
uid: c_ulong,
|
||||
magic: Magic,
|
||||
iocs: c_ulong,
|
||||
};
|
||||
|
||||
pub const Stats = extern struct {
|
||||
count: c_ulong,
|
||||
data: [15]Stat,
|
||||
|
||||
pub const Stat = extern struct {
|
||||
value: c_ulong,
|
||||
type: Type,
|
||||
|
||||
pub const Type = enum(c_int) {
|
||||
lock,
|
||||
opens,
|
||||
closes,
|
||||
ioctls,
|
||||
locks,
|
||||
unlocks,
|
||||
value,
|
||||
byte,
|
||||
count,
|
||||
irq,
|
||||
primary,
|
||||
secondary,
|
||||
dma,
|
||||
special,
|
||||
missed,
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
pub const SetVersion = extern struct {
|
||||
di_major: c_int,
|
||||
di_minor: c_int,
|
||||
dd_major: c_int,
|
||||
dd_minor: c_int,
|
||||
};
|
||||
|
||||
pub const Ctx = extern struct {
|
||||
handle: Context,
|
||||
flags: Flags,
|
||||
|
||||
pub const Flags = packed struct(c_int) {
|
||||
preserved: bool = false,
|
||||
@"2d_only": bool = false,
|
||||
_: @Int(.signed, @bitSizeOf(c_int) - 2) = 0,
|
||||
};
|
||||
};
|
||||
|
||||
pub const CtxRes = extern struct {
|
||||
count: c_int,
|
||||
contexts: [*]Ctx,
|
||||
};
|
||||
|
||||
pub const mode = struct {
|
||||
pub const display_mode_len = 32;
|
||||
pub const prop_name_len = 32;
|
||||
|
||||
pub const CardRes = extern struct {
|
||||
fb_id_ptr: u64,
|
||||
crtc_id_ptr: u64,
|
||||
connector_id_ptr: u64,
|
||||
encoder_id_ptr: u64,
|
||||
count_fbs: u32,
|
||||
count_crtcs: u32,
|
||||
count_connectors: u32,
|
||||
count_encoders: u32,
|
||||
min_width: u32,
|
||||
max_width: u32,
|
||||
min_height: u32,
|
||||
max_height: u32,
|
||||
};
|
||||
|
||||
pub const Crtc = extern struct {
|
||||
set_connectors_ptr: u64,
|
||||
count_connectors: u32,
|
||||
crtc_id: u32,
|
||||
fb_id: u32,
|
||||
x: u32,
|
||||
y: u32,
|
||||
gamma_size: u32,
|
||||
mode_valid: u32,
|
||||
mode: Modeinfo,
|
||||
|
||||
pub const Lut = extern struct {
|
||||
crtc_id: u32,
|
||||
gamma_size: u32,
|
||||
red: u64,
|
||||
green: u64,
|
||||
blue: u64,
|
||||
};
|
||||
};
|
||||
|
||||
pub const Modeinfo = extern struct {
|
||||
clock: u32,
|
||||
hdisplay: u16,
|
||||
hsync_start: u16,
|
||||
hsync_end: u16,
|
||||
htotal: u16,
|
||||
hskew: u16,
|
||||
vdisplay: u16,
|
||||
vsync_start: u16,
|
||||
vsync_end: u16,
|
||||
vtotal: u16,
|
||||
vscan: u16,
|
||||
vrefresh: u32,
|
||||
flags: u32,
|
||||
type: u32,
|
||||
|
||||
name: [display_mode_len]u8,
|
||||
};
|
||||
|
||||
pub const Cursor = extern struct {
|
||||
flags: u32,
|
||||
crtc_id: u32,
|
||||
x: i32,
|
||||
y: i32,
|
||||
width: u32,
|
||||
height: u32,
|
||||
handle: u32,
|
||||
};
|
||||
|
||||
pub const GetEncoder = extern struct {
|
||||
encoder_id: u32,
|
||||
encoder_type: u32,
|
||||
crtc_id: u32,
|
||||
possible_crtcs: u32,
|
||||
possible_clones: u32,
|
||||
};
|
||||
|
||||
pub const GetConnector = extern struct {
|
||||
encoders_ptr: u64,
|
||||
modes_ptr: u64,
|
||||
props_ptr: u64,
|
||||
prop_values_ptr: u64,
|
||||
count_modes: u32,
|
||||
count_props: u32,
|
||||
count_encoders: u32,
|
||||
encoder_id: u32,
|
||||
connector_id: u32,
|
||||
connector_type: u32,
|
||||
connector_type_id: u32,
|
||||
connection: u32,
|
||||
mm_width: u32,
|
||||
mm_height: u32,
|
||||
subpixel: u32,
|
||||
pad: u32,
|
||||
};
|
||||
|
||||
pub const GetProperty = extern struct {
|
||||
values_ptr: u64,
|
||||
enum_blob_ptr: u64,
|
||||
prop_id: u32,
|
||||
flags: u32,
|
||||
name: [prop_name_len]u8,
|
||||
count_values: u32,
|
||||
count_enum_blobs: u32,
|
||||
};
|
||||
|
||||
pub const ConnectorSetProperty = extern struct {
|
||||
value: u64,
|
||||
prop_id: u32,
|
||||
connector_id: u32,
|
||||
};
|
||||
|
||||
pub const GetBlob = extern struct {
|
||||
blob_id: u32,
|
||||
length: u32,
|
||||
data: u64,
|
||||
};
|
||||
|
||||
pub const FbCmd = extern struct {
|
||||
fb_id: u32,
|
||||
width: u32,
|
||||
height: u32,
|
||||
pitch: u32,
|
||||
bpp: u32,
|
||||
depth: u32,
|
||||
handle: u32,
|
||||
};
|
||||
|
||||
pub const CrtcPageFlip = extern struct {
|
||||
crtc_id: u32,
|
||||
fb_id: u32,
|
||||
flags: u32,
|
||||
reserved: u32,
|
||||
user_data: u64,
|
||||
};
|
||||
|
||||
pub const FbDirtyCmd = extern struct {
|
||||
fb_id: u32,
|
||||
flags: u32,
|
||||
color: u32,
|
||||
num_clips: u32,
|
||||
clips_ptr: u64,
|
||||
};
|
||||
|
||||
pub const CreateDumb = extern struct {
|
||||
height: u32,
|
||||
width: u32,
|
||||
bpp: u32,
|
||||
flags: u32,
|
||||
handle: u32,
|
||||
pitch: u32,
|
||||
size: u64,
|
||||
};
|
||||
|
||||
pub const MapDumb = extern struct {
|
||||
handle: u32,
|
||||
pad: u32,
|
||||
offset: u64,
|
||||
};
|
||||
|
||||
pub const DestroyDumb = extern struct {
|
||||
handle: u32,
|
||||
};
|
||||
|
||||
pub const GetPlaneRes = extern struct {
|
||||
plane_id_ptr: u64,
|
||||
count_planes: u32,
|
||||
};
|
||||
|
||||
pub const GetPlane = extern struct {
|
||||
plane_id: u32,
|
||||
crtc_id: u32,
|
||||
fb_id: u32,
|
||||
possible_crtcs: u32,
|
||||
gamma_size: u32,
|
||||
count_format_types: u32,
|
||||
format_type_ptr: u64,
|
||||
};
|
||||
|
||||
pub const SetPlane = extern struct {
|
||||
plane_id: u32,
|
||||
crtc_id: u32,
|
||||
fb_id: u32,
|
||||
flags: u32,
|
||||
crtc_x: i32,
|
||||
crtc_y: i32,
|
||||
crtc_w: u32,
|
||||
crtc_h: u32,
|
||||
src_x: u32,
|
||||
src_y: u32,
|
||||
src_h: u32,
|
||||
src_w: u32,
|
||||
};
|
||||
|
||||
pub const FbCmd2 = extern struct {
|
||||
fb_id: u32,
|
||||
width: u32,
|
||||
height: u32,
|
||||
pixel_format: u32,
|
||||
flags: u32,
|
||||
handles: [4]u32,
|
||||
pitches: [4]u32,
|
||||
offsets: [4]u32,
|
||||
modifier: [4]u64,
|
||||
};
|
||||
|
||||
pub const ObjGetProperties = extern struct {
|
||||
props_ptr: u64,
|
||||
prop_values_ptr: u64,
|
||||
count_props: u32,
|
||||
obj_id: u32,
|
||||
obj_type: u32,
|
||||
};
|
||||
|
||||
pub const ObjSetProperty = extern struct {
|
||||
value: u64,
|
||||
prop_id: u32,
|
||||
obj_id: u32,
|
||||
obj_type: u32,
|
||||
};
|
||||
|
||||
pub const Cursor2 = extern struct {
|
||||
flags: u32,
|
||||
crtc_id: u32,
|
||||
x: i32,
|
||||
y: i32,
|
||||
width: u32,
|
||||
height: u32,
|
||||
handle: u32,
|
||||
hot_x: i32,
|
||||
hot_y: i32,
|
||||
};
|
||||
|
||||
pub const Atomic = extern struct {
|
||||
flags: u32,
|
||||
count_objs: u32,
|
||||
objs_ptr: u64,
|
||||
count_props_ptr: u64,
|
||||
props_ptr: u64,
|
||||
prop_values_ptr: u64,
|
||||
reserved: u64,
|
||||
user_data: u64,
|
||||
};
|
||||
|
||||
pub const CreateBlob = extern struct {
|
||||
data: u64,
|
||||
length: u32,
|
||||
blob_id: u32,
|
||||
};
|
||||
|
||||
pub const DestroyBlob = extern struct {
|
||||
blob_id: u32,
|
||||
};
|
||||
|
||||
pub const CreateLease = extern struct {
|
||||
object_ids: u64,
|
||||
object_count: u32,
|
||||
flags: u32,
|
||||
lessee_id: u32,
|
||||
fd: u32,
|
||||
};
|
||||
|
||||
pub const ListLessees = extern struct {
|
||||
count_lessees: u32,
|
||||
pad: u32,
|
||||
lessees_ptr: u64,
|
||||
};
|
||||
|
||||
pub const GetLease = extern struct {
|
||||
count_objects: u32,
|
||||
pad: u32,
|
||||
objects_ptr: u64,
|
||||
};
|
||||
|
||||
pub const RevokeLease = extern struct {
|
||||
lessee_id: u32,
|
||||
};
|
||||
|
||||
pub const CloseFb = extern struct {
|
||||
fb_id: u32,
|
||||
pad: u32,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user