Port yuzu-emu/yuzu#11946: "Enable (Feral Interactive) Gamemode on Linux" (#7245)

This commit is contained in:
Tobias 2023-12-20 15:08:07 +01:00 committed by GitHub
parent 2e369c03b8
commit c7e9f8449e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 540 additions and 3 deletions

View file

@ -38,6 +38,10 @@
#include "network/network.h"
#include "video_core/renderer_base.h"
#ifdef __unix__
#include "common/linux/gamemode.h"
#endif
#undef _UNICODE
#include <getopt.h>
#ifndef _MSC_VER
@ -442,6 +446,10 @@ int main(int argc, char** argv) {
}
}
#ifdef __unix__
Common::Linux::StartGamemode();
#endif
std::thread main_render_thread([&emu_window] { emu_window->Present(); });
std::thread secondary_render_thread([&secondary_window] {
if (secondary_window) {
@ -493,6 +501,10 @@ int main(int argc, char** argv) {
system.Shutdown();
#ifdef __unix__
Common::Linux::StopGamemode();
#endif
detached_tasks.WaitForAllTasks();
return 0;
}

View file

@ -308,7 +308,7 @@ if (NOT WIN32)
endif()
if (UNIX AND NOT APPLE)
target_link_libraries(citra-qt PRIVATE Qt6::DBus)
target_link_libraries(citra-qt PRIVATE Qt6::DBus gamemode)
endif()
target_compile_definitions(citra-qt PRIVATE

View file

@ -528,6 +528,7 @@ void Config::ReadMiscellaneousValues() {
qt_config->beginGroup(QStringLiteral("Miscellaneous"));
ReadBasicSetting(Settings::values.log_filter);
ReadBasicSetting(Settings::values.enable_gamemode);
qt_config->endGroup();
}
@ -1044,6 +1045,7 @@ void Config::SaveMiscellaneousValues() {
qt_config->beginGroup(QStringLiteral("Miscellaneous"));
WriteBasicSetting(Settings::values.log_filter);
WriteBasicSetting(Settings::values.enable_gamemode);
qt_config->endGroup();
}

View file

@ -36,6 +36,9 @@ ConfigureGeneral::ConfigureGeneral(QWidget* parent)
ui->emulation_speed_combo->setVisible(!Settings::IsConfiguringGlobal());
ui->screenshot_combo->setVisible(!Settings::IsConfiguringGlobal());
ui->updateBox->setVisible(UISettings::values.updater_found);
#ifndef __unix__
ui->toggle_gamemode->setVisible(false);
#endif
SetupPerGameUI();
SetConfiguration();
@ -76,6 +79,9 @@ void ConfigureGeneral::SetConfiguration() {
ui->toggle_update_check->setChecked(
UISettings::values.check_for_update_on_start.GetValue());
ui->toggle_auto_update->setChecked(UISettings::values.update_on_close.GetValue());
#ifdef __unix__
ui->toggle_gamemode->setChecked(Settings::values.enable_gamemode.GetValue());
#endif
}
if (Settings::values.frame_limit.GetValue() == 0) {
@ -172,6 +178,9 @@ void ConfigureGeneral::ApplyConfiguration() {
UISettings::values.check_for_update_on_start = ui->toggle_update_check->isChecked();
UISettings::values.update_on_close = ui->toggle_auto_update->isChecked();
#ifdef __unix__
Settings::values.enable_gamemode = ui->toggle_gamemode->isChecked();
#endif
}
}
@ -201,6 +210,7 @@ void ConfigureGeneral::SetupPerGameUI() {
ui->general_group->setVisible(false);
ui->updateBox->setVisible(false);
ui->button_reset_defaults->setVisible(false);
ui->toggle_gamemode->setVisible(false);
ConfigurationShared::SetColoredComboBox(
ui->region_combobox, ui->widget_region,

View file

@ -43,6 +43,13 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="toggle_gamemode">
<property name="text">
<string>Enable Gamemode</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>

View file

@ -26,6 +26,7 @@
#include <QVariant>
#include <QtDBus/QDBusInterface>
#include <QtDBus/QtDBus>
#include "common/linux/gamemode.h"
#endif
#include "citra_qt/aboutdialog.h"
#include "citra_qt/applets/mii_selector.h"
@ -182,6 +183,10 @@ GMainWindow::GMainWindow(Core::System& system_)
Debugger::ToggleConsole();
#ifdef __unix__
SetGamemodeEnabled(Settings::values.enable_gamemode.GetValue());
#endif
// register types to use in slots and signals
qRegisterMetaType<std::size_t>("std::size_t");
qRegisterMetaType<Service::AM::InstallStatus>("Service::AM::InstallStatus");
@ -1323,6 +1328,10 @@ void GMainWindow::ShutdownGame() {
discord_rpc->Update();
#ifdef __unix__
Common::Linux::StopGamemode();
#endif
// The emulation is stopped, so closing the window or not does not matter anymore
disconnect(render_window, &GRenderWindow::Closed, this, &GMainWindow::OnStopGame);
disconnect(secondary_window, &GRenderWindow::Closed, this, &GMainWindow::OnStopGame);
@ -1834,6 +1843,10 @@ void GMainWindow::OnStartGame() {
discord_rpc->Update();
#ifdef __unix__
Common::Linux::StartGamemode();
#endif
UpdateSaveStates();
UpdateAPIIndicator();
}
@ -1852,6 +1865,10 @@ void GMainWindow::OnPauseGame() {
UpdateMenuState();
AllowOSSleep();
#ifdef __unix__
Common::Linux::StopGamemode();
#endif
}
void GMainWindow::OnPauseContinueGame() {
@ -2076,15 +2093,25 @@ void GMainWindow::OnConfigure() {
const auto old_input_profiles = Settings::values.input_profiles;
const auto old_touch_from_button_maps = Settings::values.touch_from_button_maps;
const bool old_discord_presence = UISettings::values.enable_discord_presence.GetValue();
#ifdef __unix__
const bool old_gamemode = Settings::values.enable_gamemode.GetValue();
#endif
auto result = configureDialog.exec();
game_list->SetDirectoryWatcherEnabled(true);
if (result == QDialog::Accepted) {
configureDialog.ApplyConfiguration();
InitializeHotkeys();
if (UISettings::values.theme != old_theme)
if (UISettings::values.theme != old_theme) {
UpdateUITheme();
if (UISettings::values.enable_discord_presence.GetValue() != old_discord_presence)
}
if (UISettings::values.enable_discord_presence.GetValue() != old_discord_presence) {
SetDiscordEnabled(UISettings::values.enable_discord_presence.GetValue());
}
#ifdef __unix__
if (Settings::values.enable_gamemode.GetValue() != old_gamemode) {
SetGamemodeEnabled(Settings::values.enable_gamemode.GetValue());
}
#endif
if (!multiplayer_state->IsHostingPublicRoom())
multiplayer_state->UpdateCredentials();
emit UpdateThemedIcons();
@ -2931,6 +2958,14 @@ void GMainWindow::SetDiscordEnabled([[maybe_unused]] bool state) {
discord_rpc->Update();
}
#ifdef __unix__
void GMainWindow::SetGamemodeEnabled(bool state) {
if (emulation_running) {
Common::Linux::SetGamemodeState(state);
}
}
#endif
#ifdef main
#undef main
#endif

View file

@ -276,6 +276,9 @@ private:
void ShowMouseCursor();
void OpenPerGameConfiguration(u64 title_id, const QString& file_name);
void UpdateAPIIndicator(bool update = false);
#ifdef __unix__
void SetGamemodeEnabled(bool state);
#endif
std::unique_ptr<Ui::MainWindow> ui;
Core::System& system;

View file

@ -154,6 +154,15 @@ add_library(citra_common STATIC
zstd_compression.h
)
if (UNIX AND NOT APPLE)
target_sources(citra_common PRIVATE
linux/gamemode.cpp
linux/gamemode.h
)
target_link_libraries(citra_common PRIVATE gamemode)
endif()
if (APPLE)
target_sources(citra_common PUBLIC
apple_authorization.h

View file

@ -0,0 +1,39 @@
// 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/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

@ -0,0 +1,24 @@
// 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

@ -421,6 +421,8 @@ struct Values {
std::vector<InputProfile> input_profiles; ///< The list of input profiles
std::vector<TouchFromButtonMap> touch_from_button_maps;
SwitchableSetting<bool> enable_gamemode{true, "enable_gamemode"};
// Core
Setting<bool> use_cpu_jit{true, "use_cpu_jit"};
SwitchableSetting<s32, true> cpu_clock_percentage{100, 5, 400, "cpu_clock_percentage"};