[gamemode] Make available on other platforms
All checks were successful
eden-license / license-header (pull_request) Successful in 27s

Signed-off-by: lizzie <lizzie@eden-emu.dev>
This commit is contained in:
lizzie 2025-08-29 23:48:25 +00:00
parent f07309afd2
commit 385debd86b
Signed by: Lizzie
GPG key ID: 00287378CADCAB13
9 changed files with 105 additions and 98 deletions

View file

@ -474,7 +474,7 @@ else()
find_package(Catch2 3.0.1 REQUIRED) find_package(Catch2 3.0.1 REQUIRED)
endif() endif()
if (CMAKE_SYSTEM_NAME STREQUAL "Linux" OR ANDROID) if (PLATFORM_LINUX OR ANDROID)
find_package(gamemode 1.7 MODULE) find_package(gamemode 1.7 MODULE)
endif() endif()

View file

@ -1,6 +1,9 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
/* /*
Copyright (c) 2017-2019, Feral Interactive Copyright (c) 2017-2025, Feral Interactive and the GameMode contributors
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@ -103,6 +106,7 @@ typedef int (*api_call_pid_return_int)(pid_t);
static api_call_return_int REAL_internal_gamemode_request_start = NULL; static api_call_return_int REAL_internal_gamemode_request_start = NULL;
static api_call_return_int REAL_internal_gamemode_request_end = NULL; static api_call_return_int REAL_internal_gamemode_request_end = NULL;
static api_call_return_int REAL_internal_gamemode_query_status = NULL; static api_call_return_int REAL_internal_gamemode_query_status = NULL;
static api_call_return_int REAL_internal_gamemode_request_restart = NULL;
static api_call_return_cstring REAL_internal_gamemode_error_string = NULL; static api_call_return_cstring REAL_internal_gamemode_error_string = NULL;
static api_call_pid_return_int REAL_internal_gamemode_request_start_for = NULL; static api_call_pid_return_int REAL_internal_gamemode_request_start_for = NULL;
static api_call_pid_return_int REAL_internal_gamemode_request_end_for = NULL; static api_call_pid_return_int REAL_internal_gamemode_request_end_for = NULL;
@ -166,6 +170,10 @@ __attribute__((always_inline)) static inline int internal_load_libgamemode(void)
(void **)&REAL_internal_gamemode_query_status, (void **)&REAL_internal_gamemode_query_status,
sizeof(REAL_internal_gamemode_query_status), sizeof(REAL_internal_gamemode_query_status),
false }, false },
{ "real_gamemode_request_restart",
(void **)&REAL_internal_gamemode_request_restart,
sizeof(REAL_internal_gamemode_request_restart),
false },
{ "real_gamemode_error_string", { "real_gamemode_error_string",
(void **)&REAL_internal_gamemode_error_string, (void **)&REAL_internal_gamemode_error_string,
sizeof(REAL_internal_gamemode_error_string), sizeof(REAL_internal_gamemode_error_string),
@ -319,6 +327,24 @@ __attribute__((always_inline)) static inline int gamemode_query_status(void)
return REAL_internal_gamemode_query_status(); return REAL_internal_gamemode_query_status();
} }
/* Redirect to the real libgamemode */
__attribute__((always_inline)) static inline int gamemode_request_restart(void)
{
/* Need to load gamemode */
if (internal_load_libgamemode() < 0) {
return -1;
}
if (REAL_internal_gamemode_request_restart == NULL) {
snprintf(internal_gamemode_client_error_string,
sizeof(internal_gamemode_client_error_string),
"gamemode_request_restart missing (older host?)");
return -1;
}
return REAL_internal_gamemode_request_restart();
}
/* Redirect to the real libgamemode */ /* Redirect to the real libgamemode */
__attribute__((always_inline)) static inline int gamemode_request_start_for(pid_t pid) __attribute__((always_inline)) static inline int gamemode_request_start_for(pid_t pid)
{ {

View file

@ -69,6 +69,8 @@ add_library(
fs/fs_util.h fs/fs_util.h
fs/path_util.cpp fs/path_util.cpp
fs/path_util.h fs/path_util.h
gamemode.cpp
gamemode.h
hash.h hash.h
heap_tracker.cpp heap_tracker.cpp
heap_tracker.h heap_tracker.h
@ -191,11 +193,7 @@ if(ANDROID)
android/applets/software_keyboard.h) android/applets/software_keyboard.h)
endif() endif()
if(LINUX AND NOT APPLE) target_link_libraries(common PRIVATE gamemode::headers)
target_sources(common PRIVATE linux/gamemode.cpp linux/gamemode.h)
target_link_libraries(common PRIVATE gamemode::headers)
endif()
if(ARCHITECTURE_x86_64) if(ARCHITECTURE_x86_64)
target_sources( target_sources(

50
src/common/gamemode.cpp Normal file
View file

@ -0,0 +1,50 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
// While technically available on al *NIX platforms, Linux is only available
// as the primary target of libgamemode.so - so warnings are suppressed
#ifdef __unix__
#include <gamemode_client.h>
#endif
#include "common/gamemode.h"
#include "common/logging/log.h"
#include "common/settings.h"
namespace Common::FeralGamemode {
void Start() noexcept {
if (Settings::values.enable_gamemode) {
#ifdef __unix__
if (gamemode_request_start() < 0) {
#ifdef __linux__
LOG_WARNING(Frontend, "{}", gamemode_error_string());
#else
LOG_INFO(Frontend, "{}", gamemode_error_string());
#endif
} else {
LOG_INFO(Frontend, "Done");
}
#endif
}
}
void Stop() noexcept {
if (Settings::values.enable_gamemode) {
#ifdef __unix__
if (gamemode_request_end() < 0) {
#ifdef __linux__
LOG_WARNING(Frontend, "{}", gamemode_error_string());
#else
LOG_INFO(Frontend, "{}", gamemode_error_string());
#endif
} else {
LOG_INFO(Frontend, "Done");
}
#endif
}
}
} // namespace Common::Linux

17
src/common/gamemode.h Normal file
View file

@ -0,0 +1,17 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
namespace Common::FeralGamemode {
/// @brief Start the gamemode client
void Start() noexcept;
/// @brief Stop the gmemode client
void Stop() noexcept;
} // namespace Common::FeralGamemode

View file

@ -1,40 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <gamemode_client.h>
#include "common/linux/gamemode.h"
#include "common/logging/log.h"
#include "common/settings.h"
namespace Common::Linux {
void StartGamemode() {
if (Settings::values.enable_gamemode) {
if (gamemode_request_start() < 0) {
LOG_WARNING(Frontend, "Failed to start gamemode: {}", gamemode_error_string());
} else {
LOG_INFO(Frontend, "Started gamemode");
}
}
}
void StopGamemode() {
if (Settings::values.enable_gamemode) {
if (gamemode_request_end() < 0) {
LOG_WARNING(Frontend, "Failed to stop gamemode: {}", gamemode_error_string());
} else {
LOG_INFO(Frontend, "Stopped gamemode");
}
}
}
void SetGamemodeState(bool state) {
if (state) {
StartGamemode();
} else {
StopGamemode();
}
}
} // namespace Common::Linux

View file

@ -1,24 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
namespace Common::Linux {
/**
* Start the (Feral Interactive) Linux gamemode if it is installed and it is activated
*/
void StartGamemode();
/**
* Stop the (Feral Interactive) Linux gamemode if it is installed and it is activated
*/
void StopGamemode();
/**
* Start or stop the (Feral Interactive) Linux gamemode if it is installed and it is activated
* @param state The new state the gamemode should have
*/
void SetGamemodeState(bool state);
} // namespace Common::Linux

View file

@ -21,9 +21,7 @@
#include <csignal> #include <csignal>
#include <sys/socket.h> #include <sys/socket.h>
#endif #endif
#ifdef __linux__ #include "common/gamemode.h"
#include "common/linux/gamemode.h"
#endif
#include <boost/container/flat_set.hpp> #include <boost/container/flat_set.hpp>
@ -2388,9 +2386,7 @@ void GMainWindow::OnEmulationStopped() {
discord_rpc->Update(); discord_rpc->Update();
#ifdef __linux__ Common::FeralGamemode::Stop();
Common::Linux::StopGamemode();
#endif
// The emulation is stopped, so closing the window or not does not matter anymore // The emulation is stopped, so closing the window or not does not matter anymore
disconnect(render_window, &GRenderWindow::Closed, this, &GMainWindow::OnStopGame); disconnect(render_window, &GRenderWindow::Closed, this, &GMainWindow::OnStopGame);
@ -3573,10 +3569,7 @@ void GMainWindow::OnStartGame() {
play_time_manager->Start(); play_time_manager->Start();
discord_rpc->Update(); discord_rpc->Update();
Common::FeralGamemode::StartGamemode();
#ifdef __linux__
Common::Linux::StartGamemode();
#endif
} }
void GMainWindow::OnRestartGame() { void GMainWindow::OnRestartGame() {
@ -3597,10 +3590,7 @@ void GMainWindow::OnPauseGame() {
play_time_manager->Stop(); play_time_manager->Stop();
UpdateMenuState(); UpdateMenuState();
AllowOSSleep(); AllowOSSleep();
Common::FeralGamemode::Stop();
#ifdef __linux__
Common::Linux::StopGamemode();
#endif
} }
void GMainWindow::OnPauseContinueGame() { void GMainWindow::OnPauseContinueGame() {

View file

@ -63,10 +63,7 @@ __declspec(dllexport) unsigned long NvOptimusEnablement = 0x00000001;
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
} }
#endif #endif
#include "common/gamemode.h"
#ifdef __linux__
#include "common/linux/gamemode.h"
#endif
static void PrintHelp(const char* argv0) { static void PrintHelp(const char* argv0) {
std::cout << "Usage: " << argv0 std::cout << "Usage: " << argv0
@ -435,10 +432,7 @@ int main(int argc, char** argv) {
// Just exit right away. // Just exit right away.
exit(0); exit(0);
}); });
Common::FeralGamemode::StartGamemode();
#ifdef __linux__
Common::Linux::StartGamemode();
#endif
void(system.Run()); void(system.Run());
if (system.DebuggerEnabled()) { if (system.DebuggerEnabled()) {
@ -450,11 +444,7 @@ int main(int argc, char** argv) {
system.DetachDebugger(); system.DetachDebugger();
void(system.Pause()); void(system.Pause());
system.ShutdownMainProcess(); system.ShutdownMainProcess();
Common::FeralGamemode::Stop();
#ifdef __linux__
Common::Linux::StopGamemode();
#endif
detached_tasks.WaitForAllTasks(); detached_tasks.WaitForAllTasks();
return 0; return 0;
} }