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)
This commit is contained in:
Ali Chraghi 2022-09-17 11:02:27 +04:30 committed by GitHub
parent 47d1544b64
commit 6043c7eae6
Failed to generate hash of commit
3 changed files with 48 additions and 45 deletions

View file

@ -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

View file

@ -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() });
};
}

View file

@ -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) {