Changeset View
Changeset View
Standalone View
Standalone View
plugins/platforms/drm/drm_output.cpp
Show First 20 Lines • Show All 122 Lines • ▼ Show 20 Line(s) | 117 | { | |||
---|---|---|---|---|---|
123 | if (m_hasNewCursor) { | 123 | if (m_hasNewCursor) { | ||
124 | m_cursorIndex = (m_cursorIndex + 1) % 2; | 124 | m_cursorIndex = (m_cursorIndex + 1) % 2; | ||
125 | m_hasNewCursor = false; | 125 | m_hasNewCursor = false; | ||
126 | } | 126 | } | ||
127 | 127 | | |||
128 | return ret; | 128 | return ret; | ||
129 | } | 129 | } | ||
130 | 130 | | |||
131 | // TODO: Respect OR combinations of values | 131 | // TODO: Do we need to handle the flipped cases differently? | ||
132 | int orientationToRotation(Qt::ScreenOrientations orientation) | 132 | int transformToRotation(DrmOutput::Transform transform) | ||
133 | { | 133 | { | ||
134 | switch (orientation) { | 134 | switch (transform) { | ||
135 | case Qt::PrimaryOrientation: | 135 | case DrmOutput::Transform::Normal: | ||
136 | case Qt::LandscapeOrientation: | 136 | case DrmOutput::Transform::Flipped: | ||
137 | return 0; | 137 | return 0; | ||
138 | case Qt::InvertedPortraitOrientation: | 138 | case DrmOutput::Transform::Rotated90: | ||
139 | case DrmOutput::Transform::Flipped90: | ||||
139 | return 90; | 140 | return 90; | ||
140 | case Qt::InvertedLandscapeOrientation: | 141 | case DrmOutput::Transform::Rotated180: | ||
142 | case DrmOutput::Transform::Flipped180: | ||||
141 | return 180; | 143 | return 180; | ||
142 | case Qt::PortraitOrientation: | 144 | case DrmOutput::Transform::Rotated270: | ||
145 | case DrmOutput::Transform::Flipped270: | ||||
143 | return 270; | 146 | return 270; | ||
144 | } | 147 | } | ||
145 | Q_UNREACHABLE(); | 148 | Q_UNREACHABLE(); | ||
146 | return 0; | 149 | return 0; | ||
147 | } | 150 | } | ||
148 | 151 | | |||
149 | QMatrix4x4 DrmOutput::matrixDisplay(const QSize &s) const | 152 | QMatrix4x4 DrmOutput::matrixDisplay(const QSize &s) const | ||
150 | { | 153 | { | ||
151 | QMatrix4x4 matrix; | 154 | QMatrix4x4 matrix; | ||
152 | const int angle = orientationToRotation(orientation()); | 155 | const int angle = transformToRotation(transform()); | ||
153 | if (angle) { | 156 | if (angle) { | ||
154 | const QSize center = s / 2; | 157 | const QSize center = s / 2; | ||
155 | 158 | | |||
156 | matrix.translate(center.width(), center.height()); | 159 | matrix.translate(center.width(), center.height()); | ||
157 | matrix.rotate(angle, 0, 0, 1); | 160 | matrix.rotate(angle, 0, 0, 1); | ||
158 | matrix.translate(-center.width(), -center.height()); | 161 | matrix.translate(-center.width(), -center.height()); | ||
159 | } | 162 | } | ||
160 | matrix.scale(scale()); | 163 | matrix.scale(scale()); | ||
Show All 18 Lines | |||||
179 | } | 182 | } | ||
180 | 183 | | |||
181 | void DrmOutput::moveCursor(const QPoint &globalPos) | 184 | void DrmOutput::moveCursor(const QPoint &globalPos) | ||
182 | { | 185 | { | ||
183 | const QMatrix4x4 hotspotMatrix = matrixDisplay(m_backend->softwareCursor().size()); | 186 | const QMatrix4x4 hotspotMatrix = matrixDisplay(m_backend->softwareCursor().size()); | ||
184 | 187 | | |||
185 | QPoint p = globalPos - AbstractWaylandOutput::globalPos(); | 188 | QPoint p = globalPos - AbstractWaylandOutput::globalPos(); | ||
186 | 189 | | |||
187 | // TODO: Respect OR combinations of values | 190 | // TODO: Do we need to handle the flipped cases differently? | ||
188 | switch (orientation()) { | 191 | switch (transform()) { | ||
189 | case Qt::PrimaryOrientation: | 192 | case Transform::Normal: | ||
190 | case Qt::LandscapeOrientation: | 193 | case Transform::Flipped: | ||
191 | break; | 194 | break; | ||
192 | case Qt::PortraitOrientation: | 195 | case Transform::Rotated90: | ||
196 | case Transform::Flipped90: | ||||
193 | p = QPoint(p.y(), pixelSize().height() - p.x()); | 197 | p = QPoint(p.y(), pixelSize().height() - p.x()); | ||
194 | break; | 198 | break; | ||
195 | case Qt::InvertedPortraitOrientation: | 199 | case Transform::Rotated270: | ||
200 | case Transform::Flipped270: | ||||
196 | p = QPoint(pixelSize().width() - p.y(), p.x()); | 201 | p = QPoint(pixelSize().width() - p.y(), p.x()); | ||
197 | break; | 202 | break; | ||
198 | case Qt::InvertedLandscapeOrientation: | 203 | case Transform::Rotated180: | ||
204 | case Transform::Flipped180: | ||||
199 | p = QPoint(pixelSize().width() - p.x(), pixelSize().height() - p.y()); | 205 | p = QPoint(pixelSize().width() - p.x(), pixelSize().height() - p.y()); | ||
200 | break; | 206 | break; | ||
207 | default: | ||||
208 | Q_UNREACHABLE(); | ||||
201 | } | 209 | } | ||
202 | p *= scale(); | 210 | p *= scale(); | ||
203 | p -= hotspotMatrix.map(m_backend->softwareCursorHotspot()); | 211 | p -= hotspotMatrix.map(m_backend->softwareCursorHotspot()); | ||
204 | drmModeMoveCursor(m_backend->fd(), m_crtc->id(), p.x(), p.y()); | 212 | drmModeMoveCursor(m_backend->fd(), m_crtc->id(), p.x(), p.y()); | ||
205 | } | 213 | } | ||
206 | 214 | | |||
207 | static QHash<int, QByteArray> s_connectorNames = { | 215 | static QHash<int, QByteArray> s_connectorNames = { | ||
208 | {DRM_MODE_CONNECTOR_Unknown, QByteArrayLiteral("Unknown")}, | 216 | {DRM_MODE_CONNECTOR_Unknown, QByteArrayLiteral("Unknown")}, | ||
▲ Show 20 Lines • Show All 427 Lines • ▼ Show 20 Line(s) | 643 | if (m_dpmsModePending == DpmsMode::On) { | |||
636 | dpmsFinishOn(); | 644 | dpmsFinishOn(); | ||
637 | } else { | 645 | } else { | ||
638 | dpmsFinishOff(); | 646 | dpmsFinishOff(); | ||
639 | } | 647 | } | ||
640 | m_dpmsMode = m_dpmsModePending; | 648 | m_dpmsMode = m_dpmsModePending; | ||
641 | return true; | 649 | return true; | ||
642 | } | 650 | } | ||
643 | 651 | | |||
644 | // TODO: Rotation is currently broken in the DRM backend for 90° and 270°. Disable all rotation for | 652 | void DrmOutput::updateTransform(Transform transform) | ||
645 | // now to not break user setups until it is possible again. | | |||
646 | #if 1 | | |||
647 | void DrmOutput::transform(KWayland::Server::OutputDeviceInterface::Transform transform) | | |||
648 | { | 653 | { | ||
649 | using KWayland::Server::OutputDeviceInterface; | | |||
650 | | ||||
651 | switch (transform) { | 654 | switch (transform) { | ||
652 | case OutputDeviceInterface::Transform::Normal: | 655 | case Transform::Normal: | ||
653 | if (m_primaryPlane) { | 656 | if (m_primaryPlane) { | ||
654 | m_primaryPlane->setTransformation(DrmPlane::Transformation::Rotate0); | 657 | m_primaryPlane->setTransformation(DrmPlane::Transformation::Rotate0); | ||
655 | } | 658 | } | ||
656 | break; | 659 | break; | ||
657 | case OutputDeviceInterface::Transform::Rotated90: | 660 | case Transform::Rotated90: | ||
658 | if (m_primaryPlane) { | 661 | if (m_primaryPlane) { | ||
659 | m_primaryPlane->setTransformation(DrmPlane::Transformation::Rotate90); | 662 | m_primaryPlane->setTransformation(DrmPlane::Transformation::Rotate90); | ||
660 | } | 663 | } | ||
661 | break; | 664 | break; | ||
662 | case OutputDeviceInterface::Transform::Rotated180: | 665 | case Transform::Rotated180: | ||
663 | if (m_primaryPlane) { | 666 | if (m_primaryPlane) { | ||
664 | m_primaryPlane->setTransformation(DrmPlane::Transformation::Rotate180); | 667 | m_primaryPlane->setTransformation(DrmPlane::Transformation::Rotate180); | ||
665 | } | 668 | } | ||
666 | break; | 669 | break; | ||
667 | case OutputDeviceInterface::Transform::Rotated270: | 670 | case Transform::Rotated270: | ||
668 | if (m_primaryPlane) { | 671 | if (m_primaryPlane) { | ||
669 | m_primaryPlane->setTransformation(DrmPlane::Transformation::Rotate270); | 672 | m_primaryPlane->setTransformation(DrmPlane::Transformation::Rotate270); | ||
670 | } | 673 | } | ||
671 | break; | 674 | break; | ||
672 | case OutputDeviceInterface::Transform::Flipped: | 675 | case Transform::Flipped: | ||
673 | // TODO: what is this exactly? | 676 | // TODO: what is this exactly? | ||
674 | break; | 677 | break; | ||
675 | case OutputDeviceInterface::Transform::Flipped90: | 678 | case Transform::Flipped90: | ||
676 | // TODO: what is this exactly? | 679 | // TODO: what is this exactly? | ||
677 | break; | 680 | break; | ||
678 | case OutputDeviceInterface::Transform::Flipped180: | 681 | case Transform::Flipped180: | ||
679 | // TODO: what is this exactly? | 682 | // TODO: what is this exactly? | ||
680 | break; | 683 | break; | ||
681 | case OutputDeviceInterface::Transform::Flipped270: | 684 | case Transform::Flipped270: | ||
682 | // TODO: what is this exactly? | 685 | // TODO: what is this exactly? | ||
683 | break; | 686 | break; | ||
684 | } | 687 | } | ||
685 | m_modesetRequested = true; | 688 | m_modesetRequested = true; | ||
686 | // the cursor might need to get rotated | 689 | // the cursor might need to get rotated | ||
687 | updateCursor(); | 690 | updateCursor(); | ||
688 | showCursor(); | 691 | showCursor(); | ||
689 | } | 692 | } | ||
690 | #else | | |||
691 | void DrmOutput::transform(KWayland::Server::OutputDeviceInterface::Transform transform) | | |||
692 | { | | |||
693 | Q_UNUSED(transform) | | |||
694 | } | | |||
695 | #endif | | |||
696 | 693 | | |||
697 | void DrmOutput::updateMode(int modeIndex) | 694 | void DrmOutput::updateMode(int modeIndex) | ||
698 | { | 695 | { | ||
699 | // get all modes on the connector | 696 | // get all modes on the connector | ||
700 | DrmScopedPointer<drmModeConnector> connector(drmModeGetConnector(m_backend->fd(), m_conn->id())); | 697 | DrmScopedPointer<drmModeConnector> connector(drmModeGetConnector(m_backend->fd(), m_conn->id())); | ||
701 | if (connector->count_modes <= modeIndex) { | 698 | if (connector->count_modes <= modeIndex) { | ||
702 | // TODO: error? | 699 | // TODO: error? | ||
703 | return; | 700 | return; | ||
▲ Show 20 Lines • Show All 132 Lines • ▼ Show 20 Line(s) | 829 | #endif | |||
836 | 833 | | |||
837 | if (!doAtomicCommit(AtomicCommitMode::Test)) { | 834 | if (!doAtomicCommit(AtomicCommitMode::Test)) { | ||
838 | //TODO: When we use planes for layered rendering, fallback to renderer instead. Also for direct scanout? | 835 | //TODO: When we use planes for layered rendering, fallback to renderer instead. Also for direct scanout? | ||
839 | //TODO: Probably should undo setNext and reset the flip list | 836 | //TODO: Probably should undo setNext and reset the flip list | ||
840 | qCDebug(KWIN_DRM) << "Atomic test commit failed. Aborting present."; | 837 | qCDebug(KWIN_DRM) << "Atomic test commit failed. Aborting present."; | ||
841 | // go back to previous state | 838 | // go back to previous state | ||
842 | if (m_lastWorkingState.valid) { | 839 | if (m_lastWorkingState.valid) { | ||
843 | m_mode = m_lastWorkingState.mode; | 840 | m_mode = m_lastWorkingState.mode; | ||
844 | setOrientation(m_lastWorkingState.orientation); | 841 | setTransform(m_lastWorkingState.transform); | ||
845 | setGlobalPos(m_lastWorkingState.globalPos); | 842 | setGlobalPos(m_lastWorkingState.globalPos); | ||
846 | if (m_primaryPlane) { | 843 | if (m_primaryPlane) { | ||
847 | m_primaryPlane->setTransformation(m_lastWorkingState.planeTransformations); | 844 | m_primaryPlane->setTransformation(m_lastWorkingState.planeTransformations); | ||
848 | } | 845 | } | ||
849 | m_modesetRequested = true; | 846 | m_modesetRequested = true; | ||
850 | // the cursor might need to get rotated | 847 | // the cursor might need to get rotated | ||
851 | updateCursor(); | 848 | updateCursor(); | ||
852 | showCursor(); | 849 | showCursor(); | ||
853 | // TODO: forward to OutputInterface and OutputDeviceInterface | 850 | // TODO: forward to OutputInterface and OutputDeviceInterface | ||
854 | setWaylandMode(); | 851 | setWaylandMode(); | ||
855 | emit screens()->changed(); | 852 | emit screens()->changed(); | ||
856 | } | 853 | } | ||
857 | return false; | 854 | return false; | ||
858 | } | 855 | } | ||
859 | const bool wasModeset = m_modesetRequested; | 856 | const bool wasModeset = m_modesetRequested; | ||
860 | if (!doAtomicCommit(AtomicCommitMode::Real)) { | 857 | if (!doAtomicCommit(AtomicCommitMode::Real)) { | ||
861 | qCDebug(KWIN_DRM) << "Atomic commit failed. This should have never happened! Aborting present."; | 858 | qCDebug(KWIN_DRM) << "Atomic commit failed. This should have never happened! Aborting present."; | ||
862 | //TODO: Probably should undo setNext and reset the flip list | 859 | //TODO: Probably should undo setNext and reset the flip list | ||
863 | return false; | 860 | return false; | ||
864 | } | 861 | } | ||
865 | if (wasModeset) { | 862 | if (wasModeset) { | ||
866 | // store current mode set as new good state | 863 | // store current mode set as new good state | ||
867 | m_lastWorkingState.mode = m_mode; | 864 | m_lastWorkingState.mode = m_mode; | ||
868 | m_lastWorkingState.orientation = orientation(); | 865 | m_lastWorkingState.transform = transform(); | ||
869 | m_lastWorkingState.globalPos = globalPos(); | 866 | m_lastWorkingState.globalPos = globalPos(); | ||
870 | if (m_primaryPlane) { | 867 | if (m_primaryPlane) { | ||
871 | m_lastWorkingState.planeTransformations = m_primaryPlane->transformation(); | 868 | m_lastWorkingState.planeTransformations = m_primaryPlane->transformation(); | ||
872 | } | 869 | } | ||
873 | m_lastWorkingState.valid = true; | 870 | m_lastWorkingState.valid = true; | ||
874 | } | 871 | } | ||
875 | m_pageFlipPending = true; | 872 | m_pageFlipPending = true; | ||
876 | return true; | 873 | return true; | ||
▲ Show 20 Lines • Show All 185 Lines • ▼ Show 20 Line(s) | |||||
1062 | 1059 | | |||
1063 | void DrmOutput::automaticRotation() | 1060 | void DrmOutput::automaticRotation() | ||
1064 | { | 1061 | { | ||
1065 | if (!m_primaryPlane) { | 1062 | if (!m_primaryPlane) { | ||
1066 | return; | 1063 | return; | ||
1067 | } | 1064 | } | ||
1068 | const auto supportedTransformations = m_primaryPlane->supportedTransformations(); | 1065 | const auto supportedTransformations = m_primaryPlane->supportedTransformations(); | ||
1069 | const auto requestedTransformation = screens()->orientationSensor()->orientation(); | 1066 | const auto requestedTransformation = screens()->orientationSensor()->orientation(); | ||
1070 | using KWayland::Server::OutputDeviceInterface; | 1067 | | ||
1071 | OutputDeviceInterface::Transform newTransformation = OutputDeviceInterface::Transform::Normal; | 1068 | Transform newTransformation = Transform::Normal; | ||
1072 | switch (requestedTransformation) { | 1069 | switch (requestedTransformation) { | ||
1073 | case OrientationSensor::Orientation::TopUp: | 1070 | case OrientationSensor::Orientation::TopUp: | ||
1074 | newTransformation = OutputDeviceInterface::Transform::Normal; | 1071 | newTransformation = Transform::Normal; | ||
1075 | break; | 1072 | break; | ||
1076 | case OrientationSensor::Orientation::TopDown: | 1073 | case OrientationSensor::Orientation::TopDown: | ||
1077 | if (!supportedTransformations.testFlag(DrmPlane::Transformation::Rotate180)) { | 1074 | if (!supportedTransformations.testFlag(DrmPlane::Transformation::Rotate180)) { | ||
1078 | return; | 1075 | return; | ||
1079 | } | 1076 | } | ||
1080 | newTransformation = OutputDeviceInterface::Transform::Rotated180; | 1077 | newTransformation = Transform::Rotated180; | ||
1081 | break; | 1078 | break; | ||
1082 | case OrientationSensor::Orientation::LeftUp: | 1079 | case OrientationSensor::Orientation::LeftUp: | ||
1083 | if (!supportedTransformations.testFlag(DrmPlane::Transformation::Rotate90)) { | 1080 | if (!supportedTransformations.testFlag(DrmPlane::Transformation::Rotate90)) { | ||
1084 | return; | 1081 | return; | ||
1085 | } | 1082 | } | ||
1086 | newTransformation = OutputDeviceInterface::Transform::Rotated90; | 1083 | newTransformation = Transform::Rotated90; | ||
1087 | break; | 1084 | break; | ||
1088 | case OrientationSensor::Orientation::RightUp: | 1085 | case OrientationSensor::Orientation::RightUp: | ||
1089 | if (!supportedTransformations.testFlag(DrmPlane::Transformation::Rotate270)) { | 1086 | if (!supportedTransformations.testFlag(DrmPlane::Transformation::Rotate270)) { | ||
1090 | return; | 1087 | return; | ||
1091 | } | 1088 | } | ||
1092 | newTransformation = OutputDeviceInterface::Transform::Rotated270; | 1089 | newTransformation = Transform::Rotated270; | ||
1093 | break; | 1090 | break; | ||
1094 | case OrientationSensor::Orientation::FaceUp: | 1091 | case OrientationSensor::Orientation::FaceUp: | ||
1095 | case OrientationSensor::Orientation::FaceDown: | 1092 | case OrientationSensor::Orientation::FaceDown: | ||
1096 | case OrientationSensor::Orientation::Undefined: | 1093 | case OrientationSensor::Orientation::Undefined: | ||
1097 | // unsupported | 1094 | // unsupported | ||
1098 | return; | 1095 | return; | ||
1099 | } | 1096 | } | ||
1100 | transform(newTransformation); | 1097 | setTransform(newTransformation); | ||
1101 | emit screens()->changed(); | 1098 | emit screens()->changed(); | ||
1102 | } | 1099 | } | ||
1103 | 1100 | | |||
1104 | int DrmOutput::gammaRampSize() const | 1101 | int DrmOutput::gammaRampSize() const | ||
1105 | { | 1102 | { | ||
1106 | return m_crtc->gammaRampSize(); | 1103 | return m_crtc->gammaRampSize(); | ||
1107 | } | 1104 | } | ||
1108 | 1105 | | |||
1109 | bool DrmOutput::setGammaRamp(const GammaRamp &gamma) | 1106 | bool DrmOutput::setGammaRamp(const GammaRamp &gamma) | ||
1110 | { | 1107 | { | ||
1111 | return m_crtc->setGammaRamp(gamma); | 1108 | return m_crtc->setGammaRamp(gamma); | ||
1112 | } | 1109 | } | ||
1113 | 1110 | | |||
1114 | } | 1111 | } |