summaryrefslogtreecommitdiff
path: root/src/screen
diff options
context:
space:
mode:
Diffstat (limited to 'src/screen')
-rw-r--r--src/screen/drm/buffer/raw.zig109
-rw-r--r--src/screen/drm/buffer/root.zig32
-rw-r--r--src/screen/drm/card.zig44
-rw-r--r--src/screen/drm/connector/kind.zig (renamed from src/screen/drm/connector/type.zig)2
-rw-r--r--src/screen/drm/connector/root.zig49
-rw-r--r--src/screen/drm/connector/status.zig (renamed from src/screen/drm/connector/connection.zig)2
-rw-r--r--src/screen/drm/crtc.zig89
-rw-r--r--src/screen/drm/crtc/root.zig119
-rw-r--r--src/screen/drm/encoder.zig (renamed from src/screen/drm/encoder/root.zig)32
-rw-r--r--src/screen/drm/encoder/type.zig11
-rw-r--r--src/screen/drm/event.zig4
-rw-r--r--src/screen/drm/frame-buffer/page-flip.zig7
-rw-r--r--src/screen/drm/frame-buffer/root.zig188
-rw-r--r--src/screen/drm/pixel.zig (renamed from src/screen/drm/frame-buffer/pixelformat.zig)12
-rw-r--r--src/screen/drm/request.zig29
-rw-r--r--src/screen/drm/request/connector.zig24
-rw-r--r--src/screen/drm/request/crtc.zig29
-rw-r--r--src/screen/drm/request/encoder.zig9
-rw-r--r--src/screen/drm/request/frame-buffer.zig29
-rw-r--r--src/screen/drm/request/resources.zig15
-rw-r--r--src/screen/drm/request/root.zig55
-rw-r--r--src/screen/drm/resources.zig26
-rw-r--r--src/screen/drm/root.zig9
-rw-r--r--src/screen/main.zig29
24 files changed, 486 insertions, 468 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();
+ }
+};
+
diff --git a/src/screen/drm/card.zig b/src/screen/drm/card.zig
index f1674bb..cff8edf 100644
--- a/src/screen/drm/card.zig
+++ b/src/screen/drm/card.zig
@@ -3,13 +3,7 @@ const os = std.os.linux;
const cerror = @import("../cerror.zig");
-const Resources = @import("resources.zig").Resources;
-const Connector = @import("connector/root.zig").Connector;
-const Encoder = @import("encoder/root.zig").Encoder;
-const Crtc = @import("crtc/root.zig").Crtc;
-const DoubleBuffer = @import("frame-buffer/root.zig").DoubleBuffer;
-const Event = @import("event.zig").Event;
-
+const drm = @import("./root.zig");
pub const Card = struct {
const Self = @This();
@@ -35,32 +29,36 @@ pub const Card = struct {
self.file.close();
}
- pub fn is_kms(self: *Card) !bool {
- const raw_info = Resources.raw_without_ids(self);
- return raw_info.count_crtcs > 0 and raw_info.count_connectors > 0 and raw_info.count_encoders > 0;
+ pub fn resources(self: *Card) !drm.Resources {
+ return drm.Resources.init(self);
}
- pub fn resources(self: *Card) !Resources {
- return Resources.init(self);
+ pub fn connector(self: *Card, id: u32) !drm.Connector {
+ return drm.Connector.init(self, id);
}
- pub fn connector(self: *Card, id: u32) !Connector {
- return Connector.init(self, id);
+ pub fn encoder(self: *Card, id: u32) !drm.Encoder {
+ return drm.Encoder.init(self, id);
}
- pub fn encoder(self: *Card, id: u32) !Encoder {
- return Encoder.init(self, id);
+ pub fn crtc(self: *Card, id: u32) !drm.Crtc {
+ return drm.Crtc.init(self, id);
}
- pub fn crtc(self: *Card, id: u32) !Crtc {
- return Crtc.init(self, id);
+ pub fn create_double_buffer(self: *Card, width: u32, height: u32, bpp: u32) !drm.Buffer {
+ return drm.Buffer.init(self, width, height, bpp);
}
- pub fn create_double_buffer(self: *Card, width: u32, height: u32, bpp: u32) !DoubleBuffer {
- return DoubleBuffer.init(self, width, height, bpp);
+ pub fn request(
+ self: *Self,
+ comptime kind: drm.request.Kind,
+ payload: anytype
+ ) !void {
+ const id = kind.id(@TypeOf(payload));
+ try cerror.from_usize(os.ioctl(self.file.handle, id, @intFromPtr(payload)));
}
- pub fn poll_event(self: *Card, timeout: i32) !?Event {
+ pub fn poll_event(self: *Card, timeout: i32) !?drm.Event {
var pollfd = os.pollfd {
.fd = self.file.handle,
.events = os.POLL.IN,
@@ -70,8 +68,8 @@ pub const Card = struct {
try cerror.from_usize(os.poll(@ptrCast(&pollfd), 1, timeout));
if ((pollfd.revents & os.POLL.IN) != 0) {
- var event = std.mem.zeroes(Event);
- try cerror.from_usize(os.read(self.file.handle, @ptrCast(&event), @sizeOf(Event)));
+ var event = std.mem.zeroes(drm.Event);
+ try cerror.from_usize(os.read(self.file.handle, @ptrCast(&event), @sizeOf(drm.Event)));
return event;
}
diff --git a/src/screen/drm/connector/type.zig b/src/screen/drm/connector/kind.zig
index c813c66..4c89b4a 100644
--- a/src/screen/drm/connector/type.zig
+++ b/src/screen/drm/connector/kind.zig
@@ -1,4 +1,4 @@
-pub const Type = enum(u32) {
+pub const Kind = enum(u32) {
unknown = 0,
vga = 1,
dvi_i = 2,
diff --git a/src/screen/drm/connector/root.zig b/src/screen/drm/connector/root.zig
index 6141899..64686b9 100644
--- a/src/screen/drm/connector/root.zig
+++ b/src/screen/drm/connector/root.zig
@@ -1,36 +1,15 @@
const std = @import("std");
const os = std.os.linux;
-const Drm = @import("../request.zig").Drm;
-const Card = @import("../card.zig").Card;
-const FrameBuffer = @import("../frame-buffer/root.zig").FrameBuffer;
-
-pub const Connection = @import("connection.zig").Connection;
-pub const Mode = @import("mode.zig").Mode;
-pub const ConnectorType = @import("type.zig").Type;
-
-const RawConnector = extern struct {
- encoder_ids: ?*u32,
- modes: ?*Mode,
- prop_ids: ?*u32,
- prop_value_ids: ?*u64,
- count_modes: u32,
- count_props: u32,
- count_encoders: u32,
- encoder_id: u32,
- id: u32,
- type: ConnectorType,
- type_id: u32,
- connection: Connection,
- mm_width: u32,
- mm_height: u32,
- subpixel: u32,
- pad: u32,
-};
+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: *Card,
+ card: *drm.Card,
encoder_ids: []u32,
modes: []Mode,
@@ -38,24 +17,24 @@ pub const Connector = struct {
prop_value_ids: []u64,
encoder_id: u32,
id: u32,
- type: ConnectorType,
+ kind: Kind,
type_id: u32,
- connection: Connection,
+ connection: Status,
mm_width: u32,
mm_height: u32,
subpixel: u32,
pad: u32,
- pub fn raw_without_ids(card: *Card, id: u32) !RawConnector {
- var result = std.mem.zeroInit(RawConnector, .{ .id = id });
- try Drm.get_connector.request(card.file.handle, RawConnector, &result);
+ 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: *Card, id: u32) !Self {
+ 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),
@@ -64,7 +43,7 @@ pub const Connector = struct {
.prop_value_ids = try card.allocator.alloc(u64, raw.count_props),
.encoder_id = raw.encoder_id,
.id = raw.id,
- .type = raw.type,
+ .kind = raw.type,
.type_id = raw.type_id,
.connection = raw.connection,
.mm_width = raw.mm_width,
@@ -84,7 +63,7 @@ pub const Connector = struct {
raw.prop_ids = @ptrCast(resources.prop_ids);
raw.prop_value_ids = @ptrCast(resources.prop_value_ids);
- try Drm.get_connector.request(card.file.handle, RawConnector, &raw);
+ try card.request(.get_connector, &raw);
return resources;
}
diff --git a/src/screen/drm/connector/connection.zig b/src/screen/drm/connector/status.zig
index 7377800..3358e34 100644
--- a/src/screen/drm/connector/connection.zig
+++ b/src/screen/drm/connector/status.zig
@@ -1,4 +1,4 @@
-pub const Connection = enum(u32) {
+pub const Status = enum(u32) {
undefined_state = 0,
connected = 1,
disconnected = 2,
diff --git a/src/screen/drm/crtc.zig b/src/screen/drm/crtc.zig
new file mode 100644
index 0000000..6130c86
--- /dev/null
+++ b/src/screen/drm/crtc.zig
@@ -0,0 +1,89 @@
+const std = @import("std");
+const drm = @import("root.zig");
+
+pub const Crtc = struct {
+ const Self = @This();
+
+ connector_ids: ?*u32,
+ count_connectors: u32,
+ id: u32,
+ buffer_id: u32,
+ x: u32,
+ y: u32,
+ mode: drm.Connector.Mode,
+ mode_valid: u32,
+ gamma_size: u32,
+ card: *drm.Card,
+
+ pub fn init(card: *drm.Card, id: u32) !Self {
+ var raw = std.mem.zeroInit(drm.request.Crtc, .{ .id = id });
+ try card.request(.get_crtc, &raw);
+ return .{
+ .connector_ids = raw.connector_ids,
+ .count_connectors = raw.count_connectors,
+ .id = raw.id,
+ .buffer_id = raw.buffer_id,
+ .x = raw.x,
+ .y = raw.y,
+ .mode = raw.mode,
+ .mode_valid = raw.mode_valid,
+ .gamma_size = raw.gamma_size,
+ .card = card,
+ };
+ }
+
+ pub fn attach(
+ self: *Self,
+ buffer: *drm.Buffer,
+ connector: *drm.Connector,
+ mode: drm.Connector.Mode
+ ) !void {
+ self.connector_ids = &connector.id;
+ self.count_connectors = 1;
+
+ var crtc = drm.request.Crtc {
+ .id = self.id,
+ .x = self.x,
+ .y = self.y,
+ .buffer_id = buffer.crtc.id,
+ .connector_ids = self.connector_ids,
+ .count_connectors = self.count_connectors,
+ .mode = mode,
+ .mode_valid = 1,
+ .gamma_size = self.gamma_size,
+ };
+
+ try self.card.request(.set_crtc, &crtc);
+ }
+
+ pub fn page_flip(self: *Self, buffer: *drm.Buffer) !void {
+ buffer.swap();
+
+ var flip = std.mem.zeroInit(drm.request.PageFlip, .{
+ .buffer_id = buffer.crtc.id,
+ .crtc_id = self.id,
+ .flags = std.mem.zeroInit(drm.request.PageFlip.Event, .{ .event = true }),
+ });
+
+ try self.card.request(.page_flip, &flip);
+ }
+
+ pub fn detach(self: *Self) void {
+ var crtc = drm.request.Crtc {
+ .id = self.id,
+ .x = self.x,
+ .y = self.y,
+ .buffer_id = self.buffer_id,
+ .connector_ids = self.connector_ids,
+ .count_connectors = self.count_connectors,
+ .mode = self.mode,
+ .mode_valid = self.mode_valid,
+ .gamma_size = self.gamma_size,
+ };
+
+ self.card.request(
+ .set_crtc,
+ &crtc
+ ) catch |err| std.debug.panic("set crtc failed on detach: {}", .{err});
+ }
+};
diff --git a/src/screen/drm/crtc/root.zig b/src/screen/drm/crtc/root.zig
deleted file mode 100644
index bbb72cb..0000000
--- a/src/screen/drm/crtc/root.zig
+++ /dev/null
@@ -1,119 +0,0 @@
-const std = @import("std");
-const Card = @import("../card.zig").Card;
-const Drm = @import("../request.zig").Drm;
-const Connector = @import("../connector/root.zig").Connector;
-const fb = @import("../frame-buffer/root.zig");
-const FrameBuffer = fb.FrameBuffer;
-const DoubleBuffer = fb.DoubleBuffer;
-const Mode = @import("../connector/mode.zig").Mode;
-
-pub const RawCrtc = extern struct {
- connector_ids: ?*u32,
- count_connectors: u32,
- id: u32,
- buffer_id: u32,
- x: u32,
- y: u32,
- gamma_size: u32,
- mode_valid: u32,
- mode: Mode,
-};
-
-const PageFlipEvent = packed struct(u32) {
- event: bool,
- is_async: bool,
- absolute: bool,
- relative: bool,
- __padding: u28,
-};
-
-const PageFlip = extern struct {
- crtc_id: u32,
- buffer_id: u32,
- flags: PageFlipEvent,
- __reserved: u32,
- user_data: u64,
-};
-
-pub const Crtc = struct {
- const Self = @This();
-
- connector_ids: ?*u32,
- count_connectors: u32,
- id: u32,
- buffer_id: u32,
- x: u32,
- y: u32,
- mode: Mode,
- mode_valid: u32,
- gamma_size: u32,
- card: *Card,
-
- pub fn init(card: *Card, id: u32) !Self {
- var raw = std.mem.zeroInit(RawCrtc, .{ .id = id });
- try Drm.get_crtc.request(card.file.handle, RawCrtc, &raw);
- return .{
- .connector_ids = raw.connector_ids,
- .count_connectors = raw.count_connectors,
- .id = raw.id,
- .buffer_id = raw.buffer_id,
- .x = raw.x,
- .y = raw.y,
- .mode = raw.mode,
- .mode_valid = raw.mode_valid,
- .gamma_size = raw.gamma_size,
- .card = card,
- };
- }
-
- pub fn attach(self: *Self, frame_buffer: *FrameBuffer, connector: *Connector, mode: Mode) !void {
- self.connector_ids = &connector.id;
- self.count_connectors = 1;
-
- var crtc = RawCrtc {
- .id = self.id,
- .x = self.x,
- .y = self.y,
- .buffer_id = frame_buffer.id,
- .connector_ids = self.connector_ids,
- .count_connectors = self.count_connectors,
- .mode = mode,
- .mode_valid = 1,
- .gamma_size = self.gamma_size,
- };
-
- try Drm.set_crtc.request(self.card.file.handle, RawCrtc, &crtc);
- }
-
- pub fn page_flip(self: *Self, double_buffer: *DoubleBuffer) !void {
- double_buffer.swap();
-
- var flip = std.mem.zeroInit(PageFlip, .{
- .buffer_id = double_buffer.crtc_buffer().id,
- .crtc_id = self.id,
- .flags = std.mem.zeroInit(PageFlipEvent, .{ .event = true }),
- });
-
- try Drm.page_flip.request(self.card.file.handle, PageFlip, &flip);
- }
-
- pub fn detach(self: *Self) void {
- var crtc = RawCrtc {
- .id = self.id,
- .x = self.x,
- .y = self.y,
- .buffer_id = self.buffer_id,
- .connector_ids = self.connector_ids,
- .count_connectors = self.count_connectors,
- .mode = self.mode,
- .mode_valid = self.mode_valid,
- .gamma_size = self.gamma_size,
- };
-
- Drm.set_crtc.request(
- self.card.file.handle,
- RawCrtc,
- &crtc
- ) catch |err| std.debug.panic("set crtc failed on detach: {}", .{err});
- }
-};
diff --git a/src/screen/drm/encoder/root.zig b/src/screen/drm/encoder.zig
index 7b8932a..19630ab 100644
--- a/src/screen/drm/encoder/root.zig
+++ b/src/screen/drm/encoder.zig
@@ -1,29 +1,31 @@
const std = @import("std");
-const Drm = @import("../request.zig").Drm;
-const Card = @import("../card.zig").Card;
-
-const Type = @import("type.zig").Type;
-
-pub const RawEncoder = extern struct {
- id: u32,
- type: Type,
- crtc_id: u32,
- possible_crtcs: u32,
- possible_clones: u32,
-};
+const drm = @import("root.zig");
+const Card = drm.Card;
pub const Encoder = struct {
const Self = @This();
+ pub const Kind = enum(u32) {
+ none = 0,
+ dac = 1,
+ tmds = 2,
+ lvds = 3,
+ tvdac = 4,
+ virtual = 5,
+ dsi = 6,
+ dpmst = 7,
+ dpi = 8,
+ };
+
id: u32,
- type: Type,
+ type: Kind,
possible_crtcs: u32,
possible_clones: u32,
card: *Card,
pub fn init(card: *Card, id: u32) !Self {
- var raw = std.mem.zeroInit(RawEncoder, .{ .id = id });
- try Drm.get_encoder.request(card.file.handle, RawEncoder, &raw);
+ var raw = std.mem.zeroInit(drm.request.Encoder, .{ .id = id });
+ try card.request(.get_encoder, &raw);
return .{
.id = raw.id,
diff --git a/src/screen/drm/encoder/type.zig b/src/screen/drm/encoder/type.zig
deleted file mode 100644
index 12246d2..0000000
--- a/src/screen/drm/encoder/type.zig
+++ /dev/null
@@ -1,11 +0,0 @@
-pub const Type = enum(u32) {
- none = 0,
- dac = 1,
- tmds = 2,
- lvds = 3,
- tvdac = 4,
- virtual = 5,
- dsi = 6,
- dpmst = 7,
- dpi = 8,
-};
diff --git a/src/screen/drm/event.zig b/src/screen/drm/event.zig
index d60af57..57bbb23 100644
--- a/src/screen/drm/event.zig
+++ b/src/screen/drm/event.zig
@@ -1,5 +1,5 @@
-pub const EventType = enum(u32) {
+pub const Kind = enum(u32) {
vblank = 1,
page_flip_complete = 2,
crtc_sequence = 3,
@@ -25,7 +25,7 @@ pub const EventPayload = extern union {
};
pub const Event = extern struct {
- type: EventType,
+ kind: Kind,
length: u32,
payload: EventPayload,
};
diff --git a/src/screen/drm/frame-buffer/page-flip.zig b/src/screen/drm/frame-buffer/page-flip.zig
deleted file mode 100644
index c6eb836..0000000
--- a/src/screen/drm/frame-buffer/page-flip.zig
+++ /dev/null
@@ -1,7 +0,0 @@
-pub const PageFlip = packed struct(u32) {
- event: bool,
- is_async: bool,
- absolute: bool,
- relative: bool,
- _padding: u28,
-}
diff --git a/src/screen/drm/frame-buffer/root.zig b/src/screen/drm/frame-buffer/root.zig
deleted file mode 100644
index e0e51f8..0000000
--- a/src/screen/drm/frame-buffer/root.zig
+++ /dev/null
@@ -1,188 +0,0 @@
-const std = @import("std");
-const os = std.os.linux;
-const Card = @import("../card.zig").Card;
-const Drm = @import("../request.zig").Drm;
-const PixelFormat = @import("pixelformat.zig").PixelFormat;
-const cerror = @import("../../cerror.zig");
-
-const CreateDumb = extern struct {
- height: u32,
- width: u32,
- bpp: u32,
- flags: u32,
- handle: u32,
- pitch: u32,
- size: u32,
-};
-
-const FrameBufferCmd2 = extern struct {
- id: u32,
- width: u32,
- height: u32,
- pixel_format: PixelFormat,
- flags: u32,
- handles: [4]u32,
- pitches: [4]u32,
- offsets: [4]u32,
- modifier: [4]u32,
-};
-
-const MapDumb = extern struct {
- handle: u32,
- __padding: u32,
- offset: i64,
-};
-
-pub const DoubleBuffer = struct {
- const Self = @This();
-
- back: FrameBuffer,
- front: FrameBuffer,
-
- pub fn init(card: *Card, width: u32, height: u32, bpp: u32) !Self {
- return .{
- .back = try FrameBuffer.init(card, width, height, bpp),
- .front = try FrameBuffer.init(card, width, height, bpp),
- };
- }
-
- pub fn swap(self: *Self) void {
- const back_data = self.back.data;
- self.back.data = self.front.data;
- self.front.data = back_data;
-
- const back_id = self.back.id;
- self.back.id = self.front.id;
- self.front.id = back_id;
- }
-
- pub fn deinit(self: *Self) void {
- self.back.deinit();
- self.front.deinit();
- }
-
- pub fn buffer(self: *Self) *FrameBuffer {
- return &self.back;
- }
-
- pub fn crtc_buffer(self: *Self) *FrameBuffer {
- return &self.front;
- }
-};
-
-pub const Pixel = packed struct(u32) {
- blue: u8,
- green: u8,
- red: u8,
- _padding: u8 = 0x0,
-};
-
-pub const FrameBuffer = struct {
- const Self = @This();
-
- card: *Card,
- id: u32,
- width: u32,
- height: u32,
- bpp: u32,
- stride: u32,
- data_size: u64,
- canvas_size: u64,
- handle: u32,
- data: [*]volatile Pixel,
-
- pub fn init(card: *Card, width: u32, height: u32, bpp: u32) !Self {
- var create_dumb = std.mem.zeroInit(CreateDumb, .{
- .width = width,
- .height = height,
- .bpp = bpp,
- });
- try Drm.create_dumb.request(
- card.file.handle,
- CreateDumb,
- &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 = FrameBufferCmd2 {
- .id = 0,
- .width = fb.width,
- .height = fb.height,
- .pixel_format = PixelFormat.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 Drm.add_frame_buffer2.request(
- card.file.handle,
- FrameBufferCmd2,
- &buffer_cmd
- );
-
- fb.id = buffer_cmd.id;
-
- var map_dumb = std.mem.zeroInit(MapDumb, .{ .handle = fb.handle });
-
- try Drm.map_dumb.request(
- card.file.handle,
- MapDumb,
- &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, pixel: Pixel) void {
- self.data[x + self.width * y] = pixel;
- }
-
- pub fn fill(self: *Self, pixel: Pixel) void {
- @memset(self.data[0..self.canvas_size], pixel);
- }
-
- 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});
-
- Drm.remove_frame_buffer.request(
- self.card.file.handle,
- u32,
- &self.id
- ) catch @panic("failed to remove frame-buffer");
-
- Drm.destroy_dumb.request(
- self.card.file.handle,
- u32,
- &self.handle
- ) catch @panic("failed to destroy dumb-buffer");
- }
-};
diff --git a/src/screen/drm/frame-buffer/pixelformat.zig b/src/screen/drm/pixel.zig
index ec98900..7c99e52 100644
--- a/src/screen/drm/frame-buffer/pixelformat.zig
+++ b/src/screen/drm/pixel.zig
@@ -6,6 +6,14 @@ fn pixel_format_code(comptime a: u8, comptime b: u8, comptime c: u8, comptime d:
(@as(u32, @intCast(d)) << 24);
}
-pub const PixelFormat = enum(u32) {
- xrgb8888 = pixel_format_code('X', 'R', '2', '4'),
+pub const Pixel = packed struct(u32) {
+ blue: u8,
+ green: u8,
+ red: u8,
+ _padding: u8 = 0x0,
+
+ pub const Format = enum(u32) {
+ xrgb8888 = pixel_format_code('X', 'R', '2', '4'),
+ };
};
+
diff --git a/src/screen/drm/request.zig b/src/screen/drm/request.zig
deleted file mode 100644
index 9a70c7d..0000000
--- a/src/screen/drm/request.zig
+++ /dev/null
@@ -1,29 +0,0 @@
-const std = @import("std");
-const os = std.os.linux;
-const cerror = @import("../cerror.zig");
-
-fn ioctl(fd: os.fd_t, request: u32, arg: usize) !void {
- try cerror.from_usize(os.ioctl(fd, request, arg));
-}
-
-pub const Drm = enum(u8) {
- const Self = @This();
-
- get_resources = 0xa0,
- get_crtc = 0xa1,
- set_crtc = 0xa2,
- get_encoder = 0xa6,
- get_connector = 0xa7,
- remove_frame_buffer = 0xaf,
- page_flip = 0xb0,
- dirty_frame_buffer = 0xb1,
- create_dumb = 0xb2,
- map_dumb = 0xb3,
- destroy_dumb = 0xb4,
- add_frame_buffer2 = 0xb8,
-
- pub fn request(self: Self, fd: os.fd_t, T: type, arg: *T) !void {
- const id = os.IOCTL.IOWR('d', @intFromEnum(self), T);
- try ioctl(fd, id, @intFromPtr(arg));
- }
-};
diff --git a/src/screen/drm/request/connector.zig b/src/screen/drm/request/connector.zig
new file mode 100644
index 0000000..7f0b788
--- /dev/null
+++ b/src/screen/drm/request/connector.zig
@@ -0,0 +1,24 @@
+const drm = @import("../root.zig");
+const Mode = drm.Connector.Mode;
+const Kind = drm.Connector.Kind;
+const Status = drm.Connector.Status;
+
+pub const Connector = extern struct {
+ encoder_ids: ?*u32,
+ modes: ?*Mode,
+ prop_ids: ?*u32,
+ prop_value_ids: ?*u64,
+ count_modes: u32,
+ count_props: u32,
+ count_encoders: u32,
+ encoder_id: u32,
+ id: u32,
+ type: Kind,
+ type_id: u32,
+ connection: Status,
+ mm_width: u32,
+ mm_height: u32,
+ subpixel: u32,
+ pad: u32,
+};
+
diff --git a/src/screen/drm/request/crtc.zig b/src/screen/drm/request/crtc.zig
new file mode 100644
index 0000000..f52a9ff
--- /dev/null
+++ b/src/screen/drm/request/crtc.zig
@@ -0,0 +1,29 @@
+const Mode = @import("../connector/mode.zig").Mode;
+
+pub const Crtc = extern struct {
+ connector_ids: ?*u32,
+ count_connectors: u32,
+ id: u32,
+ buffer_id: u32,
+ x: u32,
+ y: u32,
+ gamma_size: u32,
+ mode_valid: u32,
+ mode: Mode,
+};
+
+pub const PageFlip = extern struct {
+ pub const Event = packed struct(u32) {
+ event: bool,
+ is_async: bool,
+ absolute: bool,
+ relative: bool,
+ __padding: u28,
+ };
+
+ crtc_id: u32,
+ buffer_id: u32,
+ flags: Event,
+ __reserved: u32,
+ user_data: u64,
+};
diff --git a/src/screen/drm/request/encoder.zig b/src/screen/drm/request/encoder.zig
new file mode 100644
index 0000000..3cf7985
--- /dev/null
+++ b/src/screen/drm/request/encoder.zig
@@ -0,0 +1,9 @@
+const drm = @import("../root.zig");
+
+pub const Encoder = extern struct {
+ id: u32,
+ type: drm.Encoder.Kind,
+ crtc_id: u32,
+ possible_crtcs: u32,
+ possible_clones: u32,
+};
diff --git a/src/screen/drm/request/frame-buffer.zig b/src/screen/drm/request/frame-buffer.zig
new file mode 100644
index 0000000..8f93862
--- /dev/null
+++ b/src/screen/drm/request/frame-buffer.zig
@@ -0,0 +1,29 @@
+const drm = @import("../root.zig");
+
+pub const CreateDumb = extern struct {
+ height: u32,
+ width: u32,
+ bpp: u32,
+ flags: u32,
+ handle: u32,
+ pitch: u32,
+ size: u32,
+};
+
+pub const FrameBufferCmd2 = extern struct {
+ id: u32,
+ width: u32,
+ height: u32,
+ pixel_format: drm.Pixel.Format,
+ flags: u32,
+ handles: [4]u32,
+ pitches: [4]u32,
+ offsets: [4]u32,
+ modifier: [4]u32,
+};
+
+pub const MapDumb = extern struct {
+ handle: u32,
+ __padding: u32,
+ offset: i64,
+};
diff --git a/src/screen/drm/request/resources.zig b/src/screen/drm/request/resources.zig
new file mode 100644
index 0000000..bc3ce3c
--- /dev/null
+++ b/src/screen/drm/request/resources.zig
@@ -0,0 +1,15 @@
+pub const Resources = extern struct {
+ fb_ids: ?*u32,
+ crtc_ids: ?*u32,
+ connector_ids: ?*u32,
+ encoder_ids: ?*u32,
+ count_fbs: u32,
+ count_crtcs: u32,
+ count_connectors: u32,
+ count_encoders: u32,
+ min_width: u32,
+ max_width: u32,
+ min_height: u32,
+ max_height: u32,
+};
+
diff --git a/src/screen/drm/request/root.zig b/src/screen/drm/request/root.zig
new file mode 100644
index 0000000..7576893
--- /dev/null
+++ b/src/screen/drm/request/root.zig
@@ -0,0 +1,55 @@
+const std = @import("std");
+const os = std.os.linux;
+const cerror = @import("../../cerror.zig");
+
+pub const Resources = @import("resources.zig").Resources;
+pub const Encoder = @import("encoder.zig").Encoder;
+pub const Connector = @import("connector.zig").Connector;
+
+const crtc = @import("crtc.zig");
+pub const Crtc = crtc.Crtc;
+pub const PageFlip = crtc.PageFlip;
+
+const frame_buffer = @import("frame-buffer.zig");
+pub const CreateDumb = frame_buffer.CreateDumb;
+pub const FrameBufferCmd2 = frame_buffer.FrameBufferCmd2;
+pub const MapDumb = frame_buffer.MapDumb;
+
+
+pub const Kind = enum(u8) {
+ const Self = @This();
+
+ get_resources = 0xa0,
+ get_crtc = 0xa1,
+ set_crtc = 0xa2,
+ get_encoder = 0xa6,
+ get_connector = 0xa7,
+ remove_frame_buffer = 0xaf,
+ page_flip = 0xb0,
+ create_dumb = 0xb2,
+ map_dumb = 0xb3,
+ destroy_dumb = 0xb4,
+ add_frame_buffer2 = 0xb8,
+
+ pub fn payload(comptime self: *const Self) type {
+ return comptime switch (self.*) {
+ .get_resources => Resources,
+ .get_crtc => Crtc,
+ .set_crtc => Crtc,
+ .get_encoder => Encoder,
+ .get_connector => Connector,
+ .remove_frame_buffer => u32,
+ .page_flip => PageFlip,
+ .create_dumb => CreateDumb,
+ .map_dumb => MapDumb,
+ .destroy_dumb => u32,
+ .add_frame_buffer2 => FrameBufferCmd2,
+ };
+ }
+
+ pub fn id(comptime self: *const Self, comptime pointer_type: type) u32 {
+ const payload_type = self.payload();
+ comptime std.debug.assert(*payload_type == pointer_type);
+ return comptime os.IOCTL.IOWR('d', @intFromEnum(self.*), payload_type);
+ }
+};
diff --git a/src/screen/drm/resources.zig b/src/screen/drm/resources.zig
index fdd5042..9a8566c 100644
--- a/src/screen/drm/resources.zig
+++ b/src/screen/drm/resources.zig
@@ -1,23 +1,9 @@
const std = @import("std");
const os = std.os.linux;
const cerror = @import("../cerror.zig");
-const Card = @import("card.zig").Card;
-const Drm = @import("request.zig").Drm;
-const RawResources = extern struct {
- fb_ids: ?*u32,
- crtc_ids: ?*u32,
- connector_ids: ?*u32,
- encoder_ids: ?*u32,
- count_fbs: u32,
- count_crtcs: u32,
- count_connectors: u32,
- count_encoders: u32,
- min_width: u32,
- max_width: u32,
- min_height: u32,
- max_height: u32,
-};
+const drm = @import("root.zig");
+const Card = drm.Card;
pub const Resources = struct {
const Self = @This();
@@ -32,9 +18,9 @@ pub const Resources = struct {
width: Range,
height: Range,
- pub fn raw_without_ids(card: *Card) !RawResources {
- var result = std.mem.zeroes(RawResources);
- try Drm.get_resources.request(card.file.handle, RawResources, &result);
+ pub fn raw_without_ids(card: *Card) !drm.request.Resources {
+ var result = std.mem.zeroes(drm.request.Resources);
+ try card.request(.get_resources, &result);
return result;
}
@@ -62,7 +48,7 @@ pub const Resources = struct {
raw.crtc_ids = @ptrCast(resources.crtc_ids);
raw.connector_ids = @ptrCast(resources.connector_ids);
raw.encoder_ids = @ptrCast(resources.encoder_ids);
- try Drm.get_resources.request(card.file.handle, RawResources, &raw);
+ try card.request(.get_resources, &raw);
return resources;
}
diff --git a/src/screen/drm/root.zig b/src/screen/drm/root.zig
new file mode 100644
index 0000000..5012743
--- /dev/null
+++ b/src/screen/drm/root.zig
@@ -0,0 +1,9 @@
+pub const request = @import("request/root.zig");
+pub const Card = @import("card.zig").Card;
+pub const Resources = @import("resources.zig").Resources;
+pub const Encoder = @import("encoder.zig").Encoder;
+pub const Event = @import("event.zig").Event;
+pub const Connector = @import("connector/root.zig").Connector;
+pub const Crtc = @import("crtc.zig").Crtc;
+pub const Buffer = @import("buffer/root.zig").Buffer;
+pub const Pixel = @import("pixel.zig").Pixel;
diff --git a/src/screen/main.zig b/src/screen/main.zig
index 03ef75a..673be0e 100644
--- a/src/screen/main.zig
+++ b/src/screen/main.zig
@@ -1,18 +1,17 @@
const std = @import("std");
-const drm = @import("drm/card.zig");
-const Event = @import("drm/event.zig").Event;
+const drm = @import("drm/root.zig");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
- var card = try drm.Card.open("card1", allocator);
+ var card = try drm.Card.open("card0", allocator);
defer card.close();
var resources = try card.resources();
defer resources.deinit();
- var connector = try card.connector(resources.connector_ids[1]);
+ var connector = try card.connector(resources.connector_ids[0]);
defer connector.deinit();
std.debug.print("connector = {}\n", .{ connector.id });
@@ -32,13 +31,13 @@ pub fn main() !void {
defer double_buffer.deinit();
std.debug.print("buffer = {}, {}x{}, stride = {}\n", .{
- double_buffer.buffer().id,
- double_buffer.buffer().width,
- double_buffer.buffer().height,
- double_buffer.buffer().stride,
+ double_buffer.current.id,
+ double_buffer.current.width,
+ double_buffer.current.height,
+ double_buffer.current.stride,
});
- try crtc.attach(double_buffer.crtc_buffer(), &connector, mode);
+ try crtc.attach(&double_buffer, &connector, mode);
const Pos = struct { x: f32, y: f32 };
@@ -47,13 +46,13 @@ pub fn main() !void {
var delta: f32 = 0;
const size = 100;
- const width: f32 = @floatFromInt(double_buffer.buffer().width);
- const height: f32 = @floatFromInt(double_buffer.buffer().height);
+ const width: f32 = @floatFromInt(double_buffer.current.width);
+ const height: f32 = @floatFromInt(double_buffer.current.height);
while (true) {
const start = try std.time.Instant.now();
- double_buffer.buffer().fill(.{ .red = 0x25, .green = 0x25, .blue = 0x25 });
+ double_buffer.current.fill(.{ .red = 0x25, .green = 0x25, .blue = 0x25 });
pos.x += vec.x * delta;
pos.y += vec.y * delta;
@@ -76,7 +75,7 @@ pub fn main() !void {
for (0..size) |w| {
for (0..size) |h| {
- double_buffer.buffer().set(
+ double_buffer.current.set(
@as(u32, @intFromFloat(pos.x)) + @as(u32, @intCast(w)),
@as(u32, @intFromFloat(pos.y)) + @as(u32, @intCast(h)),
.{
@@ -95,12 +94,12 @@ pub fn main() !void {
try crtc.page_flip(&double_buffer);
while (true) {
- var event: ?Event = null;
+ var event: ?drm.Event = null;
while (event == null) {
event = try card.poll_event(5000);
}
- switch ((event orelse unreachable).type) {
+ switch ((event orelse unreachable).kind) {
.page_flip_complete => break,
else => {},
}