aboutsummaryrefslogtreecommitdiff
path: root/src/wl/shm
diff options
context:
space:
mode:
authorNathan Reiner <nathan@nathanreiner.xyz>2025-08-27 09:02:43 +0200
committerNathan Reiner <nathan@nathanreiner.xyz>2025-08-27 09:03:21 +0200
commit8a7392dea729d3ed49a8bf8eee25906c4fd616ac (patch)
tree09e0b2fa96c60a2e0c8b0cae9e631bd2dc66f52f /src/wl/shm
parentc217e7ec5cddfc002c4582fb5d52727aee843a7d (diff)
Add ancillary data mechanism to send fds to compositor.
Currently we are just attaching the fds to the object id. In theory this is not a valid implementation, since if we have more than MAX_FD file descriptors this will not work. But since this wont be the case in basically all cases of the wayland protocol, we can just ignore that for now.
Diffstat (limited to 'src/wl/shm')
-rw-r--r--src/wl/shm/anonymous-file.zig53
-rw-r--r--src/wl/shm/pool.zig37
-rw-r--r--src/wl/shm/root.zig25
3 files changed, 109 insertions, 6 deletions
diff --git a/src/wl/shm/anonymous-file.zig b/src/wl/shm/anonymous-file.zig
new file mode 100644
index 0000000..f73fbc9
--- /dev/null
+++ b/src/wl/shm/anonymous-file.zig
@@ -0,0 +1,53 @@
+const std = @import("std");
+
+const Self = @This();
+
+size: usize = 0,
+name: [24]u8 = undefined,
+fd: std.posix.fd_t = undefined,
+
+pub fn init_random() !Self {
+ var buf: [8]u8 = undefined;
+ try std.posix.getrandom(&buf);
+
+ var self: Self = .{};
+
+ const name = std.fmt.bufPrint(&self.name, "/wl.shm.{x}{x}{x}{x}{x}{x}{x}{x}", .{
+ buf[0],
+ buf[1],
+ buf[2],
+ buf[3],
+ buf[4],
+ buf[5],
+ buf[6],
+ buf[7],
+ }) catch unreachable;
+
+ self.fd = try std.posix.memfd_create(name, 0);
+
+ return self;
+}
+
+pub fn truncate(self: *Self, size: usize) !void {
+ try std.posix.ftruncate(self.fd, size);
+ self.size = size;
+}
+
+pub fn mmap(self: *Self) ![]u8 {
+ return std.posix.mmap(
+ null,
+ self.size,
+ std.os.linux.PROT.READ | std.os.linux.PROT.WRITE,
+ .{
+ .TYPE = .SHARED,
+ .ANONYMOUS = true,
+ },
+ self.fd,
+ 0,
+ );
+}
+
+pub fn close(self: *Self) void {
+ std.posix.close(self.fd);
+ self.* = undefined;
+}
diff --git a/src/wl/shm/pool.zig b/src/wl/shm/pool.zig
index dc30d1b..1f42a17 100644
--- a/src/wl/shm/pool.zig
+++ b/src/wl/shm/pool.zig
@@ -1,5 +1,10 @@
+const std = @import("std");
const wayland = @import("../../root.zig");
-const Format = @import("root.zig").Format;
+const wl = wayland.wl;
+const Format = wl.Shm.Format;
+const AnonymousFile = wl.Shm.AnonymousFile;
+
+const Self = @This();
pub const Events = wayland.EventSet(@This(), .{});
pub const Requests = union(enum) {
@@ -7,3 +12,33 @@ pub const Requests = union(enum) {
destroy: struct {},
resize: struct { u32 },
};
+
+handle: wayland.Object.Ref,
+file: AnonymousFile,
+buffer: []u8,
+
+pub fn init(
+ self: *Self,
+ ctx: *const wayland.Context,
+ size: usize,
+) !void {
+ var file = try AnonymousFile.init_random();
+ errdefer file.close();
+ try file.truncate(size);
+
+ self.* = .{
+ .handle = try ctx.display.registry.add_object(
+ ctx.allocator,
+ wayland.Object.from_self(self),
+ ),
+ .file = file,
+ .buffer = try file.mmap(),
+ };
+}
+
+pub fn deinit(self: *Self, ctx: *const wayland.Context) void {
+ self.file.close();
+ std.posix.munmap(@alignCast(self.buffer));
+ ctx.display.registry.disable_object(self.handle);
+ self.* = undefined;
+}
diff --git a/src/wl/shm/root.zig b/src/wl/shm/root.zig
index 2d24aca..fd96727 100644
--- a/src/wl/shm/root.zig
+++ b/src/wl/shm/root.zig
@@ -4,12 +4,13 @@ const wl = wayland.wl;
pub const Pool = @import("pool.zig");
pub const Format = @import("format.zig").Format;
+pub const AnonymousFile = @import("anonymous-file.zig");
const Self = @This();
pub const Events = wayland.EventSet(Self, .{ announce_format });
-pub const Requests = union(enum) {
- create_pool: struct { u32, wayland.types.Fd, u32 },
+pub const Request = union(enum) {
+ create_pool: struct { wayland.Object.Ref, wayland.types.Fd, u32 },
};
pub var instances: std.ArrayListUnmanaged(*Self) = .empty;
@@ -19,7 +20,7 @@ formats: std.EnumSet(Format) = .initEmpty(),
pub fn init(
self: *Self,
- ctx: *wayland.Context,
+ ctx: *const wayland.Context,
) !void {
self.* = .{
.handle = try ctx.display.registry.add_object(
@@ -29,7 +30,7 @@ pub fn init(
};
}
-fn announce_format(self: * Self, ctx: *wayland.Context, fmt: Format) void {
+fn announce_format(self: * Self, ctx: *const wayland.Context, fmt: Format) void {
_ = ctx;
self.formats.insert(fmt);
}
@@ -40,7 +41,7 @@ pub const handler: wl.Registry.GlobalHandler = .{
.handler = register,
};
-fn register(ctx: *wayland.Context) ?wayland.Object.Ref {
+fn register(ctx: *const wayland.Context) ?wayland.Object.Ref {
const shm = ctx.allocator.create(Self) catch return null;
shm.init(ctx) catch return null;
@@ -48,6 +49,20 @@ fn register(ctx: *wayland.Context) ?wayland.Object.Ref {
return shm.handle;
}
+pub fn create_pool(self: *Self, ctx: *const wayland.Context, size: usize) !*Pool {
+ const pool = try ctx.allocator.create(Pool);
+ errdefer ctx.allocator.destroy(pool);
+ try pool.init(ctx, size);
+
+ try ctx.display.request(self, .{ .create_pool = .{
+ pool.handle,
+ .{ .fd = pool.file.fd },
+ @truncate(size)
+ } });
+
+ return pool;
+}
+
pub fn format(
self: *const Self,
comptime fmt: []const u8,