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