~andreafeletto/levee

ref: 687c1d16212671656bb79436df39feb6275e00a3 levee/src/shm.zig -rw-r--r-- 2.0 KiB
687c1d16Andrea Feletto add case for battery capacity computation 8 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
67
68
69
const std = @import("std");
const mem = std.mem;
const os = std.os;

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

const pixman = @import("pixman");

pub const Buffer = struct {
    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;
    }
};