[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/D8602icc-effect-5.14.5
parent
b2d8bbec81
commit
26cdfd317f
|
@ -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;
|
||||
|
|
|
@ -91,6 +91,7 @@ public:
|
|||
}
|
||||
void setNext(DrmBuffer *b);
|
||||
void setTransformation(Transformations t);
|
||||
Transformations transformation();
|
||||
|
||||
bool atomicPopulate(drmModeAtomicReq *req);
|
||||
void flipBuffer();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
#include "drm_pointer.h"
|
||||
#include "drm_object.h"
|
||||
#include "drm_object_plane.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QPoint>
|
||||
|
@ -147,7 +148,6 @@ private:
|
|||
qreal m_scale = 1;
|
||||
bool m_lastGbm = false;
|
||||
drmModeModeInfo m_mode;
|
||||
drmModeModeInfo m_previousMode;
|
||||
Edid m_edid;
|
||||
QPointer<KWayland::Server::OutputInterface> m_waylandOutput;
|
||||
QPointer<KWayland::Server::OutputDeviceInterface> 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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue