Commit a71146c9 authored by Xaver Hugl's avatar Xaver Hugl
Browse files

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
parent 4ced4078
Pipeline #200276 passed with stage
in 11 minutes and 53 seconds
......@@ -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++) {
......
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