1/*
2 This file is part of the KDE project
3 SPDX-FileCopyrightText: 2023 Dave Vasilevsky <dave@vasilevsky.ca>
4
5 SPDX-License-Identifier: LGPL-2.0-only OR LGPL-3.0-only
6*/
7
8#include "gpudetection_p.h"
9
10#ifndef KIO_ANDROID_STUB
11#include <QDBusArgument>
12#include <QDBusConnection>
13#include <QDBusInterface>
14#include <QDBusReply>
15#include <QDBusVariant>
16#endif
17#include <QMap>
18#include <QString>
19
20#include <KProcess>
21
22static void checkGpu();
23// Returns true if switcheroo present
24static bool checkGpuWithSwitcheroo();
25static void checkGpuWithSolid();
26
27// TODO: GPUs are hot-swappable, watch for changes using dbus PropertiesChanged
28enum class GpuCheck {
29 NotChecked,
30 Present,
31 Absent,
32};
33static GpuCheck s_gpuCheck = GpuCheck::NotChecked;
34static QProcessEnvironment s_gpuEnv;
35
36static void checkGpu()
37{
38 if (s_gpuCheck == GpuCheck::NotChecked) {
39 if (!checkGpuWithSwitcheroo()) {
40 checkGpuWithSolid();
41 }
42 }
43}
44
45static bool checkGpuWithSwitcheroo()
46{
47#ifndef KIO_ANDROID_STUB
48 QDBusInterface switcheroo(QStringLiteral("net.hadess.SwitcherooControl"),
49 QStringLiteral("/net/hadess/SwitcherooControl"),
50 QStringLiteral("org.freedesktop.DBus.Properties"),
51 QDBusConnection::systemBus());
52 if (!switcheroo.isValid()) {
53 return false;
54 }
55
56 QDBusReply<QDBusVariant> reply = switcheroo.call(QStringLiteral("Get"), QStringLiteral("net.hadess.SwitcherooControl"), QStringLiteral("GPUs"));
57 if (!reply.isValid()) {
58 return false;
59 }
60
61 QDBusArgument arg = qvariant_cast<QDBusArgument>(v: reply.value().variant());
62 QList<QVariantMap> gpus;
63 arg >> gpus;
64
65 for (const auto &gpu : gpus) {
66 bool defaultGpu = qvariant_cast<bool>(v: gpu[QStringLiteral("Default")]);
67 if (!defaultGpu) {
68 s_gpuCheck = GpuCheck::Present;
69 QStringList envList = qvariant_cast<QStringList>(v: gpu[QStringLiteral("Environment")]);
70 for (int i = 0; i + 1 < envList.size(); i += 2) {
71 s_gpuEnv.insert(name: envList[i], value: envList[i + 1]);
72 }
73 return true;
74 }
75 }
76#endif
77
78 // No non-default GPU found
79 s_gpuCheck = GpuCheck::Absent;
80 return true;
81}
82
83static void checkGpuWithSolid()
84{
85#ifndef KIO_ANDROID_STUB
86 // TODO: Consider moving this check into kio, instead of using Solid
87 QDBusInterface iface(QStringLiteral("org.kde.Solid.PowerManagement"),
88 QStringLiteral("/org/kde/Solid/PowerManagement"),
89 QStringLiteral("org.kde.Solid.PowerManagement"),
90 QDBusConnection::sessionBus());
91 if (iface.isValid()) {
92 QDBusReply<bool> reply = iface.call(QStringLiteral("hasDualGpu"));
93 if (reply.isValid() && reply.value()) {
94 s_gpuCheck = GpuCheck::Present;
95 s_gpuEnv.insert(QStringLiteral("DRI_PRIME"), QStringLiteral("1"));
96 return;
97 }
98 }
99
100 s_gpuCheck = GpuCheck::Absent;
101#endif
102}
103
104namespace KIO
105{
106
107bool hasDiscreteGpu()
108{
109 checkGpu();
110 return s_gpuCheck == GpuCheck::Present;
111}
112
113QProcessEnvironment discreteGpuEnvironment()
114{
115 checkGpu();
116 return s_gpuEnv;
117}
118
119}
120

source code of kio/src/gui/gpudetection.cpp