From dfea5798f10a051fda8bb739f145026378f877cf Mon Sep 17 00:00:00 2001 From: Roman Gilg Date: Thu, 2 Jan 2020 14:55:02 +0000 Subject: [PATCH] [platforms/drm] Add hardware transformation API Summary: Planes might be able to do transformations without compositing required. When changing the current transform try this with the primary plane. If this fails fall back to no transformation at all through hardware and communicate the fact and other information through some getters. Also adds an environment variable to never do hardware transformations. Test Plan: Compiles. Reviewers: #kwin Subscribers: zzag, kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D25906 --- plugins/platforms/drm/drm_output.cpp | 79 +++++++++++++++++++--------- plugins/platforms/drm/drm_output.h | 15 ++++++ 2 files changed, 69 insertions(+), 25 deletions(-) diff --git a/plugins/platforms/drm/drm_output.cpp b/plugins/platforms/drm/drm_output.cpp index 15a423b8f0..32893bda05 100644 --- a/plugins/platforms/drm/drm_output.cpp +++ b/plugins/platforms/drm/drm_output.cpp @@ -650,35 +650,64 @@ bool DrmOutput::dpmsLegacyApply() return true; } +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(); + } +} + +bool DrmOutput::hardwareTransforms() const +{ + if (!m_primaryPlane) { + return false; + } + return m_primaryPlane->transformation() == outputToPlaneTransform(transform()); +} + +int DrmOutput::rotation() const +{ + return transformToRotation(transform()); +} + void DrmOutput::updateTransform(Transform transform) { - DrmPlane::Transformation planeTransform; + const auto planeTransform = outputToPlaneTransform(transform); - // TODO: Do we want to support reflections (flips)? + 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; - 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(); - } - - if (m_primaryPlane) { - m_primaryPlane->setTransformation(planeTransform); + 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; diff --git a/plugins/platforms/drm/drm_output.h b/plugins/platforms/drm/drm_output.h index b962c49b10..878a9b1643 100644 --- a/plugins/platforms/drm/drm_output.h +++ b/plugins/platforms/drm/drm_output.h @@ -83,6 +83,21 @@ public: 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