backends/drm: don't remove connectors the kernel doesn't consider removed
Removing connectors that are still powered leads to a mismatch in atomic commits: the crtc is still powered, but the connector also still there. If KWin tries to disable the crtc afterwards, the atomic commits fail because the connector needs to be disabled at the same time and it's missing from the atomic commit request. To fix this, whenever we fail to fetch information or get wrong data from the kernel (like 0 modes), use the cached information instead and keep the connector. BUG: 456298
This commit is contained in:
parent
4ced407828
commit
a71146c999
2 changed files with 27 additions and 32 deletions
|
@ -258,44 +258,38 @@ bool DrmGpu::updateOutputs()
|
|||
return c->id() == currentConnector;
|
||||
});
|
||||
DrmConnector *conn = it == m_connectors.constEnd() ? nullptr : *it;
|
||||
bool updateSuccess = true;
|
||||
if (!conn) {
|
||||
conn = new DrmConnector(this, currentConnector);
|
||||
if (!conn->init()) {
|
||||
if (!conn->init() || !conn->isConnected()) {
|
||||
delete conn;
|
||||
continue;
|
||||
}
|
||||
m_connectors << conn;
|
||||
m_allObjects << conn;
|
||||
} else if (conn->updateProperties()) {
|
||||
removedConnectors.removeOne(conn);
|
||||
} else {
|
||||
updateSuccess = false;
|
||||
}
|
||||
if (conn->isConnected() && updateSuccess) {
|
||||
if (conn->isNonDesktop() ? !findLeaseOutput(conn->id()) : !findOutput(conn->id())) {
|
||||
qCDebug(KWIN_DRM, "New %soutput on GPU %s: %s", conn->isNonDesktop() ? "non-desktop " : "", qPrintable(m_devNode), qPrintable(conn->modelName()));
|
||||
const auto pipeline = conn->pipeline();
|
||||
m_pipelines << pipeline;
|
||||
if (conn->isNonDesktop()) {
|
||||
auto leaseOutput = new DrmLeaseOutput(pipeline, m_leaseDevice);
|
||||
m_leaseOutputs << leaseOutput;
|
||||
} else {
|
||||
auto output = new DrmOutput(pipeline);
|
||||
m_drmOutputs << output;
|
||||
m_outputs << output;
|
||||
addedOutputs << output;
|
||||
Q_EMIT outputAdded(output);
|
||||
}
|
||||
pipeline->setLayers(m_platform->renderBackend()->createPrimaryLayer(pipeline), m_platform->renderBackend()->createCursorLayer(pipeline));
|
||||
pipeline->setActive(!conn->isNonDesktop());
|
||||
pipeline->applyPendingChanges();
|
||||
conn->updateProperties();
|
||||
if (conn->isConnected()) {
|
||||
removedConnectors.removeOne(conn);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else if (auto output = findOutput(conn->id())) {
|
||||
removeOutput(output);
|
||||
} else if (auto leaseOutput = findLeaseOutput(conn->id())) {
|
||||
removeLeaseOutput(leaseOutput);
|
||||
}
|
||||
qCDebug(KWIN_DRM, "New %soutput on GPU %s: %s", conn->isNonDesktop() ? "non-desktop " : "", qPrintable(m_devNode), qPrintable(conn->modelName()));
|
||||
const auto pipeline = conn->pipeline();
|
||||
m_pipelines << pipeline;
|
||||
if (conn->isNonDesktop()) {
|
||||
auto leaseOutput = new DrmLeaseOutput(pipeline, m_leaseDevice);
|
||||
m_leaseOutputs << leaseOutput;
|
||||
} else {
|
||||
auto output = new DrmOutput(pipeline);
|
||||
m_drmOutputs << output;
|
||||
m_outputs << output;
|
||||
addedOutputs << output;
|
||||
Q_EMIT outputAdded(output);
|
||||
}
|
||||
pipeline->setLayers(m_platform->renderBackend()->createPrimaryLayer(pipeline), m_platform->renderBackend()->createCursorLayer(pipeline));
|
||||
pipeline->setActive(!conn->isNonDesktop());
|
||||
pipeline->applyPendingChanges();
|
||||
}
|
||||
for (const auto &connector : qAsConst(removedConnectors)) {
|
||||
if (auto output = findOutput(connector->id())) {
|
||||
|
|
|
@ -283,11 +283,12 @@ Output::RgbRange DrmConnector::rgbRange() const
|
|||
|
||||
bool DrmConnector::updateProperties()
|
||||
{
|
||||
if (!DrmObject::updateProperties()) {
|
||||
if (auto connector = drmModeGetConnector(gpu()->fd(), id())) {
|
||||
m_conn.reset(connector);
|
||||
} else if (!m_conn) {
|
||||
return false;
|
||||
}
|
||||
m_conn.reset(drmModeGetConnector(gpu()->fd(), id()));
|
||||
if (!m_conn) {
|
||||
if (!DrmObject::updateProperties()) {
|
||||
return false;
|
||||
}
|
||||
if (const auto &dpms = getProp(PropertyIndex::Dpms)) {
|
||||
|
@ -337,7 +338,7 @@ bool DrmConnector::updateProperties()
|
|||
for (int i = 0; equal && i < m_conn->count_modes; i++) {
|
||||
equal &= checkIfEqual(m_driverModes[i]->nativeMode(), &m_conn->modes[i]);
|
||||
}
|
||||
if (!equal) {
|
||||
if (!equal && (m_driverModes.empty() || m_conn->count_modes > 0)) {
|
||||
// reload modes
|
||||
m_driverModes.clear();
|
||||
for (int i = 0; i < m_conn->count_modes; i++) {
|
||||
|
|
Loading…
Reference in a new issue