Commit dbef4fa3 authored by Vlad Zahorodnii's avatar Vlad Zahorodnii
Browse files

backends/drm: Rework GPU removal

The proposed way to handle unplugged gpus allows us to ensure that
removed outputs' lifetime can be extended to the moment when the
Platform::outputsQueried signal is emitted.

Besides that, it's possible to extend this code a bit further to make
sure that output updates are batched when hotplugging multiple gpus,
e.g. after resuming, etc.
parent 383b054e
......@@ -254,7 +254,7 @@ void DrmBackend::handleUdevEvent()
QCoreApplication::exit(1);
return;
} else {
removeGpu(gpu);
gpu->setRemoved();
updateOutputs();
}
}
......@@ -303,17 +303,6 @@ DrmGpu *DrmBackend::addGpu(const QString &fileName)
return gpu;
}
void DrmBackend::removeGpu(DrmGpu *gpu)
{
auto it = std::find_if(m_gpus.begin(), m_gpus.end(), [gpu](const auto &g) {
return g.get() == gpu;
});
if (it != m_gpus.end()) {
qCDebug(KWIN_DRM) << "Removing gpu" << gpu->devNode();
m_gpus.erase(it);
}
}
void DrmBackend::addOutput(DrmAbstractOutput *o)
{
m_outputs.append(o);
......@@ -330,18 +319,25 @@ void DrmBackend::removeOutput(DrmAbstractOutput *o)
void DrmBackend::updateOutputs()
{
for (auto it = m_gpus.begin(); it < m_gpus.end();) {
auto gpu = it->get();
gpu->updateOutputs();
if (gpu->drmOutputs().isEmpty() && gpu != primaryGpu()) {
qCDebug(KWIN_DRM) << "removing unused GPU" << gpu->devNode();
it = m_gpus.erase(it);
for (auto it = m_gpus.begin(); it != m_gpus.end(); ++it) {
if ((*it)->isRemoved()) {
(*it)->removeOutputs();
} else {
it++;
(*it)->updateOutputs();
}
}
Q_EMIT screensQueried();
for (auto it = m_gpus.begin(); it != m_gpus.end();) {
DrmGpu *gpu = it->get();
if (gpu->isRemoved() || (gpu != primaryGpu() && gpu->drmOutputs().isEmpty())) {
qCDebug(KWIN_DRM) << "Removing GPU" << (*it)->devNode();
it = m_gpus.erase(it);
} else {
it++;
}
}
}
std::unique_ptr<InputBackend> DrmBackend::createInputBackend()
......
......@@ -93,7 +93,6 @@ private:
void reactivate();
void deactivate();
void handleUdevEvent();
void removeGpu(DrmGpu *gpu);
DrmGpu *addGpu(const QString &fileName);
std::unique_ptr<Udev> m_udev;
......
......@@ -113,16 +113,7 @@ DrmGpu::DrmGpu(DrmBackend *backend, const QString &devNode, int fd, dev_t device
DrmGpu::~DrmGpu()
{
waitIdle();
const auto outputs = m_drmOutputs;
for (const auto &output : outputs) {
removeOutput(output);
}
const auto virtualOutputs = m_virtualOutputs;
for (const auto &output : virtualOutputs) {
removeVirtualOutput(output);
}
removeOutputs();
if (m_eglDisplay != EGL_NO_DISPLAY) {
eglTerminate(m_eglDisplay);
}
......@@ -340,6 +331,20 @@ bool DrmGpu::updateOutputs()
return true;
}
void DrmGpu::removeOutputs()
{
waitIdle();
const auto outputs = m_drmOutputs;
for (const auto &output : outputs) {
removeOutput(output);
}
const auto virtualOutputs = m_virtualOutputs;
for (const auto &output : virtualOutputs) {
removeVirtualOutput(output);
}
}
DrmPipeline::Error DrmGpu::checkCrtcAssignment(QVector<DrmConnector *> connectors, const QVector<DrmCrtc *> &crtcs)
{
if (connectors.isEmpty() || crtcs.isEmpty()) {
......@@ -709,6 +714,16 @@ bool DrmGpu::isNVidia() const
return m_isNVidia;
}
bool DrmGpu::isRemoved() const
{
return m_isRemoved;
}
void DrmGpu::setRemoved()
{
m_isRemoved = true;
}
bool DrmGpu::needsModeset() const
{
return std::any_of(m_pipelines.constBegin(), m_pipelines.constEnd(), [](const auto &pipeline) {
......
......@@ -54,6 +54,9 @@ public:
dev_t deviceId() const;
QString devNode() const;
bool isRemoved() const;
void setRemoved();
bool atomicModeSetting() const;
bool addFB2ModifiersSupported() const;
bool isNVidia() const;
......@@ -74,6 +77,7 @@ public:
void setEglDisplay(EGLDisplay display);
bool updateOutputs();
void removeOutputs();
DrmVirtualOutput *createVirtualOutput(const QString &name, const QSize &size, double scale);
void removeVirtualOutput(DrmVirtualOutput *output);
......@@ -112,6 +116,7 @@ private:
bool m_addFB2ModifiersSupported = false;
bool m_isNVidia;
bool m_isVirtualMachine;
bool m_isRemoved = false;
clockid_t m_presentationClock;
gbm_device *m_gbmDevice;
EGLDisplay m_eglDisplay = EGL_NO_DISPLAY;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment