diff --git a/plugins/platforms/drm/drm_object_plane.cpp b/plugins/platforms/drm/drm_object_plane.cpp
index cd45f679b3..05ec849d30 100644
--- a/plugins/platforms/drm/drm_object_plane.cpp
+++ b/plugins/platforms/drm/drm_object_plane.cpp
@@ -125,6 +125,11 @@ void DrmPlane::setTransformation(Transformations t)
setValue(int(PropertyIndex::Rotation), int(t));
}
+DrmPlane::Transformations DrmPlane::transformation()
+{
+ return Transformations(int(value(int(PropertyIndex::Rotation))));
+}
+
bool DrmPlane::atomicPopulate(drmModeAtomicReq *req)
{
bool ret = true;
diff --git a/plugins/platforms/drm/drm_object_plane.h b/plugins/platforms/drm/drm_object_plane.h
index e8f404dafa..46e468b6f0 100644
--- a/plugins/platforms/drm/drm_object_plane.h
+++ b/plugins/platforms/drm/drm_object_plane.h
@@ -91,6 +91,7 @@ public:
}
void setNext(DrmBuffer *b);
void setTransformation(Transformations t);
+ Transformations transformation();
bool atomicPopulate(drmModeAtomicReq *req);
void flipBuffer();
diff --git a/plugins/platforms/drm/drm_output.cpp b/plugins/platforms/drm/drm_output.cpp
index 59f9415641..8231baf105 100644
--- a/plugins/platforms/drm/drm_output.cpp
+++ b/plugins/platforms/drm/drm_output.cpp
@@ -804,7 +804,6 @@ void DrmOutput::updateMode(int modeIndex)
// nothing to do
return;
}
- m_previousMode = m_mode;
m_mode = connector->modes[modeIndex];
m_modesetRequested = true;
emit modeChanged();
@@ -909,13 +908,37 @@ bool DrmOutput::presentAtomically(DrmBuffer *buffer)
//TODO: When we use planes for layered rendering, fallback to renderer instead. Also for direct scanout?
//TODO: Probably should undo setNext and reset the flip list
qCDebug(KWIN_DRM) << "Atomic test commit failed. Aborting present.";
+ // go back to previous state
+ if (m_lastWorkingState.valid) {
+ m_mode = m_lastWorkingState.mode;
+ m_orientation = m_lastWorkingState.orientation;
+ setGlobalPos(m_lastWorkingState.globalPos);
+ if (m_primaryPlane) {
+ m_primaryPlane->setTransformation(m_lastWorkingState.planeTransformations);
+ }
+ m_modesetRequested = true;
+ // TODO: forward to OutputInterface and OutputDeviceInterface
+ emit modeChanged();
+ emit screens()->changed();
+ }
return false;
}
+ const bool wasModeset = m_modesetRequested;
if (!doAtomicCommit(AtomicCommitMode::Real)) {
qCDebug(KWIN_DRM) << "Atomic commit failed. This should have never happened! Aborting present.";
//TODO: Probably should undo setNext and reset the flip list
return false;
}
+ if (wasModeset) {
+ // store current mode set as new good state
+ m_lastWorkingState.mode = m_mode;
+ m_lastWorkingState.orientation = m_orientation;
+ m_lastWorkingState.globalPos = m_globalPos;
+ if (m_primaryPlane) {
+ m_lastWorkingState.planeTransformations = m_primaryPlane->transformation();
+ }
+ m_lastWorkingState.valid = true;
+ }
m_pageFlipPending = true;
return true;
}
diff --git a/plugins/platforms/drm/drm_output.h b/plugins/platforms/drm/drm_output.h
index 8767116093..856b1f150b 100644
--- a/plugins/platforms/drm/drm_output.h
+++ b/plugins/platforms/drm/drm_output.h
@@ -22,6 +22,7 @@ along with this program. If not, see .
#include "drm_pointer.h"
#include "drm_object.h"
+#include "drm_object_plane.h"
#include
#include
@@ -147,7 +148,6 @@ private:
qreal m_scale = 1;
bool m_lastGbm = false;
drmModeModeInfo m_mode;
- drmModeModeInfo m_previousMode;
Edid m_edid;
QPointer m_waylandOutput;
QPointer m_waylandOutputDevice;
@@ -166,6 +166,14 @@ private:
bool m_modesetRequested = true;
QSize m_physicalSize;
Qt::ScreenOrientation m_orientation = Qt::PrimaryOrientation;
+
+ struct {
+ Qt::ScreenOrientation orientation;
+ drmModeModeInfo mode;
+ DrmPlane::Transformations planeTransformations;
+ QPoint globalPos;
+ bool valid = false;
+ } m_lastWorkingState;
};
}