From 6043c7eae60d1ad3037a05c2901a2c2757a9b480 Mon Sep 17 00:00:00 2001 From: Ali Chraghi <63465728+alichraghi@users.noreply.github.com> Date: Sat, 17 Sep 2022 11:02:27 +0430 Subject: [PATCH] mach: add `is_app` option to disable gamemode in desktop applications; use parseIp4 (#544) * mach: add `is_app` option to disable gamemode in desktop applications * use parseIp4 instead of resolveIp (which throws a compile error in windows) --- build.zig | 2 +- src/platform/native.zig | 88 ++++++++++++++++++++--------------------- src/structs.zig | 3 ++ 3 files changed, 48 insertions(+), 45 deletions(-) diff --git a/build.zig b/build.zig index dc976ab7..162e3d6d 100644 --- a/build.zig +++ b/build.zig @@ -371,7 +371,7 @@ pub const App = struct { if (app.platform == .web) { const address = std.process.getEnvVarOwned(app.b.allocator, "MACH_ADDRESS") catch app.b.allocator.dupe(u8, "127.0.0.1") catch unreachable; const port = std.process.getEnvVarOwned(app.b.allocator, "MACH_PORT") catch app.b.allocator.dupe(u8, "8080") catch unreachable; - const address_parsed = std.net.Address.resolveIp(address, std.fmt.parseInt(u16, port, 10) catch unreachable) catch unreachable; + const address_parsed = std.net.Address.parseIp4(address, std.fmt.parseInt(u16, port, 10) catch unreachable) catch unreachable; const wasmserve = @import("tools/wasmserve/wasmserve.zig"); const install_step_name = if (std.mem.startsWith(u8, app.step.name, "example-")) app.step.name diff --git a/src/platform/native.zig b/src/platform/native.zig index 32815e8d..68571fed 100644 --- a/src/platform/native.zig +++ b/src/platform/native.zig @@ -41,7 +41,7 @@ pub const Platform = struct { last_cursor_position: structs.WindowPos, - linux_gamemode_is_active: bool, + linux_gamemode: ?bool, const EventQueue = std.TailQueue(structs.Event); const EventNode = EventQueue.Node; @@ -50,15 +50,7 @@ pub const Platform = struct { platform: *Platform, }; - fn getEnvVarOwned(allocator: std.mem.Allocator, key: []const u8) error{ OutOfMemory, InvalidUtf8 }!?[]u8 { - return std.process.getEnvVarOwned(allocator, key) catch |err| switch (err) { - error.EnvironmentVariableNotFound => @as(?[]u8, null), - else => |e| e, - }; - } pub fn init(allocator: std.mem.Allocator, core: *Core) !Platform { - const linux_gamemode_is_active = try initLinuxGamemode(allocator); - const options = core.options; const backend_type = try util.detectBackendType(allocator); @@ -166,7 +158,7 @@ pub const Platform = struct { }, .instance = instance.?, .adapter = response.?.adapter, - .linux_gamemode_is_active = linux_gamemode_is_active, + .linux_gamemode = null, }; } @@ -180,40 +172,10 @@ pub const Platform = struct { platform.allocator.destroy(ev); } - platform.deinitLinuxGamemode(); - } - - /// Check if gamemode should be activated - fn activateGamemode(allocator: std.mem.Allocator) error{ OutOfMemory, InvalidUtf8 }!bool { - const GAMEMODE_ENV = try getEnvVarOwned(allocator, "GAMEMODE"); - if (GAMEMODE_ENV) |env| { - defer allocator.free(env); - return !(std.ascii.eqlIgnoreCase(env, "off") or std.ascii.eqlIgnoreCase(env, "false")); - } - return true; - } - fn initLinuxGamemode(allocator: std.mem.Allocator) error{ OutOfMemory, DLOpenFailed, InvalidUtf8 }!bool { - if (builtin.os.tag == .linux) { - const gamemode = @import("gamemode"); - if (try activateGamemode(allocator)) { - gamemode.requestStart() catch |err| { - if (!std.mem.containsAtLeast(u8, gamemode.errorString(), 1, "dlopen failed")) - std.log.err("Gamemode error {} -> {s}", .{ err, gamemode.errorString() }); - return false; - }; - std.log.info("Gamemode activated", .{}); - return true; - } - } - return false; - } - fn deinitLinuxGamemode(platform: *Platform) void { - if (builtin.os.tag == .linux and platform.linux_gamemode_is_active) { - const gamemode = @import("gamemode"); - gamemode.requestEnd() catch |err| { - std.log.err("Gamemode error {} -> {s}", .{ err, gamemode.errorString() }); - }; - } + if (builtin.os.tag == .linux and + platform.linux_gamemode != null and + platform.linux_gamemode.?) + deinitLinuxGamemode(); } fn pushEvent(platform: *Platform, event: structs.Event) void { @@ -640,6 +602,10 @@ pub fn coreDeinit(core: *Core, allocator: std.mem.Allocator) void { pub const CoreResizeCallback = *const fn (*Core, u32, u32) callconv(.C) void; pub fn coreUpdate(core: *Core, resize: ?CoreResizeCallback) !void { + if (builtin.os.tag == .linux and !core.options.is_app and + core.internal.linux_gamemode == null and try activateGamemode(core.allocator)) + core.internal.linux_gamemode = initLinuxGamemode(); + if (core.internal.wait_event_timeout > 0.0) { if (core.internal.wait_event_timeout == std.math.inf(f64)) { // Wait for an event @@ -672,9 +638,43 @@ pub fn coreUpdate(core: *Core, resize: ?CoreResizeCallback) !void { } } +fn getEnvVarOwned(allocator: std.mem.Allocator, key: []const u8) error{ OutOfMemory, InvalidUtf8 }!?[]u8 { + return std.process.getEnvVarOwned(allocator, key) catch |err| switch (err) { + error.EnvironmentVariableNotFound => @as(?[]u8, null), + else => |e| e, + }; +} + fn glfwSizeOptional(size: structs.SizeOptional) glfw.Window.SizeOptional { return .{ .width = size.width, .height = size.height, }; } + +/// Check if gamemode should be activated +fn activateGamemode(allocator: std.mem.Allocator) error{ OutOfMemory, InvalidUtf8 }!bool { + if (try getEnvVarOwned(allocator, "GAMEMODE")) |env| { + defer allocator.free(env); + return !(std.ascii.eqlIgnoreCase(env, "off") or std.ascii.eqlIgnoreCase(env, "false")); + } + return true; +} + +fn initLinuxGamemode() bool { + const gamemode = @import("gamemode"); + gamemode.requestStart() catch |err| { + if (!std.mem.containsAtLeast(u8, gamemode.errorString(), 1, "dlopen failed")) + std.log.err("Gamemode error {} -> {s}", .{ err, gamemode.errorString() }); + return false; + }; + std.log.info("Gamemode activated", .{}); + return true; +} + +fn deinitLinuxGamemode() void { + const gamemode = @import("gamemode"); + gamemode.requestEnd() catch |err| { + std.log.err("Gamemode error {} -> {s}", .{ err, gamemode.errorString() }); + }; +} diff --git a/src/structs.zig b/src/structs.zig index 00aaa4c6..ec972d00 100644 --- a/src/structs.zig +++ b/src/structs.zig @@ -51,6 +51,9 @@ pub const Options = struct { /// Whether the application has a preference for low power or high performance GPU. power_preference: gpu.PowerPreference = .undef, + + /// If set, optimize for regular applications rather than games. e.g. disable Linux gamemode / process priority, prefer low-power GPU (if preference is .undef), etc. + is_app: bool = false, }; pub const Event = union(enum) {