mode api working through CRTC phase.
This commit is contained in:
+35
-25
@@ -5,34 +5,44 @@ pub fn main(init: std.process.Init) !void {
|
||||
const io = init.io;
|
||||
const gpa = init.gpa;
|
||||
|
||||
const card = try drm.Card.openAuto(io);
|
||||
const card = try drm.mode.Card.openAuto(io);
|
||||
defer card.close(io);
|
||||
const res = try card.getResourcesAlloc(gpa);
|
||||
defer res.deinit(gpa);
|
||||
|
||||
std.log.info("Using drm.Card.getModeAlloc...", .{});
|
||||
const mode_res_1 = try card.getModeAlloc(gpa);
|
||||
defer mode_res_1.deinit(gpa);
|
||||
const connector = try chooseConnector(card, gpa, res.connectors);
|
||||
defer connector.deinit(gpa);
|
||||
std.log.info("Selected connector {}.", .{connector.id});
|
||||
|
||||
std.log.info("Min dimensions: {d}x{d}.", .{ mode_res_1.min_width, mode_res_1.min_height });
|
||||
std.log.info("Max dimensions: {d}x{d}.", .{ mode_res_1.max_width, mode_res_1.max_height });
|
||||
const mode = chooseMode(connector.modes);
|
||||
std.log.info("Selected mode {}x{}@{}.", .{ mode.hdisplay, mode.vdisplay, mode.vrefresh });
|
||||
|
||||
std.log.info("Got {d} fbs: {any}.", .{ mode_res_1.fbs.len, mode_res_1.fbs });
|
||||
std.log.info("Got {d} crtcs: {any}.", .{ mode_res_1.crtcs.len, mode_res_1.crtcs });
|
||||
std.log.info("Got {d} connectors: {any}.", .{ mode_res_1.connectors.len, mode_res_1.connectors });
|
||||
std.log.info("Got {d} encoders: {any}.", .{ mode_res_1.encoders.len, mode_res_1.encoders });
|
||||
const encoder = try card.getEncoder(connector.encoder_id);
|
||||
std.log.info("Selected encoder {} (type: {t}).", .{ encoder.id, encoder.type });
|
||||
|
||||
var fb_buf: [16]u32 = undefined;
|
||||
var crtc_buf: [16]u32 = undefined;
|
||||
var connector_buf: [16]u32 = undefined;
|
||||
var encoder_buf: [16]u32 = undefined;
|
||||
|
||||
std.log.info("Using drm.Card.getModeBuffered...", .{});
|
||||
const mode_res_2 = try card.getModeBuffered(&fb_buf, &crtc_buf, &connector_buf, &encoder_buf);
|
||||
|
||||
std.log.info("Min dimensions: {d}x{d}.", .{ mode_res_2.min_width, mode_res_2.min_height });
|
||||
std.log.info("Max dimensions: {d}x{d}.", .{ mode_res_2.max_width, mode_res_2.max_height });
|
||||
|
||||
std.log.info("Got {d} fbs: {any}.", .{ mode_res_2.fbs.len, mode_res_2.fbs });
|
||||
std.log.info("Got {d} crtcs: {any}.", .{ mode_res_2.crtcs.len, mode_res_2.crtcs });
|
||||
std.log.info("Got {d} connectors: {any}.", .{ mode_res_2.connectors.len, mode_res_2.connectors });
|
||||
std.log.info("Got {d} encoders: {any}.", .{ mode_res_2.encoders.len, mode_res_2.encoders });
|
||||
const crtc = try card.getCrtc(encoder.crtc_id);
|
||||
std.log.info("Selected crtc {} (mode valid: {}).", .{ crtc.id, crtc.mode != null });
|
||||
}
|
||||
|
||||
fn chooseConnector(
|
||||
card: drm.mode.Card,
|
||||
gpa: std.mem.Allocator,
|
||||
connectors: []const u32,
|
||||
) !drm.mode.Connector {
|
||||
for (connectors) |id| {
|
||||
const connector = try card.getConnectorAlloc(gpa, id);
|
||||
if (connector.connection == .connected) return connector;
|
||||
connector.deinit(gpa);
|
||||
}
|
||||
return error.NoConnectedConnectors;
|
||||
}
|
||||
|
||||
fn chooseMode(modes: []const drm.sys.mode.Modeinfo) drm.sys.mode.Modeinfo {
|
||||
var best = modes[0];
|
||||
const best_score = @as(u64, best.hdisplay) * @as(u64, best.vdisplay) * @as(u64, best.vrefresh);
|
||||
for (modes) |mode| {
|
||||
const score = @as(u64, mode.hdisplay) * @as(u64, mode.vdisplay) * @as(u64, mode.vrefresh);
|
||||
if (score > best_score) best = mode;
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
+20
-153
@@ -3,176 +3,43 @@ const format = @import("format.zig");
|
||||
const log = std.log.scoped(.drm);
|
||||
|
||||
pub const sys = @import("sys.zig");
|
||||
pub const mode = @import("mode.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);
|
||||
pub const OpenError = std.Io.File.OpenError || std.Io.Dir.OpenError;
|
||||
|
||||
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;
|
||||
pub fn open(io: std.Io, path: []const u8) OpenError!Card {
|
||||
if (std.fs.path.isAbsolute(path))
|
||||
return std.Io.Dir.openFileAbsolute(io, path, .{ .mode = .read_write });
|
||||
|
||||
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 = try dir.openFile(io, path, .{ .mode = .read_write }) };
|
||||
}
|
||||
|
||||
return Card{ .handle = handle };
|
||||
pub const OpenAutoError = OpenError || std.Io.Dir.Iterator.Error || error{NoDevicesFound};
|
||||
|
||||
pub fn openAuto(io: std.Io) OpenAutoError!Card {
|
||||
const dir = try std.Io.Dir.openDirAbsolute(io, "/dev/dri", .{ .iterate = true });
|
||||
defer dir.close(io);
|
||||
|
||||
var it = dir.iterateAssumeFirstIteration();
|
||||
while (try it.next(io)) |entry| if (entry.kind == .character_device)
|
||||
return Card{ .handle = try dir.openFile(io, entry.name, .{ .mode = .read_write }) };
|
||||
|
||||
return error.NoDevicesFound;
|
||||
}
|
||||
|
||||
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);
|
||||
pub inline fn modeHandle(self: Card) mode.Card {
|
||||
return .{ .handle = self.handle };
|
||||
}
|
||||
};
|
||||
|
||||
+330
@@ -0,0 +1,330 @@
|
||||
const std = @import("std");
|
||||
const sys = @import("sys.zig");
|
||||
const base = @import("drm.zig");
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
pub const Card = struct {
|
||||
handle: std.Io.File,
|
||||
|
||||
pub const OpenError = std.Io.File.OpenError || std.Io.Dir.OpenError;
|
||||
|
||||
pub fn open(io: std.Io, path: []const u8) OpenError!Card {
|
||||
if (std.fs.path.isAbsolute(path))
|
||||
return std.Io.Dir.openFileAbsolute(io, path, .{ .mode = .read_write });
|
||||
|
||||
const dir = try std.Io.Dir.openDirAbsolute(io, "/dev/dri", .{});
|
||||
defer dir.close(io);
|
||||
|
||||
return Card{ .handle = try dir.openFile(io, path, .{ .mode = .read_write }) };
|
||||
}
|
||||
|
||||
pub const OpenAutoError = OpenError || std.Io.Dir.Iterator.Error || error{NoDevicesFound};
|
||||
|
||||
pub fn openAuto(io: std.Io) OpenAutoError!Card {
|
||||
const dir = try std.Io.Dir.openDirAbsolute(io, "/dev/dri", .{ .iterate = true });
|
||||
defer dir.close(io);
|
||||
|
||||
var it = dir.iterateAssumeFirstIteration();
|
||||
while (try it.next(io)) |entry| if (entry.kind == .character_device)
|
||||
return Card{ .handle = try dir.openFile(io, entry.name, .{ .mode = .read_write }) };
|
||||
|
||||
return error.NoDevicesFound;
|
||||
}
|
||||
|
||||
pub fn close(self: Card, io: std.Io) void {
|
||||
self.handle.close(io);
|
||||
}
|
||||
|
||||
pub inline fn baseHandle(self: Card) base.Card {
|
||||
return .{ .handle = self.handle };
|
||||
}
|
||||
|
||||
pub const GetResourcesError = sys.IoctlError || error{OutOfMemory};
|
||||
|
||||
pub fn getResourcesAlloc(self: Card, gpa: Allocator) GetResourcesError!Resources {
|
||||
while (true) {
|
||||
var res = std.mem.zeroes(sys.mode.CardRes);
|
||||
try sys.ioctl(self.handle.handle, .mode_getresources, &res);
|
||||
|
||||
var ret = Resources{
|
||||
.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;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getResourcesBuffered(
|
||||
self: Card,
|
||||
fbs: []u32,
|
||||
crtcs: []u32,
|
||||
connectors: []u32,
|
||||
encoders: []u32,
|
||||
) GetResourcesError!Resources {
|
||||
var res = sys.mode.CardRes{
|
||||
.min_width = 0,
|
||||
.max_width = 0,
|
||||
.min_height = 0,
|
||||
.max_height = 0,
|
||||
.count_fbs = @intCast(fbs.len),
|
||||
.fb_id_ptr = @intFromPtr(fbs.ptr),
|
||||
.count_crtcs = @intCast(crtcs.len),
|
||||
.crtc_id_ptr = @intFromPtr(crtcs.ptr),
|
||||
.count_connectors = @intCast(connectors.len),
|
||||
.connector_id_ptr = @intFromPtr(connectors.ptr),
|
||||
.count_encoders = @intCast(encoders.len),
|
||||
.encoder_id_ptr = @intFromPtr(encoders.ptr),
|
||||
};
|
||||
try sys.ioctl(self.handle.handle, .mode_getresources, &res);
|
||||
|
||||
if (res.count_fbs > fbs.len or
|
||||
res.count_crtcs > crtcs.len or
|
||||
res.count_connectors > connectors.len or
|
||||
res.count_encoders > encoders.len)
|
||||
return error.OutOfMemory;
|
||||
|
||||
return Resources{
|
||||
.min_width = res.min_width,
|
||||
.max_width = res.max_width,
|
||||
.min_height = res.min_height,
|
||||
.max_height = res.max_height,
|
||||
.fbs = fbs[0..res.count_fbs],
|
||||
.crtcs = crtcs[0..res.count_crtcs],
|
||||
.connectors = connectors[0..res.count_connectors],
|
||||
.encoders = encoders[0..res.count_encoders],
|
||||
};
|
||||
}
|
||||
|
||||
pub const GetConnectorError = sys.IoctlError || error{OutOfMemory};
|
||||
|
||||
pub fn getConnectorAlloc(self: Card, gpa: Allocator, id: u32) GetConnectorError!Connector {
|
||||
while (true) {
|
||||
var get_conn = std.mem.zeroInit(sys.mode.GetConnector, .{ .connector_id = id });
|
||||
try sys.ioctl(self.handle.handle, .mode_getconnector, &get_conn);
|
||||
const cached = get_conn;
|
||||
|
||||
const encoders = try gpa.alloc(u32, get_conn.count_encoders);
|
||||
errdefer gpa.free(encoders);
|
||||
|
||||
const modes = try gpa.alloc(sys.mode.Modeinfo, get_conn.count_modes);
|
||||
errdefer gpa.free(modes);
|
||||
|
||||
const props = try gpa.alloc(u32, get_conn.count_props);
|
||||
errdefer gpa.free(props);
|
||||
const prop_values = try gpa.alloc(u64, get_conn.count_props);
|
||||
errdefer gpa.free(prop_values);
|
||||
|
||||
get_conn.encoders_ptr = @intFromPtr(encoders.ptr);
|
||||
get_conn.modes_ptr = @intFromPtr(modes.ptr);
|
||||
get_conn.props_ptr = @intFromPtr(props.ptr);
|
||||
get_conn.prop_values_ptr = @intFromPtr(prop_values.ptr);
|
||||
|
||||
try sys.ioctl(self.handle.handle, .mode_getconnector, &get_conn);
|
||||
|
||||
if (cached.count_encoders < get_conn.count_encoders or
|
||||
cached.count_modes < get_conn.count_modes or
|
||||
cached.count_props < get_conn.count_props)
|
||||
{
|
||||
gpa.free(prop_values);
|
||||
gpa.free(props);
|
||||
gpa.free(modes);
|
||||
gpa.free(encoders);
|
||||
continue;
|
||||
}
|
||||
|
||||
return Connector{
|
||||
.id = id,
|
||||
.encoder_id = get_conn.encoder_id,
|
||||
.connection = @enumFromInt(get_conn.connection),
|
||||
// Unsure why libdrm does this conversion,
|
||||
// but we'll follow suite for compatability.
|
||||
.subpixel = @enumFromInt(get_conn.subpixel + 1),
|
||||
.encoders = encoders[0..get_conn.count_encoders],
|
||||
.modes = modes[0..get_conn.count_modes],
|
||||
.props = props[0..get_conn.count_props],
|
||||
.prop_values = prop_values[0..get_conn.count_props],
|
||||
.mm_width = get_conn.mm_width,
|
||||
.mm_height = get_conn.mm_height,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub inline fn getConnectorBuffered(
|
||||
self: Card,
|
||||
encoders: []u32,
|
||||
modes: []sys.mode.Modeinfo,
|
||||
props: []u32,
|
||||
prop_values: []u64,
|
||||
id: u32,
|
||||
) GetConnectorError!Connector {
|
||||
std.debug.assert(props.len == prop_values.len);
|
||||
var get_conn = std.mem.zeroInit(sys.mode.GetConnector, .{
|
||||
.connector_id = id,
|
||||
.count_encoders = @as(u32, @intCast(encoders.len)),
|
||||
.encoders_ptr = @intFromPtr(encoders.ptr),
|
||||
.count_modes = @as(u32, @intCast(modes.len)),
|
||||
.modes_ptr = @intFromPtr(modes.ptr),
|
||||
.count_props = @as(u32, @intCast(props.len)),
|
||||
.props_ptr = @intFromPtr(props.ptr),
|
||||
.prop_values_ptr = @intFromPtr(prop_values.ptr),
|
||||
});
|
||||
try sys.ioctl(self.handle.handle, .mode_getconnector, &get_conn);
|
||||
|
||||
if (get_conn.count_encoders > encoders.len or
|
||||
get_conn.count_modes > modes.len or
|
||||
get_conn.count_props > props.len)
|
||||
return error.OutOfMemory;
|
||||
|
||||
return Connector{
|
||||
.id = id,
|
||||
.encoder_id = get_conn.encoder_id,
|
||||
.connection = @enumFromInt(get_conn.connection),
|
||||
.subpixel = @enumFromInt(get_conn.subpixel + 1),
|
||||
.encoders = encoders[0..get_conn.count_encoders],
|
||||
.modes = modes[0..get_conn.count_modes],
|
||||
.props = props[0..get_conn.count_props],
|
||||
.prop_values = prop_values[0..get_conn.count_props],
|
||||
.mm_width = get_conn.mm_width,
|
||||
.mm_height = get_conn.mm_height,
|
||||
};
|
||||
}
|
||||
|
||||
pub const GetEncoderError = sys.IoctlError;
|
||||
|
||||
pub fn getEncoder(self: Card, id: u32) GetEncoderError!Encoder {
|
||||
var get_encoder = std.mem.zeroInit(sys.mode.GetEncoder, .{ .encoder_id = id });
|
||||
try sys.ioctl(self.handle.handle, .mode_getencoder, &get_encoder);
|
||||
|
||||
return Encoder{
|
||||
.id = id,
|
||||
.type = get_encoder.encoder_type,
|
||||
.crtc_id = get_encoder.crtc_id,
|
||||
.possible_crtcs = get_encoder.possible_crtcs,
|
||||
.possible_clones = get_encoder.possible_clones,
|
||||
};
|
||||
}
|
||||
|
||||
pub const GetCrtcError = sys.IoctlError;
|
||||
|
||||
pub fn getCrtc(self: Card, id: u32) GetCrtcError!Crtc {
|
||||
var crtc = std.mem.zeroInit(sys.mode.Crtc, .{ .crtc_id = id });
|
||||
try sys.ioctl(self.handle.handle, .mode_getcrtc, &crtc);
|
||||
|
||||
return Crtc{
|
||||
.id = id,
|
||||
.fb_id = crtc.fb_id,
|
||||
.x = crtc.x,
|
||||
.y = crtc.y,
|
||||
.gamma_size = crtc.gamma_size,
|
||||
.mode = if (crtc.mode_valid != 0) crtc.mode else null,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub const Connection = enum(u32) {
|
||||
connected = 1,
|
||||
disconnected = 2,
|
||||
unknown = 3,
|
||||
};
|
||||
|
||||
pub const Subpixel = enum(u32) {
|
||||
unknown = 1,
|
||||
horizontal_rgb = 2,
|
||||
horizontal_bgr = 3,
|
||||
vertical_rgb = 4,
|
||||
vertical_bgr = 5,
|
||||
none = 6,
|
||||
};
|
||||
|
||||
pub const Resources = struct {
|
||||
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: Resources, gpa: Allocator) void {
|
||||
gpa.free(self.encoders);
|
||||
gpa.free(self.connectors);
|
||||
gpa.free(self.crtcs);
|
||||
gpa.free(self.fbs);
|
||||
}
|
||||
};
|
||||
|
||||
pub const Connector = struct {
|
||||
id: u32,
|
||||
encoder_id: u32,
|
||||
connection: Connection,
|
||||
mm_width: u32,
|
||||
mm_height: u32,
|
||||
subpixel: Subpixel,
|
||||
encoders: []const u32,
|
||||
modes: []const sys.mode.Modeinfo,
|
||||
props: []const u32,
|
||||
prop_values: []const u64,
|
||||
|
||||
pub fn deinit(self: Connector, gpa: Allocator) void {
|
||||
gpa.free(self.prop_values);
|
||||
gpa.free(self.props);
|
||||
gpa.free(self.modes);
|
||||
gpa.free(self.encoders);
|
||||
}
|
||||
};
|
||||
|
||||
pub const Encoder = struct {
|
||||
id: u32,
|
||||
type: sys.mode.GetEncoder.Type,
|
||||
crtc_id: u32,
|
||||
possible_crtcs: u32,
|
||||
possible_clones: u32,
|
||||
};
|
||||
|
||||
pub const Crtc = struct {
|
||||
id: u32,
|
||||
fb_id: u32,
|
||||
x: u32,
|
||||
y: u32,
|
||||
gamma_size: u32,
|
||||
mode: ?sys.mode.Modeinfo,
|
||||
};
|
||||
+44
-3
@@ -322,10 +322,39 @@ pub const mode = struct {
|
||||
vtotal: u16,
|
||||
vscan: u16,
|
||||
vrefresh: u32,
|
||||
flags: u32,
|
||||
type: u32,
|
||||
flags: Flags,
|
||||
type: Type,
|
||||
|
||||
name: [display_mode_len]u8,
|
||||
|
||||
pub const Flags = packed struct(u32) {
|
||||
phsync: bool = false,
|
||||
nhsync: bool = false,
|
||||
pvsync: bool = false,
|
||||
nvsync: bool = false,
|
||||
interlace: bool = false,
|
||||
dblscan: bool = false,
|
||||
csync: bool = false,
|
||||
pcsync: bool = false,
|
||||
ncsync: bool = false,
|
||||
hskew: bool = false,
|
||||
_deprecated10: u1 = 0,
|
||||
_deprecated11: u1 = 0,
|
||||
dblclk: bool = false,
|
||||
clkdiv2: bool = false,
|
||||
_: u18 = 0,
|
||||
};
|
||||
|
||||
pub const Type = packed struct(u32) {
|
||||
_deprecated0: u1 = 0,
|
||||
_deprecated1: u1 = 0,
|
||||
_deprecated2: u1 = 0,
|
||||
preferred: bool = false,
|
||||
_deprecated4: u1 = 0,
|
||||
userdef: bool = false,
|
||||
driver: bool = false,
|
||||
_: u25 = 0,
|
||||
};
|
||||
};
|
||||
|
||||
pub const Cursor = extern struct {
|
||||
@@ -340,10 +369,22 @@ pub const mode = struct {
|
||||
|
||||
pub const GetEncoder = extern struct {
|
||||
encoder_id: u32,
|
||||
encoder_type: u32,
|
||||
encoder_type: Type,
|
||||
crtc_id: u32,
|
||||
possible_crtcs: u32,
|
||||
possible_clones: u32,
|
||||
|
||||
pub const Type = enum(u32) {
|
||||
none = 0,
|
||||
dac = 1,
|
||||
tmds = 2,
|
||||
lvds = 3,
|
||||
tvdac = 4,
|
||||
virtual = 5,
|
||||
dsi = 6,
|
||||
dpmst = 7,
|
||||
dpi = 8,
|
||||
};
|
||||
};
|
||||
|
||||
pub const GetConnector = extern struct {
|
||||
|
||||
Reference in New Issue
Block a user