backends/drm: fix properties not being applied when a modeset is not needed

When testing whether or not a modeset is needed, all that gets tested is
whether or not the kernel would allow the commit to happen without the ALLOW_MODESET
flag. If there's properties that are only changed in DrmPipeline::prepareAtomicModeset,
we need to apply those in the next commit, regardless of whether or not
the ALLOW_MODESET flag is necessary.

BUG: 476060
master
Xaver Hugl 11 months ago
parent 457deeb27d
commit ff2bc0798f

@ -80,12 +80,9 @@ DrmPipeline::Error DrmPipeline::present()
if (gpu()->atomicModeSetting()) {
// test the full state, to take pending commits into account
auto fullState = std::make_unique<DrmAtomicCommit>(QList<DrmPipeline *>{this});
if (Error err = prepareAtomicPresentation(fullState.get()); err != Error::None) {
if (Error err = prepareAtomicCommit(fullState.get(), CommitMode::Test); err != Error::None) {
return err;
}
if (m_pending.crtc->cursorPlane()) {
prepareAtomicCursor(fullState.get());
}
if (!fullState->test()) {
return errnoToError();
}
@ -94,6 +91,10 @@ DrmPipeline::Error DrmPipeline::present()
if (Error err = prepareAtomicPresentation(primaryPlaneUpdate.get()); err != Error::None) {
return err;
}
if (m_pending.needsModesetProperties && !prepareAtomicModeset(primaryPlaneUpdate.get())) {
return Error::InvalidArguments;
}
atomicCommitSuccessful();
m_commitThread->addCommit(std::move(primaryPlaneUpdate));
return Error::None;
} else {
@ -135,20 +136,8 @@ DrmPipeline::Error DrmPipeline::commitPipelinesAtomic(const QList<DrmPipeline *>
}
}
for (const auto &pipeline : pipelines) {
if (pipeline->activePending()) {
if (pipeline->prepareAtomicPresentation(commit.get()) != Error::None) {
return Error::InvalidArguments;
}
if (pipeline->m_pending.crtc->cursorPlane()) {
pipeline->prepareAtomicCursor(commit.get());
}
if (mode == CommitMode::TestAllowModeset || mode == CommitMode::CommitModeset) {
if (!pipeline->prepareAtomicModeset(commit.get())) {
return Error::InvalidArguments;
}
}
} else {
pipeline->prepareAtomicDisable(commit.get());
if (Error err = pipeline->prepareAtomicCommit(commit.get(), mode); err != Error::None) {
return err;
}
}
for (const auto &unused : unusedObjects) {
@ -160,9 +149,13 @@ DrmPipeline::Error DrmPipeline::commitPipelinesAtomic(const QList<DrmPipeline *>
qCDebug(KWIN_DRM) << "Atomic modeset test failed!" << strerror(errno);
return errnoToError();
}
const bool withoutModeset = commit->test();
const bool withoutModeset = std::all_of(pipelines.begin(), pipelines.end(), [](DrmPipeline *pipeline) {
auto commit = std::make_unique<DrmAtomicCommit>(QVector<DrmPipeline *>{pipeline});
return pipeline->prepareAtomicCommit(commit.get(), CommitMode::TestAllowModeset) == Error::None && commit->test();
});
for (const auto &pipeline : pipelines) {
pipeline->m_pending.needsModeset = !withoutModeset;
pipeline->m_pending.needsModesetProperties = true;
}
return Error::None;
}
@ -191,6 +184,26 @@ DrmPipeline::Error DrmPipeline::commitPipelinesAtomic(const QList<DrmPipeline *>
}
}
DrmPipeline::Error DrmPipeline::prepareAtomicCommit(DrmAtomicCommit *commit, CommitMode mode)
{
if (activePending()) {
if (Error err = prepareAtomicPresentation(commit); err != Error::None) {
return err;
}
if (m_pending.crtc->cursorPlane()) {
prepareAtomicCursor(commit);
}
if (mode == CommitMode::TestAllowModeset || mode == CommitMode::CommitModeset || m_pending.needsModesetProperties) {
if (!prepareAtomicModeset(commit)) {
return Error::InvalidArguments;
}
}
} else {
prepareAtomicDisable(commit);
}
return Error::None;
}
static QRect centerBuffer(const QSize &bufferSize, const QSize &modeSize)
{
const double widthScale = bufferSize.width() / double(modeSize.width());
@ -365,6 +378,7 @@ DrmPipeline::Error DrmPipeline::errnoToError()
void DrmPipeline::atomicCommitSuccessful()
{
m_pending.needsModeset = false;
m_pending.needsModesetProperties = false;
m_current = m_pending;
}

@ -157,6 +157,7 @@ private:
// atomic modesetting only
void atomicCommitSuccessful();
Error prepareAtomicCommit(DrmAtomicCommit *commit, CommitMode mode);
bool prepareAtomicModeset(DrmAtomicCommit *commit);
Error prepareAtomicPresentation(DrmAtomicCommit *commit);
void prepareAtomicCursor(DrmAtomicCommit *commit);
@ -176,6 +177,7 @@ private:
bool active = true; // whether or not the pipeline should be currently used
bool enabled = true; // whether or not the pipeline needs a crtc
bool needsModeset = false;
bool needsModesetProperties = false;
std::shared_ptr<DrmConnectorMode> mode;
uint32_t overscan = 0;
Output::RgbRange rgbRange = Output::RgbRange::Automatic;

Loading…
Cancel
Save