platforms/drm: improve VT switching behavior

Instead of setting pipelines one by one, use DrmGpu::updateOutputs to
set all the outputs on a GPU with a single atomic commit. This makes
the switch both faster, more reliable and in case the other drm master
changes the output configuration, prevents blanking.
This commit is contained in:
Xaver Hugl 2021-09-13 16:56:06 +02:00
parent 2bd02f660b
commit b8d69a326c
2 changed files with 27 additions and 49 deletions

View file

@ -147,24 +147,8 @@ void DrmBackend::reactivate()
m_active = true;
for (const auto &output : qAsConst(m_outputs)) {
if (auto drmOutput = qobject_cast<DrmOutput *>(output)) {
drmOutput->pipeline()->updateProperties();
if (drmOutput->isEnabled()) {
if (drmOutput->gpu()->atomicModeSetting() && !drmOutput->pipeline()->isConnected()) {
drmOutput->pipeline()->setActive(false);
}
drmOutput->showCursor();
} else {
drmOutput->pipeline()->setActive(false);
}
}
output->renderLoop()->uninhibit();
}
for (const auto &output : qAsConst(m_outputs)) {
if (auto drmOutput = qobject_cast<DrmOutput *>(output)) {
drmOutput->pipeline()->setActive(output->isEnabled());
}
}
if (Compositor *compositor = Compositor::self()) {
compositor->addRepaintFull();
@ -183,9 +167,7 @@ void DrmBackend::deactivate()
}
for (const auto &output : qAsConst(m_outputs)) {
if (output->isEnabled()) {
output->renderLoop()->inhibit();
}
output->renderLoop()->inhibit();
}
m_active = false;

View file

@ -200,13 +200,11 @@ bool DrmGpu::updateOutputs()
}
// find unused and connected connectors
bool hasUnusedConnectors = false;
QVector<DrmConnector *> connectedConnectors;
for (const auto &conn : qAsConst(m_connectors)) {
auto output = findOutput(conn->id());
if (conn->isConnected() && !conn->isNonDesktop()) {
connectedConnectors << conn;
hasUnusedConnectors |= output == nullptr;
if (output) {
output->updateModes();
}
@ -224,37 +222,35 @@ bool DrmGpu::updateOutputs()
plane->updateProperties();
}
if (hasUnusedConnectors) {
// delete current pipelines of active outputs
for (const auto &output : qAsConst(m_drmOutputs)) {
m_pipelines.removeOne(output->pipeline());
delete output->pipeline();
output->setPipeline(nullptr);
}
// delete current pipelines of active outputs
for (const auto &output : qAsConst(m_drmOutputs)) {
m_pipelines.removeOne(output->pipeline());
delete output->pipeline();
output->setPipeline(nullptr);
}
if (m_atomicModeSetting) {
// sort outputs by being already connected (to any CRTC) so that already working outputs get preferred
std::sort(connectedConnectors.begin(), connectedConnectors.end(), [](auto c1, auto c2){
return c1->getProp(DrmConnector::PropertyIndex::CrtcId)->current() > c2->getProp(DrmConnector::PropertyIndex::CrtcId)->current();
});
}
const auto config = findWorkingCombination({}, connectedConnectors, m_crtcs, m_planes);
m_pipelines << config;
if (m_atomicModeSetting) {
// sort outputs by being already connected (to any CRTC) so that already working outputs get preferred
std::sort(connectedConnectors.begin(), connectedConnectors.end(), [](auto c1, auto c2){
return c1->getProp(DrmConnector::PropertyIndex::CrtcId)->current() > c2->getProp(DrmConnector::PropertyIndex::CrtcId)->current();
});
}
const auto config = findWorkingCombination({}, connectedConnectors, m_crtcs, m_planes);
m_pipelines << config;
for (const auto &pipeline : config) {
auto output = pipeline->output();
if (m_outputs.contains(output)) {
// try setting hardware rotation
output->updateTransform(output->transform());
} else {
qCDebug(KWIN_DRM).nospace() << "New output on GPU " << m_devNode << ": " << pipeline->connector()->modelName();
if (!output->initCursor(m_cursorSize)) {
m_backend->setSoftwareCursorForced(true);
}
m_outputs << output;
m_drmOutputs << output;
Q_EMIT outputAdded(output);
for (const auto &pipeline : config) {
auto output = pipeline->output();
if (m_outputs.contains(output)) {
// try setting hardware rotation
output->updateTransform(output->transform());
} else {
qCDebug(KWIN_DRM).nospace() << "New output on GPU " << m_devNode << ": " << pipeline->connector()->modelName();
if (!output->initCursor(m_cursorSize)) {
m_backend->setSoftwareCursorForced(true);
}
m_outputs << output;
m_drmOutputs << output;
Q_EMIT outputAdded(output);
}
}