const std = @import("std"); const drm = @import("drm/card.zig"); const Event = @import("drm/event.zig").Event; pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}){}; const allocator = gpa.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[0]); defer connector.deinit(); std.debug.print("connector = {}\n", .{ connector.id }); const mode = connector.modes[0]; std.debug.print("mode = {s}@{d}Hz\n", .{ mode.name, mode.frame_rate() }); var crtc = try crtc: { for (connector.encoder_ids) |encoder_id| { var encoder = try card.encoder(encoder_id); defer encoder.deinit(); for (resources.crtc_ids, 0..) |crtc_id, index| { if ((encoder.possible_crtcs & (@as(u32, 1) << @intCast(index))) != 0) { break :crtc card.crtc(crtc_id); } } } break :crtc error.CrtcNotFound; }; defer crtc.detach(); std.debug.print("crtc = {}\n", .{ crtc.id }); var double_buffer = try card.create_double_buffer(mode.horizontal.size, mode.vertical.size, 32); 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, }); try crtc.attach(double_buffer.crtc_buffer(), &connector, mode); const Pos = struct { x: f32, y: f32 }; var vec = Pos { .x = 10, .y = 10 }; var pos = Pos { .x = 0, .y = 0 }; var delta: f32 = 0; const size = 100; const width: f32 = @floatFromInt(double_buffer.buffer().width); const height: f32 = @floatFromInt(double_buffer.buffer().height); while (true) { const start = try std.time.Instant.now(); double_buffer.buffer().fill(.{ .red = 0, .green = 0, .blue = 0 }); pos.x += vec.x * delta; pos.y += vec.y * delta; if (pos.x < 0) { pos.x = -pos.x; vec.x = -vec.x; } else if (pos.x + size >= width) { pos.x = width - size; vec.x = -vec.x; } if (pos.y < 0) { pos.y = -pos.y; vec.y = -vec.y; } else if (pos.y + size >= height) { pos.y = height - size; vec.y = -vec.y; } for (0..size) |w| { for (0..size) |h| { double_buffer.buffer().set( @as(u32, @intFromFloat(pos.x)) + @as(u32, @intCast(w)), @as(u32, @intFromFloat(pos.y)) + @as(u32, @intCast(h)), .{ .red = 0xff, .green = 0, .blue = 0, }); } } const end = try std.time.Instant.now(); const elapsed = (@as(f32, @floatFromInt(end.since(start))) / std.time.ns_per_s); std.debug.print("FPS: {d:.2}\r", .{ 1 / elapsed }); delta = elapsed * 60; try crtc.page_flip(&double_buffer); while (true) { var event: ?Event = null; while (event == null) { event = try card.poll_event(5000); } switch ((event orelse unreachable).type) { .page_flip_complete => break, else => {}, } } } }