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 @@ -83,6 +83,21 @@ bool supportsTransformations() const; + /** + * Drm planes might be capable of realizing the current output transform without usage + * of compositing. This is a getter to query the current state of that + * + * @return true if the hardware realizes the transform without further assistance + */ + bool hardwareTransforms() const; + + /** + * The current rotation of the output + * + * @return rotation in degree + */ + int rotation() const; + private: friend class DrmBackend; friend class DrmCrtc; // TODO: For use of setModeLegacy. Remove later when we allow multiple connectors per crtc 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 @@ -650,35 +650,64 @@ return true; } -void DrmOutput::updateTransform(Transform transform) -{ - DrmPlane::Transformation planeTransform; - - // TODO: Do we want to support reflections (flips)? +DrmPlane::Transformations outputToPlaneTransform(DrmOutput::Transform transform) + { + using OutTrans = DrmOutput::Transform; + using PlaneTrans = DrmPlane::Transformation; + + // TODO: Do we want to support reflections (flips)? + + switch (transform) { + case OutTrans::Normal: + case OutTrans::Flipped: + return PlaneTrans::Rotate0; + case OutTrans::Rotated90: + case OutTrans::Flipped90: + return PlaneTrans::Rotate90; + case OutTrans::Rotated180: + case OutTrans::Flipped180: + return PlaneTrans::Rotate180; + case OutTrans::Rotated270: + case OutTrans::Flipped270: + return PlaneTrans::Rotate270; + default: + Q_UNREACHABLE(); + } +} - switch (transform) { - case Transform::Normal: - case Transform::Flipped: - planeTransform = DrmPlane::Transformation::Rotate0; - break; - case Transform::Rotated90: - case Transform::Flipped90: - planeTransform = DrmPlane::Transformation::Rotate90; - break; - case Transform::Rotated180: - case Transform::Flipped180: - planeTransform = DrmPlane::Transformation::Rotate180; - break; - case Transform::Rotated270: - case Transform::Flipped270: - planeTransform = DrmPlane::Transformation::Rotate270; - break; - default: - Q_UNREACHABLE(); +bool DrmOutput::hardwareTransforms() const +{ + if (!m_primaryPlane) { + return false; } + return m_primaryPlane->transformation() == outputToPlaneTransform(transform()); +} - if (m_primaryPlane) { - m_primaryPlane->setTransformation(planeTransform); +int DrmOutput::rotation() const +{ + return transformToRotation(transform()); +} + +void DrmOutput::updateTransform(Transform transform) +{ + const auto planeTransform = outputToPlaneTransform(transform); + + if (m_primaryPlane) { + // At the moment we have to exclude hardware transforms for vertical buffers. + // For that we need to support other buffers and graceful fallback from atomic tests. + // Reason is that standard linear buffers are not suitable. + const bool isPortrait = transform == Transform::Rotated90 + || transform == Transform::Flipped90 + || transform == Transform::Rotated270 + || transform == Transform::Flipped270; + + if (!qEnvironmentVariableIsSet("KWIN_DRM_SW_ROTATIONS_ONLY") && + (m_primaryPlane->supportedTransformations() & planeTransform) && + !isPortrait) { + m_primaryPlane->setTransformation(planeTransform); + } else { + m_primaryPlane->setTransformation(DrmPlane::Transformation::Rotate0); + } } m_modesetRequested = true;