diff --git a/launcher/Application.cpp b/launcher/Application.cpp index ab23f013..3f313ee4 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -126,6 +126,7 @@ #ifdef Q_OS_LINUX #include #include "gamemode_client.h" +#include "MangoHud.h" #endif @@ -1525,17 +1526,8 @@ void Application::updateCapabilities() if (gamemode_query_status() >= 0) m_capabilities |= SupportsGameMode; - { - void *dummy = dlopen("libMangoHud_dlsym.so", RTLD_LAZY); - // try normal variant as well - if (dummy == NULL) - dummy = dlopen("libMangoHud.so", RTLD_LAZY); - - if (dummy != NULL) { - dlclose(dummy); - m_capabilities |= SupportsMangoHud; - } - } + if (!MangoHud::getLibraryString().isEmpty()) + m_capabilities |= SupportsMangoHud; #endif } diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 33086121..439feb44 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -92,6 +92,15 @@ set(CORE_SOURCES MTPixmapCache.h ) +if (UNIX AND NOT CYGWIN AND NOT APPLE) +set(CORE_SOURCES + ${CORE_SOURCES} + + # MangoHud + MangoHud.h + MangoHud.cpp + ) +endif() set(PATHMATCHER_SOURCES # Path matchers diff --git a/launcher/MangoHud.cpp b/launcher/MangoHud.cpp new file mode 100644 index 00000000..d635518e --- /dev/null +++ b/launcher/MangoHud.cpp @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * PrismLauncher - Minecraft Launcher + * Copyright (C) 2022 Jan Drögehoff + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include + +#include "MangoHud.h" +#include "FileSystem.h" +#include "Json.h" + +namespace MangoHud { + +QString getLibraryString() +{ + /* + * Check for vulkan layers in this order: + * + * $VK_LAYER_PATH + * $XDG_DATA_DIRS (/usr/local/share/:/usr/share/) + * $XDG_DATA_HOME (~/.local/share) + * /etc + * $XDG_CONFIG_DIRS (/etc/xdg) + * $XDG_CONFIG_HOME (~/.config) + */ + + QStringList vkLayerList; + { + QString home = QDir::homePath(); + + QString vkLayerPath = qEnvironmentVariable("VK_LAYER_PATH"); + if (!vkLayerPath.isEmpty()) { + vkLayerList << vkLayerPath; + } + + QStringList xdgDataDirs = qEnvironmentVariable("XDG_DATA_DIRS", "/usr/local/share/:/usr/share/").split(QLatin1String(":")); + for (QString dir : xdgDataDirs) { + vkLayerList << FS::PathCombine(dir, "vulkan", "implicit_layer.d"); + } + + QString xdgDataHome = qEnvironmentVariable("XDG_DATA_HOME"); + if (xdgDataHome.isEmpty()) { + xdgDataHome = FS::PathCombine(home, ".local", "share"); + } + vkLayerList << FS::PathCombine(xdgDataHome, "vulkan", "implicit_layer.d"); + + vkLayerList << "/etc"; + + QStringList xdgConfigDirs = qEnvironmentVariable("XDG_CONFIG_DIRS", "/etc/xdg").split(QLatin1String(":")); + for (QString dir : xdgConfigDirs) { + vkLayerList << FS::PathCombine(dir, "vulkan", "implicit_layer.d"); + } + + QString xdgConfigHome = qEnvironmentVariable("XDG_CONFIG_HOME"); + if (xdgConfigHome.isEmpty()) { + xdgConfigHome = FS::PathCombine(home, ".config"); + } + vkLayerList << FS::PathCombine(xdgConfigHome, "vulkan", "implicit_layer.d"); + } + + for (QString vkLayer : vkLayerList) { + QString filePath = FS::PathCombine(vkLayer, "MangoHud.json"); + if (!QFile::exists(filePath)) + continue; + + auto conf = Json::requireDocument(filePath, vkLayer); + auto confObject = Json::requireObject(conf, vkLayer); + auto layer = Json::ensureObject(confObject, "layer"); + return Json::ensureString(layer, "library_path"); + } + + return QString(); +} +} // namespace MangoHud diff --git a/launcher/MangoHud.h b/launcher/MangoHud.h new file mode 100644 index 00000000..7b7c2849 --- /dev/null +++ b/launcher/MangoHud.h @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * PrismLauncher - Minecraft Launcher + * Copyright (C) 2022 Jan Drögehoff + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include + +namespace MangoHud { + +QString getLibraryString(); +} diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index a3adb268..1d37224a 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -88,6 +88,10 @@ #include "minecraft/gameoptions/GameOptions.h" #include "minecraft/update/FoldersTask.h" +#ifdef Q_OS_LINUX +#include "MangoHud.h" +#endif + #define IBUS "@im=ibus" // all of this because keeping things compatible with deprecated old settings @@ -482,9 +486,22 @@ QProcessEnvironment MinecraftInstance::createLaunchEnvironment() #ifdef Q_OS_LINUX if (settings()->get("EnableMangoHud").toBool() && APPLICATION->capabilities() & Application::SupportsMangoHud) { - auto preload = env.value("LD_PRELOAD", "") + ":libMangoHud_dlsym.so:libMangoHud.so"; - env.insert("LD_PRELOAD", preload); + auto preloadList = env.value("LD_PRELOAD").split(QLatin1String(":")); + auto libPaths = env.value("LD_LIBRARY_PATH").split(QLatin1String(":")); + + auto mangoHudLibString = MangoHud::getLibraryString(); + if (!mangoHudLibString.isEmpty()) + { + QFileInfo mangoHudLib(mangoHudLibString); + + // dlsym variant is only needed for OpenGL and not included in the vulkan layer + preloadList << "libMangoHud_dlsym.so" << mangoHudLib.fileName(); + libPaths << mangoHudLib.absolutePath(); + } + + env.insert("LD_PRELOAD", preloadList.join(QLatin1String(":"))); + env.insert("LD_LIBRARY_PATH", libPaths.join(QLatin1String(":"))); env.insert("MANGOHUD", "1"); }