diff options
Diffstat (limited to 'src/screen/drm')
23 files changed, 472 insertions, 453 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; |