stevee

My wayland statusbar
git clone git://gtms.dev/stevee
Log | Files | Refs | README | LICENSE

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 }