backends/drm: Notify about failed frames if there are actually pending frames

In case a modeset needs to be performed, the drm backend will test all
pipelines to ensure that new mode won't cause any bandwidth issues on
other outputs, etc.

To do that, it may delay presenting frames. If the new configuration
doesn't work, it needs to notify about failed frames.

However, the relevant code that notifies the RenderLoop about failed
atomic commits doesn't check if there's actually a pending modeset
present.

When switching between VTs, systemd can revoke master permissions from
kwin. To make things even more trickier, kwin can try to present a frame
in that short time span.
master
Vlad Zahorodnii 3 years ago
parent d92bbdb2be
commit 9f93358bc1

@ -727,12 +727,20 @@ bool DrmGpu::maybeModeset()
bool presentPendingForAll = std::all_of(pipelines.constBegin(), pipelines.constEnd(), [](const auto &pipeline) {
return pipeline->modesetPresentPending() || !pipeline->pending.active;
});
if (presentPendingForAll) {
return DrmPipeline::commitPipelines(pipelines, DrmPipeline::CommitMode::CommitModeset, unusedObjects());
} else {
if (!presentPendingForAll) {
// commit only once all pipelines are ready for presentation
return true;
}
const bool ok = DrmPipeline::commitPipelines(pipelines, DrmPipeline::CommitMode::CommitModeset, unusedObjects());
for (DrmPipeline *pipeline : qAsConst(pipelines)) {
if (pipeline->modesetPresentPending() && pipeline->output()) {
pipeline->resetModesetPresentPending();
if (!ok) {
pipeline->output()->presentFailed();
}
}
}
return ok;
}
QVector<DrmObject*> DrmGpu::unusedObjects() const

@ -126,10 +126,6 @@ bool DrmPipeline::commitPipelines(const QVector<DrmPipeline*> &pipelines, Commit
pipeline->pending.crtc->rollbackPending();
pipeline->pending.crtc->primaryPlane()->rollbackPending();
}
if (mode != CommitMode::Test && pipeline->activePending() && pipeline->output()) {
pipeline->m_modesetPresentPending = false;
pipeline->output()->presentFailed();
}
}
for (const auto &obj : unusedObjects) {
printProps(obj, PrintMode::OnlyChanged);
@ -187,7 +183,6 @@ bool DrmPipeline::commitPipelines(const QVector<DrmPipeline*> &pipelines, Commit
}
}
if (mode != CommitMode::Test) {
pipeline->m_modesetPresentPending = false;
pipeline->m_pageflipPending = true;
pipeline->m_connector->commit();
if (pipeline->pending.crtc) {
@ -225,9 +220,6 @@ bool DrmPipeline::commitPipelines(const QVector<DrmPipeline*> &pipelines, Commit
for (const auto &pipeline : pipelines) {
pipeline->revertPendingChanges();
pipeline->applyPendingChangesLegacy();
if (mode == CommitMode::CommitModeset && pipeline->output() && pipeline->activePending()) {
pipeline->output()->presentFailed();
}
}
return false;
} else {
@ -510,6 +502,11 @@ bool DrmPipeline::modesetPresentPending() const
return m_modesetPresentPending;
}
void DrmPipeline::resetModesetPresentPending()
{
m_modesetPresentPending = false;
}
DrmCrtc *DrmPipeline::currentCrtc() const
{
return m_current.crtc;

@ -80,6 +80,7 @@ public:
void pageFlipped(std::chrono::nanoseconds timestamp);
bool pageflipPending() const;
bool modesetPresentPending() const;
void resetModesetPresentPending();
void printDebugInfo() const;
QSize sourceSize() const;

Loading…
Cancel
Save