File indexing completed on 2025-01-12 03:39:37
0001 /* 0002 This file is part of the KDE project 0003 SPDX-FileCopyrightText: 2023 Dave Vasilevsky <dave@vasilevsky.ca> 0004 0005 SPDX-License-Identifier: LGPL-2.0-only OR LGPL-3.0-only 0006 */ 0007 0008 #include "gpudetection_p.h" 0009 0010 #ifndef KIO_ANDROID_STUB 0011 #include <QDBusArgument> 0012 #include <QDBusConnection> 0013 #include <QDBusInterface> 0014 #include <QDBusReply> 0015 #include <QDBusVariant> 0016 #endif 0017 #include <QMap> 0018 #include <QString> 0019 0020 #include <KProcess> 0021 0022 static void checkGpu(); 0023 // Returns true if switcheroo present 0024 static bool checkGpuWithSwitcheroo(); 0025 static void checkGpuWithSolid(); 0026 0027 // TODO: GPUs are hot-swappable, watch for changes using dbus PropertiesChanged 0028 enum class GpuCheck { 0029 NotChecked, 0030 Present, 0031 Absent, 0032 }; 0033 static GpuCheck s_gpuCheck = GpuCheck::NotChecked; 0034 static QProcessEnvironment s_gpuEnv; 0035 0036 static void checkGpu() 0037 { 0038 if (s_gpuCheck == GpuCheck::NotChecked) { 0039 if (!checkGpuWithSwitcheroo()) { 0040 checkGpuWithSolid(); 0041 } 0042 } 0043 } 0044 0045 static bool checkGpuWithSwitcheroo() 0046 { 0047 #ifndef KIO_ANDROID_STUB 0048 QDBusInterface switcheroo(QStringLiteral("net.hadess.SwitcherooControl"), 0049 QStringLiteral("/net/hadess/SwitcherooControl"), 0050 QStringLiteral("org.freedesktop.DBus.Properties"), 0051 QDBusConnection::systemBus()); 0052 if (!switcheroo.isValid()) { 0053 return false; 0054 } 0055 0056 QDBusReply<QDBusVariant> reply = switcheroo.call(QStringLiteral("Get"), QStringLiteral("net.hadess.SwitcherooControl"), QStringLiteral("GPUs")); 0057 if (!reply.isValid()) { 0058 return false; 0059 } 0060 0061 QDBusArgument arg = qvariant_cast<QDBusArgument>(reply.value().variant()); 0062 QList<QVariantMap> gpus; 0063 arg >> gpus; 0064 0065 for (const auto &gpu : gpus) { 0066 bool defaultGpu = qvariant_cast<bool>(gpu[QStringLiteral("Default")]); 0067 if (!defaultGpu) { 0068 s_gpuCheck = GpuCheck::Present; 0069 QStringList envList = qvariant_cast<QStringList>(gpu[QStringLiteral("Environment")]); 0070 for (int i = 0; i + 1 < envList.size(); i += 2) { 0071 s_gpuEnv.insert(envList[i], envList[i + 1]); 0072 } 0073 return true; 0074 } 0075 } 0076 #endif 0077 0078 // No non-default GPU found 0079 s_gpuCheck = GpuCheck::Absent; 0080 return true; 0081 } 0082 0083 static void checkGpuWithSolid() 0084 { 0085 #ifndef KIO_ANDROID_STUB 0086 // TODO: Consider moving this check into kio, instead of using Solid 0087 QDBusInterface iface(QStringLiteral("org.kde.Solid.PowerManagement"), 0088 QStringLiteral("/org/kde/Solid/PowerManagement"), 0089 QStringLiteral("org.kde.Solid.PowerManagement"), 0090 QDBusConnection::sessionBus()); 0091 if (iface.isValid()) { 0092 QDBusReply<bool> reply = iface.call(QStringLiteral("hasDualGpu")); 0093 if (reply.isValid() && reply.value()) { 0094 s_gpuCheck = GpuCheck::Present; 0095 s_gpuEnv.insert(QStringLiteral("DRI_PRIME"), QStringLiteral("1")); 0096 return; 0097 } 0098 } 0099 0100 s_gpuCheck = GpuCheck::Absent; 0101 #endif 0102 } 0103 0104 namespace KIO 0105 { 0106 0107 bool hasDiscreteGpu() 0108 { 0109 checkGpu(); 0110 return s_gpuCheck == GpuCheck::Present; 0111 } 0112 0113 QProcessEnvironment discreteGpuEnvironment() 0114 { 0115 checkGpu(); 0116 return s_gpuEnv; 0117 } 0118 0119 }