diff --git a/.gitea/workflows/Build.yml b/.gitea/workflows/Build.yml index be38594..a9595d1 100644 --- a/.gitea/workflows/Build.yml +++ b/.gitea/workflows/Build.yml @@ -22,9 +22,6 @@ jobs: with: node-version: 24 - - name: Installing system dependencies - run: apt update && apt install wayland-protocols - - name: Building run: zig build soft diff --git a/build.zig b/build.zig index 811c21d..e8abe2c 100644 --- a/build.zig +++ b/build.zig @@ -76,7 +76,6 @@ pub fn build(b: *std.Build) !void { if (builtin.target.os.tag == .linux) { base_c_includes.link_libc = true; - base_c_includes.defineCMacroRaw("STROLL_ENABLE_WAYLAND"); } base_mod.addImport("base_c", base_c_includes.createModule()); diff --git a/src/vulkan/c_includes.h b/src/vulkan/c_includes.h index 174e75a..cdb1bab 100644 --- a/src/vulkan/c_includes.h +++ b/src/vulkan/c_includes.h @@ -1,6 +1,2 @@ #include #include - -#ifdef STROLL_ENABLE_WAYLAND - #include -#endif diff --git a/src/vulkan/wsi/WaylandSurfaceKHR.zig b/src/vulkan/wsi/WaylandSurfaceKHR.zig index 211f39e..d3863fa 100644 --- a/src/vulkan/wsi/WaylandSurfaceKHR.zig +++ b/src/vulkan/wsi/WaylandSurfaceKHR.zig @@ -22,7 +22,7 @@ const WaylandImage = struct { fn wlRegistryHandleGlobal(data: ?*anyopaque, registry: ?*wayland.wl_registry, name: u32, interface: [*c]const u8, _: u32) callconv(.c) void { const pshm: **wayland.wl_shm = @ptrCast(@alignCast(data orelse return)); if (std.mem.eql(u8, std.mem.span(interface), "wl_shm")) { - if (wayland.c.wl_registry_bind(registry orelse return, name, wayland.wl_shm_interface, 1)) |shm| { + if (wayland.wl_registry_bind(registry orelse return, name, wayland.wl_shm_interface, 1)) |shm| { pshm.* = @ptrCast(@alignCast(shm)); } } @@ -65,9 +65,9 @@ pub fn create(instance: *Instance, allocator: std.mem.Allocator, info: *const vk .image_map = .empty, }; - const registry = wayland.c.wl_display_get_registry(@ptrCast(self.display)) orelse return VkError.Unknown; - _ = wayland.c.wl_registry_add_listener(registry, &wl_registry_listener, @ptrCast(&self.shm)); - _ = wayland.c.wl_display_dispatch(@ptrCast(self.display)); + const registry = wayland.wl_display_get_registry(@ptrCast(self.display)) orelse return VkError.Unknown; + _ = wayland.wl_registry_add_listener(registry, &wl_registry_listener, @ptrCast(&self.shm)); + _ = wayland.wl_display_dispatch(@ptrCast(self.display)); return &self.interface; } @@ -106,11 +106,11 @@ pub fn attachImage(interface: *Interface, allocator: std.mem.Allocator, image: * const data = std.posix.mmap(null, size, .{ .READ = true, .WRITE = true }, .{ .TYPE = .SHARED }, fd, 0) catch return VkError.OutOfHostMemory; errdefer std.posix.munmap(data); - const pool = wayland.c.wl_shm_create_pool(self.shm, fd, @intCast(size)) orelse return VkError.Unknown; - defer wayland.c.wl_shm_pool_destroy(pool); + const pool = wayland.wl_shm_create_pool(self.shm, fd, @intCast(size)) orelse return VkError.Unknown; + defer wayland.wl_shm_pool_destroy(pool); - const buffer = wayland.c.wl_shm_pool_create_buffer(pool, 0, @intCast(width), @intCast(height), @intCast(stride), wayland.WL_SHM_FORMAT_ARGB8888) orelse return VkError.Unknown; - errdefer wayland.c.wl_buffer_destroy(buffer); + const buffer = wayland.wl_shm_pool_create_buffer(pool, 0, @intCast(width), @intCast(height), @intCast(stride), wayland.WL_SHM_FORMAT_ARGB8888) orelse return VkError.Unknown; + errdefer wayland.wl_buffer_destroy(buffer); wl_image.* = .{ .buffer = buffer, @@ -128,7 +128,7 @@ pub fn detachImage(interface: *Interface, allocator: std.mem.Allocator, image: * const entry = self.image_map.fetchRemove(image) orelse return; const wl_image = entry.value; - wayland.c.wl_buffer_destroy(wl_image.buffer); + wayland.wl_buffer_destroy(wl_image.buffer); std.posix.munmap(wl_image.data); allocator.destroy(wl_image); } @@ -146,11 +146,11 @@ pub fn presentImage(interface: *Interface, allocator: std.mem.Allocator, image: .layer_count = 1, }); - wayland.c.wl_surface_attach(@ptrCast(self.surface), wl_image.buffer, 0, 0); - wayland.c.wl_surface_damage(@ptrCast(self.surface), 0, 0, @intCast(wl_image.width), @intCast(wl_image.height)); - wayland.c.wl_surface_commit(@ptrCast(self.surface)); + wayland.wl_surface_attach(@ptrCast(self.surface), wl_image.buffer, 0, 0); + wayland.wl_surface_damage(@ptrCast(self.surface), 0, 0, @intCast(wl_image.width), @intCast(wl_image.height)); + wayland.wl_surface_commit(@ptrCast(self.surface)); - _ = wayland.c.wl_display_flush(@ptrCast(self.display)); + _ = wayland.wl_display_flush(@ptrCast(self.display)); image.state = .Available; } diff --git a/src/vulkan/wsi/clients/wayland.zig b/src/vulkan/wsi/clients/wayland.zig index 1522bb1..f1a1acf 100644 --- a/src/vulkan/wsi/clients/wayland.zig +++ b/src/vulkan/wsi/clients/wayland.zig @@ -1,29 +1,59 @@ +//! Minimal wayland client protocol declarations and loader + const std = @import("std"); const vk = @import("vulkan"); const lib = @import("../../lib.zig"); -pub const c = lib.c; - const VkError = lib.VkError; -pub const wl_registry_listener = c.wl_registry_listener; +pub extern const wl_registry_interface: wl_interface; +pub extern const wl_shm_pool_interface: wl_interface; +pub extern const wl_buffer_interface: wl_interface; -pub const WL_SHM_FORMAT_ARGB8888 = c.WL_SHM_FORMAT_ARGB8888; +pub const wl_registry_listener = extern struct { + global: ?*const fn (data: ?*anyopaque, wl_registry: ?*wl_registry, name: u32, interface: [*c]const u8, version: u32) callconv(.c) void = null, + global_remove: ?*const fn (data: ?*anyopaque, wl_registry: ?*wl_registry, name: u32) callconv(.c) void = null, +}; -pub const wl_buffer = c.wl_buffer; -pub const wl_callback = c.wl_buffer; -pub const wl_interface = c.wl_interface; -pub const wl_registry = c.wl_registry; -pub const wl_shm = c.wl_shm; -pub const wl_shm_pool = c.wl_shm_pool; -pub const wl_proxy = c.wl_proxy; +pub const WL_BUFFER_DESTROY = @as(c_int, 0); +pub const WL_DISPLAY_GET_REGISTRY = @as(c_int, 1); +pub const WL_REGISTRY_BIND = @as(c_int, 0); +pub const WL_SHM_CREATE_POOL = @as(c_int, 0); +pub const WL_SHM_FORMAT_ARGB8888 = @as(c_int, 0); +pub const WL_SHM_POOL_CREATE_BUFFER = @as(c_int, 0); +pub const WL_SHM_POOL_DESTROY = @as(c_int, 1); +pub const WL_SURFACE_ATTACH = @as(c_int, 1); +pub const WL_SURFACE_COMMIT = @as(c_int, 6); +pub const WL_SURFACE_DAMAGE = @as(c_int, 2); -// vk.wl_XXX instead of c.wl_XXX to avoid casts with Zig Vulkan bindings functions +pub const wl_buffer = opaque {}; +pub const wl_callback = opaque {}; +pub const wl_registry = opaque {}; +pub const wl_shm = opaque {}; +pub const wl_shm_pool = opaque {}; +pub const wl_proxy = opaque {}; pub const wl_display = vk.wl_display; pub const wl_surface = vk.wl_surface; +pub const wl_message = extern struct { + name: ?[*:0]const u8 = null, + signature: [*c]const u8 = null, + types: [*c]*const wl_interface = null, +}; + +pub const wl_interface = extern struct { + name: ?[*:0]const u8 = null, + version: c_int = 0, + method_count: c_int = 0, + methods: ?[*]const wl_message = null, + event_count: c_int = 0, + events: ?[*]const wl_message = null, +}; + pub var wl_display_dispatch: *const fn (*wl_display) callconv(.c) c_int = undefined; -pub var wl_proxy_marshal_flags: *const fn (*wl_proxy, u32, *const wl_interface, u32, u32, ...) callconv(.c) ?*wl_proxy = undefined; +pub var wl_proxy_marshal_flags: *const fn (*wl_proxy, u32, ?*const wl_interface, u32, u32, ...) callconv(.c) ?*wl_proxy = undefined; +pub var wl_proxy_get_version: *const fn (*wl_proxy) callconv(.c) u32 = undefined; +pub var wl_proxy_add_listener: *const fn (*wl_proxy, **const fn (void) void, ?*anyopaque) callconv(.c) c_int = undefined; pub var wl_display_flush: *const fn (*wl_display) callconv(.c) c_int = undefined; pub var wl_shm_interface: *wl_interface = undefined; @@ -45,6 +75,8 @@ pub fn load() VkError!void { wl_display_dispatch = module.lookup(@TypeOf(wl_display_dispatch), "wl_display_dispatch") orelse return VkError.Unknown; wl_proxy_marshal_flags = module.lookup(@TypeOf(wl_proxy_marshal_flags), "wl_proxy_marshal_flags") orelse return VkError.Unknown; + wl_proxy_get_version = module.lookup(@TypeOf(wl_proxy_get_version), "wl_proxy_get_version") orelse return VkError.Unknown; + wl_proxy_add_listener = module.lookup(@TypeOf(wl_proxy_add_listener), "wl_proxy_add_listener") orelse return VkError.Unknown; wl_display_flush = module.lookup(@TypeOf(wl_display_flush), "wl_display_flush") orelse return VkError.Unknown; wl_shm_interface = module.lookup(*wl_interface, "wl_shm_interface") orelse return VkError.Unknown; @@ -57,3 +89,118 @@ pub fn unload() void { module.close(); } } + +pub fn wl_registry_bind(registry: *wl_registry, name: u32, interface: *const wl_interface, version: u32) callconv(.c) ?*wl_proxy { + return wl_proxy_marshal_flags( + @ptrCast(@alignCast(registry)), + WL_REGISTRY_BIND, + interface, + version, + 0, + name, + interface.*.name, + version, + @as(?*anyopaque, null), + ); +} + +pub fn wl_display_get_registry(display: *wl_display) callconv(.c) ?*wl_registry { + return @ptrCast(@alignCast(wl_proxy_marshal_flags( + @ptrCast(@alignCast(display)), + WL_DISPLAY_GET_REGISTRY, + &wl_registry_interface, + wl_proxy_get_version(@ptrCast(@alignCast(display))), + 0, + @as(?*anyopaque, null), + ))); +} + +pub fn wl_registry_add_listener(registry: *wl_registry, listener: *const wl_registry_listener, data: ?*anyopaque) callconv(.c) c_int { + return wl_proxy_add_listener(@ptrCast(@alignCast(registry)), @ptrCast(@alignCast(@constCast(listener))), data); +} + +pub fn wl_shm_create_pool(shm: *wl_shm, fd: i32, size: i32) callconv(.c) ?*wl_shm_pool { + return @ptrCast(@alignCast(wl_proxy_marshal_flags( + @ptrCast(@alignCast(shm)), + WL_SHM_CREATE_POOL, + &wl_shm_pool_interface, + wl_proxy_get_version(@ptrCast(@alignCast(shm))), + 0, + @as(?*anyopaque, null), + fd, + size, + ))); +} + +pub fn wl_shm_pool_destroy(shm_pool: *wl_shm_pool) callconv(.c) void { + _ = wl_proxy_marshal_flags( + @ptrCast(@alignCast(shm_pool)), + WL_SHM_POOL_DESTROY, + null, + wl_proxy_get_version(@ptrCast(@alignCast(shm_pool))), + @bitCast(@as(c_int, @as(c_int, 1) << @intCast(@as(c_int, 0)))), + ); +} + +pub fn wl_shm_pool_create_buffer(shm_pool: *wl_shm_pool, offset: i32, width: i32, height: i32, stride: i32, format: u32) callconv(.c) ?*wl_buffer { + return @ptrCast(@alignCast(wl_proxy_marshal_flags( + @ptrCast(@alignCast(shm_pool)), + WL_SHM_POOL_CREATE_BUFFER, + &wl_buffer_interface, + wl_proxy_get_version(@ptrCast(@alignCast(shm_pool))), + 0, + @as(?*anyopaque, null), + offset, + width, + height, + stride, + format, + ))); +} + +pub fn wl_buffer_destroy(buffer: *wl_buffer) callconv(.c) void { + _ = wl_proxy_marshal_flags( + @ptrCast(@alignCast(buffer)), + WL_BUFFER_DESTROY, + null, + wl_proxy_get_version(@ptrCast(@alignCast(buffer))), + @bitCast(@as(c_int, @as(c_int, 1) << @intCast(@as(c_int, 0)))), + ); +} + +pub fn wl_surface_attach(surface: *wl_surface, buffer: *wl_buffer, x: i32, y: i32) callconv(.c) void { + _ = wl_proxy_marshal_flags( + @ptrCast(@alignCast(surface)), + WL_SURFACE_ATTACH, + null, + wl_proxy_get_version(@ptrCast(@alignCast(surface))), + 0, + buffer, + x, + y, + ); +} + +pub fn wl_surface_damage(surface: *wl_surface, x: i32, y: i32, width: i32, height: i32) callconv(.c) void { + _ = wl_proxy_marshal_flags( + @ptrCast(@alignCast(surface)), + WL_SURFACE_DAMAGE, + null, + wl_proxy_get_version(@ptrCast(@alignCast(surface))), + 0, + x, + y, + width, + height, + ); +} + +pub fn wl_surface_commit(surface: *wl_surface) callconv(.c) void { + _ = wl_proxy_marshal_flags( + @ptrCast(@alignCast(surface)), + WL_SURFACE_COMMIT, + null, + wl_proxy_get_version(@ptrCast(@alignCast(surface))), + 0, + ); +}