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:
parent
2bd02f660b
commit
b8d69a326c
2 changed files with 27 additions and 49 deletions
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue