File indexing completed on 2024-05-12 17:00:15

0001 /*
0002  * SPDX-FileCopyrightText: 2020 Arjen Hiemstra <ahiemstra@heimr.nl>
0003  * 
0004  * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  */
0006 
0007 #include "LinuxBackend.h"
0008 
0009 #include <KLocalizedString>
0010 #include <QDebug>
0011 
0012 #include <libudev.h>
0013 
0014 #include "LinuxAmdGpu.h"
0015 #include "LinuxNvidiaGpu.h"
0016 
0017 // Vendor ID strings, as used in sysfs
0018 static const char *amdVendor = "0x1002";
0019 static const char *intelVendor = "0x8086";
0020 static const char *nvidiaVendor = "0x10de";
0021 
0022 LinuxBackend::LinuxBackend(QObject *parent)
0023     : GpuBackend(parent)
0024 {
0025 }
0026 
0027 void LinuxBackend::start()
0028 {
0029     if (!m_udev) {
0030         m_udev = udev_new();
0031     }
0032 
0033     auto enumerate = udev_enumerate_new(m_udev);
0034 
0035     udev_enumerate_add_match_property(enumerate, "DEVTYPE", "drm_minor");
0036     udev_enumerate_add_match_subsystem(enumerate, "drm");
0037     udev_enumerate_scan_devices(enumerate);
0038 
0039     auto devices = udev_enumerate_get_list_entry(enumerate);
0040     for (auto entry = devices; entry; entry = udev_list_entry_get_next(entry)) {
0041         auto path = udev_list_entry_get_name(entry);
0042         auto drmDevice = udev_device_new_from_syspath(m_udev, path);
0043         auto pciDevice = udev_device_get_parent(drmDevice);
0044 
0045         if (strstr(udev_device_get_sysname(drmDevice), "render") != NULL) {
0046             udev_device_unref(drmDevice);
0047             continue;
0048         }
0049 
0050         auto vendor = QByteArray(udev_device_get_sysattr_value(pciDevice, "vendor"));
0051         auto drmNumber = std::atoi(udev_device_get_sysnum(drmDevice));
0052 
0053         auto gpuId = QStringLiteral("gpu%1").arg(drmNumber);
0054         auto gpuName = i18nc("@title %1 is GPU number", "GPU %1", drmNumber + 1);
0055 
0056         GpuDevice *gpu = nullptr;
0057         if (vendor == amdVendor) {
0058             gpu = new LinuxAmdGpu{gpuId, gpuName, pciDevice};
0059         } else if (vendor == nvidiaVendor) {
0060             gpu = new LinuxNvidiaGpu{gpuId, gpuName, pciDevice};
0061         } else {
0062             qDebug() << "Found unsupported GPU:" << path;
0063             udev_device_unref(drmDevice);
0064             continue;
0065         }
0066 
0067         gpu->initialize();
0068         m_devices.append(gpu);
0069         Q_EMIT deviceAdded(gpu);
0070 
0071         udev_device_unref(drmDevice);
0072     }
0073 
0074     udev_enumerate_unref(enumerate);
0075 }
0076 
0077 void LinuxBackend::stop()
0078 {
0079     qDeleteAll(m_devices);
0080     udev_unref(m_udev);
0081 }
0082 
0083 void LinuxBackend::update()
0084 {
0085     for (auto device : qAsConst(m_devices)) {
0086         device->update();
0087     }
0088 }
0089 
0090 int LinuxBackend::deviceCount()
0091 {
0092     return m_devices.count();
0093 }