xref: /OK3568_Linux_fs/buildroot/package/qt5/qt5base/0014-linuxfb-Support-rotate.patch (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1From cc8e902f0511700b797fed870b1a7e6a61e84711 Mon Sep 17 00:00:00 2001
2From: Jeffy Chen <jeffy.chen@rock-chips.com>
3Date: Mon, 29 Apr 2019 12:11:42 +0800
4Subject: [PATCH 14/28] linuxfb: Support rotate
5
6Base on:
7https://borkedlabs.com/blog/2015/06-01-qt5-linuxfb-rotation-for-lcds/
8
9Usage:
10export QT_QPA_PLATFORM=linuxfb:rotation=90
11
12Conflicts:
13    src/plugins/platforms/linuxfb/qlinuxfbdrmscreen.cpp
14
15Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
16Signed-off-by: Ziyuan Xu <xzy.xu@rock-chips.com>
17---
18 .../platforms/linuxfb/qlinuxfbdrmscreen.cpp   | 33 +++++++++++++++++--
19 .../platforms/linuxfb/qlinuxfbdrmscreen.h     |  2 ++
20 .../platforms/linuxfb/qlinuxfbscreen.cpp      | 33 ++++++++++++++++---
21 .../platforms/linuxfb/qlinuxfbscreen.h        |  2 ++
22 4 files changed, 62 insertions(+), 8 deletions(-)
23
24diff --git a/src/plugins/platforms/linuxfb/qlinuxfbdrmscreen.cpp b/src/plugins/platforms/linuxfb/qlinuxfbdrmscreen.cpp
25index 29d146f4..0c4f6d2c 100644
26--- a/src/plugins/platforms/linuxfb/qlinuxfbdrmscreen.cpp
27+++ b/src/plugins/platforms/linuxfb/qlinuxfbdrmscreen.cpp
28@@ -49,6 +49,7 @@
29 #include <QLoggingCategory>
30 #include <QGuiApplication>
31 #include <QPainter>
32+#include <QtCore/QRegularExpression>
33 #include <QtFbSupport/private/qfbcursor_p.h>
34 #include <QtFbSupport/private/qfbwindow_p.h>
35 #include <QtKmsSupport/private/qkmsdevice_p.h>
36@@ -408,9 +409,16 @@ void QLinuxFbDevice::swapBuffers(Output *output)
37
38 QLinuxFbDrmScreen::QLinuxFbDrmScreen(const QStringList &args)
39     : m_screenConfig(nullptr),
40-      m_device(nullptr)
41+      m_device(nullptr),
42+      m_rotation(0)
43 {
44-    Q_UNUSED(args);
45+    QRegularExpression rotationRx(QLatin1String("rotation=(0|90|180|270)"));
46+
47+    for (const QString &arg : qAsConst(args)) {
48+        QRegularExpressionMatch match;
49+        if (arg.contains(rotationRx, &match))
50+            m_rotation = match.captured(1).toInt();
51+    }
52 }
53
54 QLinuxFbDrmScreen::~QLinuxFbDrmScreen()
55@@ -440,6 +448,12 @@ bool QLinuxFbDrmScreen::initialize()
56     QLinuxFbDevice::Output *output(m_device->output(0));
57
58     mGeometry = QRect(QPoint(0, 0), output->currentRes());
59+    if(m_rotation % 180) {
60+        int tmp = mGeometry.width();
61+        mGeometry.setWidth(mGeometry.height());
62+        mGeometry.setHeight(tmp);
63+    }
64+
65     mDepth = depthForDrmFormat(output->kmsOutput.drm_format);
66     mFormat = formatForDrmFormat(output->kmsOutput.drm_format);
67     mPhysicalSize = output->kmsOutput.physical_size;
68@@ -475,8 +489,21 @@ QRegion QLinuxFbDrmScreen::doRedraw()
69     // Image has alpha but no need for blending at this stage.
70     // Do not waste time with the default SourceOver.
71     pntr.setCompositionMode(QPainter::CompositionMode_Source);
72-    for (const QRect &rect : qAsConst(output->dirty[output->backFb]))
73+    for (const QRect &rect : qAsConst(output->dirty[output->backFb])) {
74+        if(m_rotation) {
75+            if(m_rotation == 180)
76+                pntr.translate(mGeometry.width()/2, mGeometry.height()/2);
77+            else
78+                pntr.translate(mGeometry.height()/2, mGeometry.width()/2);
79+
80+            pntr.rotate(m_rotation);
81+            pntr.translate(-mGeometry.width()/2, -mGeometry.height()/2);
82+        }
83+
84         pntr.drawImage(rect, mScreenImage, rect);
85+
86+        pntr.resetTransform();
87+    }
88     pntr.end();
89
90     output->dirty[output->backFb] = QRegion();
91diff --git a/src/plugins/platforms/linuxfb/qlinuxfbdrmscreen.h b/src/plugins/platforms/linuxfb/qlinuxfbdrmscreen.h
92index 50a95767..4065392d 100644
93--- a/src/plugins/platforms/linuxfb/qlinuxfbdrmscreen.h
94+++ b/src/plugins/platforms/linuxfb/qlinuxfbdrmscreen.h
95@@ -61,6 +61,8 @@ public:
96 private:
97     QKmsScreenConfig *m_screenConfig;
98     QLinuxFbDevice *m_device;
99+
100+    int m_rotation;
101 };
102
103 QT_END_NAMESPACE
104diff --git a/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp b/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp
105index cb8962d4..40381fcb 100644
106--- a/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp
107+++ b/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp
108@@ -287,7 +287,7 @@ static void blankScreen(int fd, bool on)
109 }
110
111 QLinuxFbScreen::QLinuxFbScreen(const QStringList &args)
112-    : mArgs(args), mFbFd(-1), mTtyFd(-1), mBlitter(0)
113+    : mArgs(args), mFbFd(-1), mTtyFd(-1), mBlitter(0), mRotation(0)
114 {
115     mMmap.data = 0;
116 }
117@@ -313,6 +313,7 @@ bool QLinuxFbScreen::initialize()
118     QRegularExpression mmSizeRx(QLatin1String("mmsize=(\\d+)x(\\d+)"));
119     QRegularExpression sizeRx(QLatin1String("size=(\\d+)x(\\d+)"));
120     QRegularExpression offsetRx(QLatin1String("offset=(\\d+)x(\\d+)"));
121+    QRegularExpression rotationRx(QLatin1String("rotation=(0|90|180|270)"));
122
123     QString fbDevice, ttyDevice;
124     QSize userMmSize;
125@@ -334,6 +335,8 @@ bool QLinuxFbScreen::initialize()
126             ttyDevice = match.captured(1);
127         else if (arg.contains(fbRx, &match))
128             fbDevice = match.captured(1);
129+        else if (arg.contains(rotationRx, &match))
130+            mRotation = match.captured(1).toInt();
131     }
132
133     if (fbDevice.isEmpty()) {
134@@ -372,9 +375,16 @@ bool QLinuxFbScreen::initialize()
135     mDepth = determineDepth(vinfo);
136     mBytesPerLine = finfo.line_length;
137     QRect geometry = determineGeometry(vinfo, userGeometry);
138+    QRect originalGeometry = geometry;
139+    if(mRotation % 180) {
140+        int tmp = geometry.width();
141+        geometry.setWidth(geometry.height());
142+        geometry.setHeight(tmp);
143+    }
144+
145     mGeometry = QRect(QPoint(0, 0), geometry.size());
146     mFormat = determineFormat(vinfo, mDepth);
147-    mPhysicalSize = determinePhysicalSize(vinfo, userMmSize, geometry.size());
148+    mPhysicalSize = determinePhysicalSize(vinfo, userMmSize, originalGeometry.size());
149
150     // mmap the framebuffer
151     mMmap.size = finfo.smem_len;
152@@ -384,11 +394,11 @@ bool QLinuxFbScreen::initialize()
153         return false;
154     }
155
156-    mMmap.offset = geometry.y() * mBytesPerLine + geometry.x() * mDepth / 8;
157+    mMmap.offset = originalGeometry.y() * mBytesPerLine + originalGeometry.x() * mDepth / 8;
158     mMmap.data = data + mMmap.offset;
159
160     QFbScreen::initializeCompositor();
161-    mFbScreenImage = QImage(mMmap.data, geometry.width(), geometry.height(), mBytesPerLine, mFormat);
162+    mFbScreenImage = QImage(mMmap.data, originalGeometry.width(), originalGeometry.height(), mBytesPerLine, mFormat);
163
164     mCursor = new QFbCursor(this);
165
166@@ -413,9 +423,22 @@ QRegion QLinuxFbScreen::doRedraw()
167         mBlitter = new QPainter(&mFbScreenImage);
168
169     mBlitter->setCompositionMode(QPainter::CompositionMode_Source);
170-    for (const QRect &rect : touched)
171+    for (const QRect &rect : touched) {
172+        if(mRotation) {
173+            if(mRotation == 180)
174+                mBlitter->translate(mGeometry.width()/2, mGeometry.height()/2);
175+            else
176+                mBlitter->translate(mGeometry.height()/2, mGeometry.width()/2);
177+
178+            mBlitter->rotate(mRotation);
179+            mBlitter->translate(-mGeometry.width()/2, -mGeometry.height()/2);
180+        }
181+
182         mBlitter->drawImage(rect, mScreenImage, rect);
183
184+        mBlitter->resetTransform();
185+    }
186+
187     return touched;
188 }
189
190diff --git a/src/plugins/platforms/linuxfb/qlinuxfbscreen.h b/src/plugins/platforms/linuxfb/qlinuxfbscreen.h
191index c7ce455e..70ea02fa 100644
192--- a/src/plugins/platforms/linuxfb/qlinuxfbscreen.h
193+++ b/src/plugins/platforms/linuxfb/qlinuxfbscreen.h
194@@ -75,6 +75,8 @@ private:
195     } mMmap;
196
197     QPainter *mBlitter;
198+
199+    int mRotation;
200 };
201
202 QT_END_NAMESPACE
203--
2042.20.1
205
206