From d65588bc2d07bfcf6edcd342b9c4dc140f577cb5 Mon Sep 17 00:00:00 2001 From: Joshua Holmes Date: Tue, 10 Sep 2024 23:46:14 -0700 Subject: [PATCH] core: setup linux to detect and select x11 or wayland implementation --- src/core/Linux.zig | 72 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 67 insertions(+), 5 deletions(-) diff --git a/src/core/Linux.zig b/src/core/Linux.zig index a9c16acc..b392e69e 100644 --- a/src/core/Linux.zig +++ b/src/core/Linux.zig @@ -1,6 +1,8 @@ const std = @import("std"); const mach = @import("../main.zig"); const Core = @import("../Core.zig"); +const X11 = @import("linux/X11.zig"); +const Wayland = @import("linux/Wayland.zig"); const gpu = mach.gpu; const InitOptions = Core.InitOptions; const Event = Core.Event; @@ -19,12 +21,15 @@ const KeyMods = Core.KeyMods; const log = std.log.scoped(.mach); const gamemode_log = std.log.scoped(.gamemode); +const Backend = union(enum) { + x11: X11, + wayland: Wayland, +}; + pub const Linux = @This(); allocator: std.mem.Allocator, -core: *Core, -modifiers: KeyMods, -title: [:0]u8, + display_mode: DisplayMode, vsync_mode: VSyncMode, cursor_mode: CursorMode, @@ -35,20 +40,77 @@ refresh_rate: u32, size: Size, surface_descriptor: gpu.Surface.Descriptor, gamemode: ?bool = null, +backend: Backend, pub fn init( linux: *Linux, core: *Core.Mod, options: InitOptions, ) !void { - _ = core; + linux.allocator = options.allocator; + + if (!options.is_app and try wantGamemode(linux.allocator)) linux.gamemode = initLinuxGamemode(); + + const desired_backend: Backend = blk: { + const backend = std.process.getEnvVarOwned( + linux.allocator, + "MACH_CORE_BACKEND", + ) catch |err| switch (err) { + error.EnvironmentVariableNotFound => { + // TODO(core): default to .x11 in the future + break :blk .wayland; + }, + else => return err, + }; + defer linux.allocator.free(backend); + + if (std.ascii.eqlIgnoreCase(backend, "x11")) break :blk .x11; + if (std.ascii.eqlIgnoreCase(backend, "wayland")) break :blk .wayland; + std.debug.panic("mach: unknown MACH_CORE_BACKEND: {s}", .{backend}); + }; + + if (desired_backend == .x11) { + // TODO(core): support X11 in the future + @panic("X11 is not supported...YET"); + } + + // Try to initialize the desired backend, falling back to the other if that one is not supported + switch (desired_backend) { + .x11 => { + const x11 = X11.init(core, options) catch |err| switch (err) { + error.NotSupported => { + log.err("failed to initialize X11 backend, falling back to Wayland", .{}); + linux.backend = .{ .wayland = try Wayland.init(linux, core, options) }; + }, + else => return err, + }; + linux.backend = .{ .x11 = x11 }; + }, + .wayland => { + const wayland = Wayland.init(core, options) catch |err| switch (err) { + error.NotSupported => { + log.err("failed to initialize Wayland backend, falling back to X11", .{}); + linux.backend = .{ .x11 = try X11.init(linux, core, options) }; + + // TODO(core): support X11 in the future + @panic("X11 is not supported...YET"); + }, + else => return err, + }; + linux.backend = .{ .wayland = wayland }; + }, + } + + linux.size = linux.backend.size; + linux.surface_descriptor = linux.backend.surface_descriptor; + linux.refresh_rate = 60; // TODO: set to something meaningful - if (!options.is_app and try wantGamemode(options.allocator)) linux.gamemode = initLinuxGamemode(); return; } pub fn deinit(linux: *Linux) void { if (linux.gamemode != null and linux.gamemode.?) deinitLinuxGamemode(); + linux.backend.deinit(); return; }