~andreafeletto/levee

ref: a40cd1f35e815d58ac2b5bdf3968a611a8a0972e levee/src/Buffer.zig -rw-r--r-- 1.8 KiB
a40cd1f3Andrea Feletto pulse: respect muted flag 5 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
const std = @import("std");
const mem = std.mem;
const os = std.os;

const pixman = @import("pixman");
const wl = @import("wayland").client.wl;

const Buffer = @This();

data: ?[]align(4096) u8,
buffer: ?*wl.Buffer,
pix: ?*pixman.Image,
busy: bool,
width: u31,
height: u31,
size: u31,

pub fn init(self: *Buffer, shm: *wl.Shm, width: u31, height: u31) !void {
    self.busy = true;
    self.width = width;
    self.height = height;

    const fd = try os.memfd_create("levee-wayland-shm-buffer-pool", 0);
    defer os.close(fd);

    const stride = width * 4;
    self.size = stride * height;
    try os.ftruncate(fd, self.size);

    self.data = try os.mmap(null, self.size, os.PROT.READ | os.PROT.WRITE, os.MAP.SHARED, fd, 0);
    errdefer os.munmap(self.data.?);

    const pool = try shm.createPool(fd, self.size);
    defer pool.destroy();

    self.buffer = try pool.createBuffer(0, width, height, stride, .argb8888);
    errdefer self.buffer.?.destroy();
    self.buffer.?.setListener(*Buffer, listener, self);

    self.pix = pixman.Image.createBitsNoClear(.a8r8g8b8, width, height, @ptrCast([*c]u32, self.data.?), stride);
}

pub fn deinit(self: *Buffer) void {
    if (self.pix) |pix| _ = pix.unref();
    if (self.buffer) |buf| buf.destroy();
    if (self.data) |data| os.munmap(data);
}

fn listener(_: *wl.Buffer, event: wl.Buffer.Event, buffer: *Buffer) void {
    switch (event) {
        .release => buffer.busy = false,
    }
}

pub fn nextBuffer(pool: *[2]Buffer, shm: *wl.Shm, width: u16, height: u16) !*Buffer {
    if (pool[0].busy and pool[1].busy) {
        return error.NoAvailableBuffers;
    }
    const buffer = if (!pool[0].busy) &pool[0] else &pool[1];

    if (buffer.width != width or buffer.height != height) {
        buffer.deinit();
        try buffer.init(shm, width, height);
    }
    return buffer;
}