Commit 26cdfd31 authored by Martin Flöser's avatar Martin Flöser
Browse files

[platforms/drm] Restore previous mode if an atomic test fails

Summary:
When KWin successfully presents a new mode, it stores the current state
as the last working mode. If a new modeset is requested and the atomic
test fails, all is undone and reverted to this last knowing mode.

Currently included are:
 * the mode
 * global position
 * transformation

This is only done on a modeset not when going to DPMS.

Test Plan:
Selected the not working vertical rotation and nothing bad
happened.

Reviewers: #kwin, #plasma, subdiff

Subscribers: plasma-devel, kwin

Tags: #kwin

Differential Revision: https://phabricator.kde.org/D8602
parent b2d8bbec
...@@ -125,6 +125,11 @@ void DrmPlane::setTransformation(Transformations t) ...@@ -125,6 +125,11 @@ void DrmPlane::setTransformation(Transformations t)
setValue(int(PropertyIndex::Rotation), int(t)); setValue(int(PropertyIndex::Rotation), int(t));
} }
DrmPlane::Transformations DrmPlane::transformation()
{
return Transformations(int(value(int(PropertyIndex::Rotation))));
}
bool DrmPlane::atomicPopulate(drmModeAtomicReq *req) bool DrmPlane::atomicPopulate(drmModeAtomicReq *req)
{ {
bool ret = true; bool ret = true;
......
...@@ -91,6 +91,7 @@ public: ...@@ -91,6 +91,7 @@ public:
} }
void setNext(DrmBuffer *b); void setNext(DrmBuffer *b);
void setTransformation(Transformations t); void setTransformation(Transformations t);
Transformations transformation();
bool atomicPopulate(drmModeAtomicReq *req); bool atomicPopulate(drmModeAtomicReq *req);
void flipBuffer(); void flipBuffer();
......
...@@ -804,7 +804,6 @@ void DrmOutput::updateMode(int modeIndex) ...@@ -804,7 +804,6 @@ void DrmOutput::updateMode(int modeIndex)
// nothing to do // nothing to do
return; return;
} }
m_previousMode = m_mode;
m_mode = connector->modes[modeIndex]; m_mode = connector->modes[modeIndex];
m_modesetRequested = true; m_modesetRequested = true;
emit modeChanged(); emit modeChanged();
...@@ -909,13 +908,37 @@ bool DrmOutput::presentAtomically(DrmBuffer *buffer) ...@@ -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: 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 //TODO: Probably should undo setNext and reset the flip list
qCDebug(KWIN_DRM) << "Atomic test commit failed. Aborting present."; 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; return false;
} }
const bool wasModeset = m_modesetRequested;
if (!doAtomicCommit(AtomicCommitMode::Real)) { if (!doAtomicCommit(AtomicCommitMode::Real)) {
qCDebug(KWIN_DRM) << "Atomic commit failed. This should have never happened! Aborting present."; qCDebug(KWIN_DRM) << "Atomic commit failed. This should have never happened! Aborting present.";
//TODO: Probably should undo setNext and reset the flip list //TODO: Probably should undo setNext and reset the flip list
return false; 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; m_pageFlipPending = true;
return true; return true;
} }
......
...@@ -22,6 +22,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. ...@@ -22,6 +22,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "drm_pointer.h" #include "drm_pointer.h"
#include "drm_object.h" #include "drm_object.h"
#include "drm_object_plane.h"
#include <QObject> #include <QObject>
#include <QPoint> #include <QPoint>
...@@ -147,7 +148,6 @@ private: ...@@ -147,7 +148,6 @@ private:
qreal m_scale = 1; qreal m_scale = 1;
bool m_lastGbm = false; bool m_lastGbm = false;
drmModeModeInfo m_mode; drmModeModeInfo m_mode;
drmModeModeInfo m_previousMode;
Edid m_edid; Edid m_edid;
QPointer<KWayland::Server::OutputInterface> m_waylandOutput; QPointer<KWayland::Server::OutputInterface> m_waylandOutput;
QPointer<KWayland::Server::OutputDeviceInterface> m_waylandOutputDevice; QPointer<KWayland::Server::OutputDeviceInterface> m_waylandOutputDevice;
...@@ -166,6 +166,14 @@ private: ...@@ -166,6 +166,14 @@ private:
bool m_modesetRequested = true; bool m_modesetRequested = true;
QSize m_physicalSize; QSize m_physicalSize;
Qt::ScreenOrientation m_orientation = Qt::PrimaryOrientation; Qt::ScreenOrientation m_orientation = Qt::PrimaryOrientation;
struct {
Qt::ScreenOrientation orientation;
drmModeModeInfo mode;
DrmPlane::Transformations planeTransformations;
QPoint globalPos;
bool valid = false;
} m_lastWorkingState;
}; };
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment