diff --git a/plugins/platforms/drm/drm_object_plane.h b/plugins/platforms/drm/drm_object_plane.h --- a/plugins/platforms/drm/drm_object_plane.h +++ b/plugins/platforms/drm/drm_object_plane.h @@ -91,6 +91,7 @@ } void setNext(DrmBuffer *b); void setTransformation(Transformations t); + Transformations transformation(); bool atomicPopulate(drmModeAtomicReq *req); void flipBuffer(); diff --git a/plugins/platforms/drm/drm_object_plane.cpp b/plugins/platforms/drm/drm_object_plane.cpp --- a/plugins/platforms/drm/drm_object_plane.cpp +++ b/plugins/platforms/drm/drm_object_plane.cpp @@ -125,6 +125,11 @@ 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_output.h b/plugins/platforms/drm/drm_output.h --- a/plugins/platforms/drm/drm_output.h +++ b/plugins/platforms/drm/drm_output.h @@ -22,6 +22,7 @@ #include "drm_pointer.h" #include "drm_object.h" +#include "drm_object_plane.h" #include #include @@ -147,7 +148,6 @@ 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 @@ 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; }; } diff --git a/plugins/platforms/drm/drm_output.cpp b/plugins/platforms/drm/drm_output.cpp --- a/plugins/platforms/drm/drm_output.cpp +++ b/plugins/platforms/drm/drm_output.cpp @@ -804,7 +804,6 @@ // nothing to do return; } - m_previousMode = m_mode; m_mode = connector->modes[modeIndex]; m_modesetRequested = true; emit modeChanged(); @@ -909,13 +908,37 @@ //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; }