drm: Fix hotplugging docking stations

Summary:
It turns out DRM connectors are not static and may change over time.
This patch refreshes them right before looking for new outputs.

BUG: 419061
FIXED-IN: 5.19.0

Test Plan:
Seems to work better, it's still not ideal but I think there's an unrelated bug
sending updates to clients.

Reviewers: #kwin, davidedmundson, meven

Reviewed By: #kwin, davidedmundson, meven

Subscribers: dalbers, kwin

Tags: #kwin

Differential Revision: https://phabricator.kde.org/D28642
icc-effect-master
Aleix Pol 2020-04-07 13:24:08 +02:00
parent 6a33533816
commit 85b322ad9c
2 changed files with 49 additions and 31 deletions

View File

@ -320,34 +320,9 @@ void DrmBackend::openDrm()
}
}
DrmScopedPointer<drmModeRes> resources(drmModeGetResources(m_fd));
if (!resources) {
qCWarning(KWIN_DRM) << "drmModeGetResources failed";
return;
}
for (int i = 0; i < resources->count_connectors; ++i) {
m_connectors << new DrmConnector(resources->connectors[i], m_fd);
}
for (int i = 0; i < resources->count_crtcs; ++i) {
m_crtcs << new DrmCrtc(resources->crtcs[i], this, i);
}
if (m_atomicModeSetting) {
auto tryAtomicInit = [] (DrmObject *obj) -> bool {
if (obj->atomicInit()) {
return false;
} else {
delete obj;
return true;
}
};
m_connectors.erase(std::remove_if(m_connectors.begin(), m_connectors.end(), tryAtomicInit), m_connectors.end());
m_crtcs.erase(std::remove_if(m_crtcs.begin(), m_crtcs.end(), tryAtomicInit), m_crtcs.end());
}
initCursor();
updateOutputs();
if (!updateOutputs())
return;
if (m_outputs.isEmpty()) {
qCDebug(KWIN_DRM) << "No connected outputs found on startup.";
@ -381,16 +356,55 @@ void DrmBackend::openDrm()
setReady(true);
}
void DrmBackend::updateOutputs()
bool DrmBackend::updateOutputs()
{
if (m_fd < 0) {
return;
return false;
}
DrmScopedPointer<drmModeRes> resources(drmModeGetResources(m_fd));
if (!resources) {
qCWarning(KWIN_DRM) << "drmModeGetResources failed";
return;
return false;
}
auto oldConnectors = m_connectors;
for (int i = 0; i < resources->count_connectors; ++i) {
const uint32_t currentConnector = resources->connectors[i];
auto it = std::find_if(m_connectors.constBegin(), m_connectors.constEnd(), [currentConnector] (DrmConnector *c) { return c->id() == currentConnector; });
if (it == m_connectors.constEnd()) {
auto c = new DrmConnector(currentConnector, m_fd);
if (m_atomicModeSetting && !c->atomicInit()) {
delete c;
continue;
}
m_connectors << c;
} else {
oldConnectors.removeOne(*it);
}
}
auto oldCrtcs = m_crtcs;
for (int i = 0; i < resources->count_crtcs; ++i) {
const uint32_t currentCrtc = resources->crtcs[i];
auto it = std::find_if(m_crtcs.constBegin(), m_crtcs.constEnd(), [currentCrtc] (DrmCrtc *c) { return c->id() == currentCrtc; });
if (it == m_crtcs.constEnd()) {
auto c = new DrmCrtc(currentCrtc, this, i);
if (m_atomicModeSetting && !c->atomicInit()) {
delete c;
continue;
}
m_crtcs << c;
} else {
oldCrtcs.removeOne(*it);
}
}
for (auto c : qAsConst(oldConnectors)) {
m_connectors.removeOne(c);
}
for (auto c : qAsConst(oldCrtcs)) {
m_crtcs.removeOne(c);
}
QVector<DrmOutput*> connectedOutputs;
@ -503,6 +517,10 @@ void DrmBackend::updateOutputs()
if (!m_outputs.isEmpty()) {
emit screensQueried();
}
qDeleteAll(oldConnectors);
qDeleteAll(oldCrtcs);
return true;
}
void DrmBackend::readOutputsConfiguration()

View File

@ -156,7 +156,7 @@ private:
void activate(bool active);
void reactivate();
void deactivate();
void updateOutputs();
bool updateOutputs();
void setCursor();
void updateCursor();
void moveCursor(Cursor *cursor, const QPoint &pos);