From 8d9e47ee227c16e81dd0a6db3f12a94fcd14dc48 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Fri, 30 Apr 2021 10:05:49 +0300 Subject: [PATCH] platforms/drm: Introduce KWIN_DRM_DEVICES This allows to instruct kwin what drm devices must be used explicitly. BUG: 435467 --- src/plugins/platforms/drm/drm_backend.cpp | 33 ++++++++++++++++------ src/plugins/platforms/drm/drm_backend.h | 2 +- src/plugins/platforms/drm/drm_gpu.cpp | 2 +- src/plugins/platforms/drm/drm_gpu.h | 6 ++-- src/plugins/platforms/fbdev/fb_backend.cpp | 4 +-- src/udev.cpp | 4 +-- src/udev.h | 2 +- 7 files changed, 34 insertions(+), 19 deletions(-) diff --git a/src/plugins/platforms/drm/drm_backend.cpp b/src/plugins/platforms/drm/drm_backend.cpp index b1dd60dab8..538bb46554 100644 --- a/src/plugins/platforms/drm/drm_backend.cpp +++ b/src/plugins/platforms/drm/drm_backend.cpp @@ -40,6 +40,7 @@ #include // system #include +#include #include // drm #include @@ -176,9 +177,16 @@ bool DrmBackend::initialize() connect(session(), &Session::activeChanged, this, &DrmBackend::activate); connect(session(), &Session::awoke, this, &DrmBackend::turnOutputsOn); - std::vector devices = m_udev->listGPUs(); - for (unsigned int gpu_index = 0; gpu_index < devices.size(); gpu_index++) { - addGpu(std::move(devices.at(gpu_index))); + const QStringList explicitGpus = qEnvironmentVariable("KWIN_DRM_DEVICES").split(':', Qt::SkipEmptyParts); + if (!explicitGpus.isEmpty()) { + for (const QString &fileName : explicitGpus) { + addGpu(fileName); + } + } else { + const auto devices = m_udev->listGPUs(); + for (const UdevDevice::Ptr &device : devices) { + addGpu(device->devNode()); + } } if (m_gpus.isEmpty()) { @@ -217,7 +225,7 @@ void DrmBackend::handleUdevEvent() if (device->action() == QStringLiteral("add")) { if (m_gpus.isEmpty() || !primaryGpu()->useEglStreams()) { - if (const auto &gpu = addGpu(std::move(device))) { + if (const auto &gpu = addGpu(device->devNode())) { updateOutputs(); updateCursor(); emit gpuAdded(gpu); @@ -249,24 +257,31 @@ void DrmBackend::handleUdevEvent() } } -DrmGpu *DrmBackend::addGpu(std::unique_ptr device) +DrmGpu *DrmBackend::addGpu(const QString &fileName) { - int fd = session()->openRestricted(device->devNode()); + int fd = session()->openRestricted(fileName); if (fd < 0) { - qCWarning(KWIN_DRM) << "failed to open drm device at" << device->devNode(); + qCWarning(KWIN_DRM) << "failed to open drm device at" << fileName; return nullptr; } // try to make a simple drm get resource call, if it fails it is not useful for us drmModeRes *resources = drmModeGetResources(fd); if (!resources) { - qCDebug(KWIN_DRM) << "Skipping KMS incapable drm device node at" << device->devNode(); + qCDebug(KWIN_DRM) << "Skipping KMS incapable drm device node at" << fileName; session()->closeRestricted(fd); return nullptr; } drmModeFreeResources(resources); - DrmGpu *gpu = new DrmGpu(this, device->devNode(), fd, device->devNum()); + struct stat buf; + if (fstat(fd, &buf) == -1) { + qCDebug(KWIN_DRM, "Failed to fstat %s: %s", qPrintable(fileName), strerror(errno)); + session()->closeRestricted(fd); + return nullptr; + } + + DrmGpu *gpu = new DrmGpu(this, fileName, fd, buf.st_rdev); if (!gpu->useEglStreams() || m_gpus.isEmpty()) { m_gpus.append(gpu); m_active = true; diff --git a/src/plugins/platforms/drm/drm_backend.h b/src/plugins/platforms/drm/drm_backend.h index e348716a16..0176cfb3bd 100644 --- a/src/plugins/platforms/drm/drm_backend.h +++ b/src/plugins/platforms/drm/drm_backend.h @@ -92,7 +92,7 @@ private: void writeOutputsConfiguration(); QString generateOutputConfigurationUuid() const; void handleUdevEvent(); - DrmGpu *addGpu(std::unique_ptr device); + DrmGpu *addGpu(const QString &fileName); QScopedPointer m_udev; QScopedPointer m_udevMonitor; diff --git a/src/plugins/platforms/drm/drm_gpu.cpp b/src/plugins/platforms/drm/drm_gpu.cpp index 2f491d014d..e4fe909b81 100644 --- a/src/plugins/platforms/drm/drm_gpu.cpp +++ b/src/plugins/platforms/drm/drm_gpu.cpp @@ -36,7 +36,7 @@ namespace KWin { -DrmGpu::DrmGpu(DrmBackend *backend, QByteArray devNode, int fd, dev_t deviceId) +DrmGpu::DrmGpu(DrmBackend *backend, const QString &devNode, int fd, dev_t deviceId) : m_backend(backend) , m_devNode(devNode) , m_fd(fd) diff --git a/src/plugins/platforms/drm/drm_gpu.h b/src/plugins/platforms/drm/drm_gpu.h index 0dfabdbff5..aabdfe2459 100644 --- a/src/plugins/platforms/drm/drm_gpu.h +++ b/src/plugins/platforms/drm/drm_gpu.h @@ -34,7 +34,7 @@ class DrmGpu : public QObject { Q_OBJECT public: - DrmGpu(DrmBackend *backend, QByteArray devNode, int fd, dev_t deviceId); + DrmGpu(DrmBackend *backend, const QString &devNode, int fd, dev_t deviceId); ~DrmGpu(); // getters @@ -58,7 +58,7 @@ public: return m_useEglStreams; } - QByteArray devNode() const { + QString devNode() const { return m_devNode; } @@ -118,7 +118,7 @@ private: DrmBackend* const m_backend; AbstractEglBackend *m_eglBackend; - const QByteArray m_devNode; + const QString m_devNode; QSize m_cursorSize; const int m_fd; const dev_t m_deviceId; diff --git a/src/plugins/platforms/fbdev/fb_backend.cpp b/src/plugins/platforms/fbdev/fb_backend.cpp index cddaa34748..d26273e6af 100644 --- a/src/plugins/platforms/fbdev/fb_backend.cpp +++ b/src/plugins/platforms/fbdev/fb_backend.cpp @@ -103,14 +103,14 @@ bool FramebufferBackend::initialize() { setSoftwareCursorForced(true); - QByteArray framebufferDevice = deviceIdentifier(); + QString framebufferDevice = deviceIdentifier(); if (framebufferDevice.isEmpty()) { const auto fbs = Udev().listFramebuffers(); if (fbs.size() > 0) { framebufferDevice = fbs.at(0)->devNode(); } } - int fd = open(framebufferDevice.constData(), O_RDWR | O_CLOEXEC); + int fd = open(framebufferDevice.toUtf8().constData(), O_RDWR | O_CLOEXEC); qCDebug(KWIN_FB) << "Using frame buffer device:" << framebufferDevice; if (fd < 0) { qCWarning(KWIN_FB) << "failed to open frame buffer device:" << framebufferDevice; diff --git a/src/udev.cpp b/src/udev.cpp index 5fb515e7b5..94a35a1479 100644 --- a/src/udev.cpp +++ b/src/udev.cpp @@ -208,9 +208,9 @@ UdevDevice::~UdevDevice() udev_device_unref(m_device); } -const char *UdevDevice::devNode() +QString UdevDevice::devNode() const { - return udev_device_get_devnode(m_device); + return QString::fromUtf8(udev_device_get_devnode(m_device)); } dev_t UdevDevice::devNum() const diff --git a/src/udev.h b/src/udev.h index 5dcfbd4213..4e42298934 100644 --- a/src/udev.h +++ b/src/udev.h @@ -30,7 +30,7 @@ public: UdevDevice(udev_device *device); ~UdevDevice(); - const char *devNode(); + QString devNode() const; dev_t devNum() const; const char *property(const char *key); bool hasProperty(const char *key, const char *value);