diff --git a/examples/01_client_connect.zig b/examples/01_client_connect.zig index f61c52f..b347fdb 100644 --- a/examples/01_client_connect.zig +++ b/examples/01_client_connect.zig @@ -174,12 +174,16 @@ pub fn main() !void { // allocate a shared memory file for display purposes const Pixel = [4]u8; const framebuffer_size = [2]usize{ 128, 128 }; - const framebuffer_file_len = framebuffer_size[0] * framebuffer_size[1] * @sizeOf(Pixel); + const pool_file_len = 1024 * framebuffer_size[0] * framebuffer_size[1] * @sizeOf(Pixel); - const framebuffer_fd = try std.os.memfd_create("my-wayland-framebuffer", 0); - try std.os.ftruncate(framebuffer_fd, framebuffer_file_len); - const framebuffer_bytes = try std.os.mmap(null, framebuffer_file_len, std.os.PROT.READ | std.os.PROT.WRITE, std.os.MAP.SHARED, framebuffer_fd, 0); - const framebuffer = @as([*][4]u8, @ptrCast(framebuffer_bytes.ptr))[0 .. framebuffer_bytes.len / @sizeOf([4]u8)]; + const pool_fd = try std.os.memfd_create("my-wayland-framebuffer", 0); + try std.os.ftruncate(pool_fd, pool_file_len); + const pool_bytes = try std.os.mmap(null, pool_file_len, std.os.PROT.READ | std.os.PROT.WRITE, std.os.MAP.SHARED, pool_fd, 0); + var pool_fixed_buffer_allocator = std.heap.FixedBufferAllocator.init(pool_bytes); + var pool_general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){ .backing_allocator = pool_fixed_buffer_allocator.allocator() }; + const pool_alloc = pool_general_purpose_allocator.allocator(); + + const framebuffer = try pool_alloc.alloc(Pixel, framebuffer_size[0] * framebuffer_size[1]); // put some interesting colors into the framebuffer for (0..framebuffer_size[1]) |y| { @@ -196,18 +200,22 @@ pub fn main() !void { const wl_shm_pool_id = id_pool.create(); { - std.debug.print("framebuffer_fd: {}\n", .{framebuffer_fd}); + std.debug.print("framebuffer_fd: {}\n", .{pool_fd}); try conn.send( wayland.core.Shm.Request, shm_id, .{ .create_pool = .{ .new_id = wl_shm_pool_id, - .fd = @enumFromInt(framebuffer_fd), - .size = framebuffer_file_len, + .fd = @enumFromInt(pool_fd), + .size = pool_file_len, } }, ); } + var framebuffers = std.AutoHashMap(u32, []Pixel).init(gpa); + defer framebuffers.deinit(); + try framebuffers.put(wl_shm_pool_id, framebuffer); + const wl_buffer_id = id_pool.create(); try conn.send( wayland.core.ShmPool.Request, @@ -249,6 +257,8 @@ pub fn main() !void { wayland.core.Surface.Request.commit, ); + var window_size: [2]u32 = [2]u32{ @intCast(framebuffer_size[0]), @intCast(framebuffer_size[1]) }; + var running = true; while (running) { const header, const body = try conn.recv(); @@ -265,6 +275,63 @@ pub fn main() !void { } }, ); + const new_buffer_id = id_pool.create(); + const new_framebuffer = try pool_alloc.alloc(Pixel, window_size[0] * window_size[1]); + try framebuffers.put(new_buffer_id, new_framebuffer); + + // put some interesting colors into the new_framebuffer + for (0..window_size[1]) |y| { + const row = new_framebuffer[y * window_size[0] .. (y + 1) * window_size[0]]; + for (row, 0..window_size[0]) |*pixel, x| { + pixel.* = .{ + @truncate(x), + @truncate(y), + 0x00, + 0xFF, + }; + } + } + + try conn.send( + wayland.core.ShmPool.Request, + wl_shm_pool_id, + .{ .create_buffer = .{ + .new_id = new_buffer_id, + .offset = @intCast(@intFromPtr(new_framebuffer.ptr) - @intFromPtr(pool_bytes.ptr)), + .width = @intCast(window_size[0]), + .height = @intCast(window_size[1]), + .stride = @as(i32, @intCast(window_size[0])) * @sizeOf([4]u8), + .format = .argb8888, + } }, + ); + + try conn.send( + wayland.core.Surface.Request, + surface_id, + .{ .attach = .{ + .buffer = new_buffer_id, + .x = 0, + .y = 0, + } }, + ); + + try conn.send( + wayland.core.Surface.Request, + surface_id, + .{ .damage = .{ + .x = 0, + .y = 0, + .width = std.math.maxInt(i32), + .height = std.math.maxInt(i32), + } }, + ); + + try conn.send( + wayland.core.Surface.Request, + surface_id, + wayland.core.Surface.Request.commit, + ); + // commit the configuration try conn.send( wayland.core.Surface.Request, @@ -278,13 +345,14 @@ pub fn main() !void { switch (event) { .configure => |conf| { std.debug.print("<- xdg_toplevel@{} configure <{}, {}> {any}\n", .{ header.object_id, conf.width, conf.height, conf.states }); + window_size = .{ + @intCast(conf.width), + @intCast(conf.height), + }; }, .close => running = false, else => |tag| std.debug.print("<- xdg_toplevel@{} {s} {}\n", .{ header.object_id, @tagName(tag), event }), } - } else if (header.object_id == wl_buffer_id) { - const event = try wayland.deserialize(wayland.core.Buffer.Event, header, body); - std.debug.print("<- wl_buffer@{} {}\n", .{ header.object_id, event }); } else if (header.object_id == xdg_wm_base_id) { const event = try wayland.deserialize(wayland.xdg.WmBase.Event, header, body); switch (event) { @@ -316,6 +384,14 @@ pub fn main() !void { std.debug.print("<- wl_keyboard@{}\n", .{event}); }, } + } else if (framebuffers.get(header.object_id)) |framebuffer_slice| { + const event = try wayland.deserialize(wayland.core.Buffer.Event, header, body); + switch (event) { + .release => { + _ = framebuffers.remove(header.object_id); + pool_alloc.free(framebuffer_slice); + }, + } } else if (header.object_id == DISPLAY_ID) { const event = try wayland.deserialize(wayland.core.Display.Event, header, body); switch (event) {