Buffer.zig (1974B)
1 const std = @import("std"); 2 3 const pixman = @import("pixman"); 4 const wl = @import("wayland").client.wl; 5 6 const Buffer = @This(); 7 8 mmap: ?[]align(4096) u8 = null, 9 data: ?[]u32 = null, 10 buffer: ?*wl.Buffer = null, 11 pix: ?*pixman.Image = null, 12 13 busy: bool = false, 14 width: u31 = 0, 15 height: u31 = 0, 16 size: u31 = 0, 17 18 pub fn resize(self: *Buffer, shm: *wl.Shm, width: u31, height: u31) !void { 19 if (width == 0 or height == 0) return; 20 21 self.busy = true; 22 self.width = width; 23 self.height = height; 24 25 const fd = try std.posix.memfd_create("levee-shm", std.os.linux.MFD.CLOEXEC); 26 defer std.posix.close(fd); 27 28 const stride = width * 4; 29 self.size = stride * height; 30 try std.posix.ftruncate(fd, self.size); 31 32 self.mmap = try std.posix.mmap(null, self.size, std.posix.PROT.READ | std.posix.PROT.WRITE, .{ .TYPE = .SHARED }, fd, 0); 33 self.data = std.mem.bytesAsSlice(u32, self.mmap.?); 34 35 const pool = try shm.createPool(fd, self.size); 36 defer pool.destroy(); 37 38 self.buffer = try pool.createBuffer(0, width, height, stride, .argb8888); 39 errdefer self.buffer.?.destroy(); 40 self.buffer.?.setListener(*Buffer, listener, self); 41 42 self.pix = pixman.Image.createBitsNoClear(.a8r8g8b8, width, height, self.data.?.ptr, stride); 43 } 44 45 pub fn deinit(self: *Buffer) void { 46 if (self.pix) |pix| _ = pix.unref(); 47 if (self.buffer) |buf| buf.destroy(); 48 if (self.mmap) |mmap| std.posix.munmap(mmap); 49 } 50 51 fn listener(_: *wl.Buffer, event: wl.Buffer.Event, buffer: *Buffer) void { 52 switch (event) { 53 .release => buffer.busy = false, 54 } 55 } 56 57 pub fn nextBuffer(pool: *[2]Buffer, shm: *wl.Shm, width: u16, height: u16) !*Buffer { 58 if (pool[0].busy and pool[1].busy) { 59 return error.NoAvailableBuffers; 60 } 61 const buffer = if (!pool[0].busy) &pool[0] else &pool[1]; 62 63 if (buffer.width != width or buffer.height != height) { 64 buffer.deinit(); 65 try buffer.resize(shm, width, height); 66 } 67 return buffer; 68 }