platforms/drm: Introduce KWIN_DRM_DEVICES

This allows to instruct kwin what drm devices must be used explicitly.

BUG: 435467
This commit is contained in:
Vlad Zahorodnii 2021-04-30 10:05:49 +03:00
parent 23e3a9a86f
commit 8d9e47ee22
7 changed files with 34 additions and 19 deletions

View file

@ -40,6 +40,7 @@
#include <QSocketNotifier>
// system
#include <algorithm>
#include <sys/stat.h>
#include <unistd.h>
// drm
#include <xf86drm.h>
@ -176,9 +177,16 @@ bool DrmBackend::initialize()
connect(session(), &Session::activeChanged, this, &DrmBackend::activate);
connect(session(), &Session::awoke, this, &DrmBackend::turnOutputsOn);
std::vector<UdevDevice::Ptr> 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<UdevDevice> 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;

View file

@ -92,7 +92,7 @@ private:
void writeOutputsConfiguration();
QString generateOutputConfigurationUuid() const;
void handleUdevEvent();
DrmGpu *addGpu(std::unique_ptr<UdevDevice> device);
DrmGpu *addGpu(const QString &fileName);
QScopedPointer<Udev> m_udev;
QScopedPointer<UdevMonitor> m_udevMonitor;

View file

@ -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)

View file

@ -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;

View file

@ -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;

View file

@ -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

View file

@ -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);