From 097a6a9b5c4f63b41c1717e43371716a2026a66b Mon Sep 17 00:00:00 2001 From: Lorenzo Torres Date: Mon, 4 Aug 2025 02:46:36 +0200 Subject: [PATCH] Implemented Xorg initialization code --- build.zig | 20 +++++++++++++++++--- src/c.zig | 5 +++++ src/main.zig | 10 ++++++---- src/renderer/Mesh.zig | 2 +- src/renderer/Renderer.zig | 6 +++--- src/renderer/Window.zig | 2 +- src/renderer/c.zig | 5 ----- src/renderer/vulkan.zig | 30 ++++++++++++++++++++---------- src/sideros.zig | 2 ++ src/wayland.zig | 4 ++-- src/xorg.zig | 39 +++++++++++++++++++++++++++++++++++++++ 11 files changed, 96 insertions(+), 29 deletions(-) delete mode 100644 src/renderer/c.zig create mode 100644 src/xorg.zig diff --git a/build.zig b/build.zig index 18f935f..eafaded 100644 --- a/build.zig +++ b/build.zig @@ -51,13 +51,27 @@ pub fn build(b: *std.Build) void { }), }); exe.root_module.addImport("sideros", sideros); - exe.root_module.addCSourceFile(.{ .file = b.path("ext/xdg-shell.c") }); - exe.root_module.addIncludePath(b.path("ext")); + sideros.addIncludePath(b.path("ext")); exe.linkSystemLibrary("vulkan"); - exe.linkSystemLibrary("wayland-client"); exe.linkLibC(); + const options = b.addOptions(); + + if (target.result.os.tag == .linux) { + const wayland = b.option(bool, "wayland", "Use Wayland to create the main window") orelse false; + if (wayland) { + exe.linkSystemLibrary("wayland-client"); + exe.root_module.addCSourceFile(.{ .file = b.path("ext/xdg-shell.c") }); + } else { + exe.linkSystemLibrary("xcb"); + exe.linkSystemLibrary("xcb-icccm"); + } + options.addOption(bool, "wayland", wayland); + } + + sideros.addOptions("config", options); + b.installArtifact(exe); const root_lib = b.addLibrary(.{ diff --git a/src/c.zig b/src/c.zig index 0251923..895dbbf 100644 --- a/src/c.zig +++ b/src/c.zig @@ -1,4 +1,9 @@ pub const c = @cImport({ @cInclude("wayland-client.h"); @cInclude("xdg-shell.h"); + @cInclude("xcb/xcb.h"); + @cInclude("vulkan/vulkan.h"); + @cInclude("vulkan/vulkan_wayland.h"); + @cInclude("vulkan/vulkan_xcb.h"); + @cInclude("xcb/xcb_icccm.h"); }); diff --git a/src/main.zig b/src/main.zig index 0d300c3..c582d32 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,11 +1,12 @@ const std = @import("std"); -const config = @import("config"); +const config = @import("sideros").config; const math = @import("sideros").math; const Input = @import("sideros").Input; const mods = @import("sideros").mods; const ecs = @import("sideros").ecs; -//const Renderer = @import("sideros").Renderer; -const wayland = @import("wayland.zig"); +const builtin = @import("builtin"); + +const platform = if (builtin.target.os.tag == .linux) (if (config.wayland) @import("wayland.zig") else @import("xorg.zig")) else @import("xorg.zig"); //fn testSystem2(pool: *ecs.Pool) void { // std.debug.print("{any}\n", .{pool.resources.input.isKeyDown(.a)}); @@ -66,5 +67,6 @@ pub fn main() !void { // try pool.addComponent(entity, ecs.components.Position{ .x = 1.0, .y = 0.5, .z = 3.0 }); // try pool.addComponent(entity, ecs.components.Speed{ .speed = 5.0 }); // } - try wayland.init(allocator); + + try platform.init(allocator); } diff --git a/src/renderer/Mesh.zig b/src/renderer/Mesh.zig index d356967..6b2d98f 100644 --- a/src/renderer/Mesh.zig +++ b/src/renderer/Mesh.zig @@ -1,4 +1,4 @@ -const c = @import("c.zig").c; +const c = @import("sideros").c; const std = @import("std"); const vk = @import("vulkan.zig"); const gltf = @import("gltf.zig"); diff --git a/src/renderer/Renderer.zig b/src/renderer/Renderer.zig index fe247c5..16df8f7 100644 --- a/src/renderer/Renderer.zig +++ b/src/renderer/Renderer.zig @@ -1,4 +1,4 @@ -const c = @import("c.zig"); +const c = @import("sideros").c; const ecs = @import("ecs"); const std = @import("std"); const vk = @import("vulkan.zig"); @@ -19,10 +19,10 @@ current_frame: u32, vertex_buffer: vk.Buffer, index_buffer: vk.Buffer, -pub fn init(allocator: Allocator, display: ?*anyopaque, s: ?*anyopaque) !Renderer { +pub fn init(comptime C: type, comptime S: type, allocator: Allocator, display: C, s: S) !Renderer { const instance = try vk.Instance.create(allocator); - const surface = try vk.Surface.create(instance, display, s); + const surface = try vk.Surface.create(C, S, instance, display, s); var physical_device = try vk.PhysicalDevice.pick(allocator, instance); const device = try physical_device.create_device(surface, allocator, 2); diff --git a/src/renderer/Window.zig b/src/renderer/Window.zig index 5513ad7..ff3d6cd 100644 --- a/src/renderer/Window.zig +++ b/src/renderer/Window.zig @@ -1,4 +1,4 @@ -const c = @import("c.zig").c; +const c = @import("sideros").c; const ecs = @import("ecs"); const std = @import("std"); diff --git a/src/renderer/c.zig b/src/renderer/c.zig deleted file mode 100644 index c80ef4b..0000000 --- a/src/renderer/c.zig +++ /dev/null @@ -1,5 +0,0 @@ -pub const c = @cImport({ - @cInclude("vulkan/vulkan.h"); - @cInclude("vulkan/vulkan_wayland.h"); - @cInclude("wayland-client.h"); -}); diff --git a/src/renderer/vulkan.zig b/src/renderer/vulkan.zig index 4e1aa4e..753cdcc 100644 --- a/src/renderer/vulkan.zig +++ b/src/renderer/vulkan.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const c = @import("c.zig").c; +const c = @import("sideros").c; const Window = @import("Window.zig"); const Mesh = @import("Mesh.zig"); const sideros = @import("sideros"); @@ -7,6 +7,7 @@ const Camera = @import("Camera.zig"); const math = sideros.math; const Allocator = std.mem.Allocator; +const config = sideros.config; const builtin = @import("builtin"); const debug = (builtin.mode == .Debug); @@ -73,8 +74,7 @@ pub const Instance = struct { handle: c.VkInstance, pub fn create(allocator: Allocator) !Instance { - const extensions = [_][*c]const u8 {c.VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME, c.VK_KHR_SURFACE_EXTENSION_NAME}; - //const extensions = [_][:0]const u8 {"VK_KHR_wayland_surface\0", "VK_KHR_surface\0"}; + const extensions = [_][*c]const u8 {if (config.wayland) c.VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME else c.VK_KHR_XCB_SURFACE_EXTENSION_NAME, c.VK_KHR_SURFACE_EXTENSION_NAME}; // Querry avaliable extensions size var avaliableExtensionsCount: u32 = 0; @@ -757,15 +757,25 @@ pub fn Swapchain(comptime n: usize) type { pub const Surface = struct { handle: c.VkSurfaceKHR, - pub fn create(instance: Instance, display: ?*anyopaque, surface: ?*anyopaque) !Surface { + pub fn create(comptime C: type, comptime S: type, instance: Instance, display: C, surface: S) !Surface { var handle: c.VkSurfaceKHR = undefined; - const create_info: c.VkWaylandSurfaceCreateInfoKHR = .{ - .sType = c.VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR, - .display = @ptrCast(display), - .surface = @ptrCast(surface), - }; + if (config.wayland) { + const create_info: c.VkWaylandSurfaceCreateInfoKHR = .{ + .sType = c.VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR, + .display = display, + .surface = surface, + }; + + try mapError(c.vkCreateWaylandSurfaceKHR(instance.handle, &create_info, null, &handle)); + } else { + const create_info: c.VkXcbSurfaceCreateInfoKHR = .{ + .sType = c.VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR, + .connection = display, + .window = surface, + }; + try mapError(c.vkCreateXcbSurfaceKHR(instance.handle, &create_info, null, &handle)); + } - try mapError(c.vkCreateWaylandSurfaceKHR(instance.handle, &create_info, null, &handle)); return .{ .handle = handle, }; diff --git a/src/sideros.zig b/src/sideros.zig index cf4795b..19f032f 100644 --- a/src/sideros.zig +++ b/src/sideros.zig @@ -3,3 +3,5 @@ pub const Input = @import("Input.zig"); pub const mods = @import("mods"); pub const ecs = @import("ecs"); pub const Renderer = @import("renderer"); +pub const config = @import("config"); +pub const c = @import("c.zig").c; diff --git a/src/wayland.zig b/src/wayland.zig index bde076f..efc8e82 100644 --- a/src/wayland.zig +++ b/src/wayland.zig @@ -1,4 +1,4 @@ -const c = @import("c.zig").c; +const c = @import("sideros").c; const std = @import("std"); const Renderer = @import("sideros").Renderer; @@ -136,7 +136,7 @@ pub fn init(allocator: std.mem.Allocator) !void { _ = c.wl_display_dispatch(display); } - var renderer = try Renderer.init(allocator, @ptrCast(display), @ptrCast(surface)); + var renderer = try Renderer.init(@TypeOf(display), @TypeOf(surface), allocator, display, surface); defer renderer.deinit(); try renderer.render(); diff --git a/src/xorg.zig b/src/xorg.zig new file mode 100644 index 0000000..992685a --- /dev/null +++ b/src/xorg.zig @@ -0,0 +1,39 @@ +const std = @import("std"); +const Renderer = @import("sideros").Renderer; +const c = @import("sideros").c; + +pub fn init(allocator: std.mem.Allocator) !void { + const connection = c.xcb_connect(null, null); + defer c.xcb_disconnect(connection); + + const setup = c.xcb_get_setup(connection); + const iter = c.xcb_setup_roots_iterator(setup); + const screen = iter.data; + + const mask = c.XCB_CW_EVENT_MASK; + const value = c.XCB_EVENT_MASK_EXPOSURE; + + const window = c.xcb_generate_id(connection); + _ = c.xcb_create_window(connection, c.XCB_COPY_FROM_PARENT, window, screen.*.root, 0, 0, 800, 600, 10, c.XCB_WINDOW_CLASS_INPUT_OUTPUT, screen.*.root_visual, mask, &value); + + var hints: c.xcb_size_hints_t = undefined; + c.xcb_icccm_size_hints_set_min_size(&hints, 800, 600); + c.xcb_icccm_size_hints_set_max_size(&hints, 800, 600); + _ = c.xcb_icccm_set_wm_size_hints(connection, window, c.XCB_ATOM_WM_NORMAL_HINTS, &hints); + + _ = c.xcb_map_window(connection, window); + + _ = c.xcb_flush(connection); + + var renderer = try Renderer.init(@TypeOf(connection), @TypeOf(window), allocator, connection, window); + defer renderer.deinit(); + + while (c.xcb_wait_for_event(connection)) |e| { + switch (e.*.response_type & ~@as(u32, 0x80)) { + else => {}, + } + + try renderer.render(); + std.c.free(e); + } +}