1From 762b506da170480bb101c4d7841850cc2aba3825 Mon Sep 17 00:00:00 2001 2From: Jeffy Chen <jeffy.chen@rock-chips.com> 3Date: Thu, 11 Jun 2020 10:27:16 +0800 4Subject: [PATCH 16/28] HACK: linuxfb: Support direct painting 5 6Doing direct painting on fully update single window case. 7 8Define QT_FB_DIRECT_PAINTING macro to enable. 9 10Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> 11--- 12 .../fbconvenience/qfbbackingstore.cpp | 29 +++++++++-- 13 .../fbconvenience/qfbbackingstore_p.h | 12 ++++- 14 .../fbconvenience/qfbscreen.cpp | 49 +++++++++++++++++-- 15 .../fbconvenience/qfbscreen_p.h | 2 + 16 .../platforms/linuxfb/qlinuxfbdrmscreen.cpp | 14 ++++++ 17 5 files changed, 98 insertions(+), 8 deletions(-) 18 19diff --git a/src/platformsupport/fbconvenience/qfbbackingstore.cpp b/src/platformsupport/fbconvenience/qfbbackingstore.cpp 20index e2d94406..92c2d92c 100644 21--- a/src/platformsupport/fbconvenience/qfbbackingstore.cpp 22+++ b/src/platformsupport/fbconvenience/qfbbackingstore.cpp 23@@ -47,6 +47,9 @@ 24 25 QT_BEGIN_NAMESPACE 26 27+QImage * QFbBackingStore::gScreenImage = NULL; 28+QImage * QFbBackingStore::gFbImage = NULL; 29+ 30 QFbBackingStore::QFbBackingStore(QWindow *window) 31 : QPlatformBackingStore(window) 32 { 33@@ -76,15 +79,33 @@ void QFbBackingStore::resize(const QSize &size, const QRegion &staticContents) 34 mImage = QImage(size, window()->screen()->handle()->format()); 35 } 36 37-const QImage QFbBackingStore::image() 38+QPaintDevice *QFbBackingStore::paintDevice() 39 { 40- return mImage; 41-} 42+ // HACK: gScreenImage available means allowing directly painting 43+ if (!gScreenImage) 44+ return &mImage; 45 46+ // HACK: Prefer directly painting to fb when it's available 47+ if (gFbImage) 48+ return gFbImage; 49+ 50+ return gScreenImage; 51+} 52 53 QImage QFbBackingStore::toImage() const 54 { 55- return mImage; 56+ if (!gScreenImage) 57+ return mImage; 58+ 59+ if (gFbImage) 60+ return *gFbImage; 61+ 62+ return *gScreenImage; 63+} 64+ 65+const QImage QFbBackingStore::image() 66+{ 67+ return toImage(); 68 } 69 70 void QFbBackingStore::lock() 71diff --git a/src/platformsupport/fbconvenience/qfbbackingstore_p.h b/src/platformsupport/fbconvenience/qfbbackingstore_p.h 72index c4762c93..214d85c2 100644 73--- a/src/platformsupport/fbconvenience/qfbbackingstore_p.h 74+++ b/src/platformsupport/fbconvenience/qfbbackingstore_p.h 75@@ -66,7 +66,7 @@ public: 76 QFbBackingStore(QWindow *window); 77 ~QFbBackingStore(); 78 79- QPaintDevice *paintDevice() override { return &mImage; } 80+ QPaintDevice *paintDevice() override; 81 void flush(QWindow *window, const QRegion ®ion, const QPoint &offset) override; 82 83 void resize(const QSize &size, const QRegion ®ion) override; 84@@ -80,11 +80,21 @@ public: 85 void beginPaint(const QRegion &) override; 86 void endPaint() override; 87 88+ static void setScreenImage(QImage *screenImage) 89+ { gScreenImage = screenImage; }; 90+ static void setFbImage(QImage *fbImage) { gFbImage = fbImage; } 91+ 92+ static bool hasScreenImage() { return gScreenImage != NULL; }; 93+ static bool hasFbImage() { return gFbImage != NULL; }; 94+ 95 protected: 96 friend class QFbWindow; 97 98 QImage mImage; 99 QMutex mImageMutex; 100+ 101+ static QImage *gScreenImage; 102+ static QImage *gFbImage; 103 }; 104 105 QT_END_NAMESPACE 106diff --git a/src/platformsupport/fbconvenience/qfbscreen.cpp b/src/platformsupport/fbconvenience/qfbscreen.cpp 107index 76984dfe..21308067 100644 108--- a/src/platformsupport/fbconvenience/qfbscreen.cpp 109+++ b/src/platformsupport/fbconvenience/qfbscreen.cpp 110@@ -56,7 +56,8 @@ QFbScreen::QFbScreen() 111 mCursor(0), 112 mDepth(16), 113 mFormat(QImage::Format_RGB16), 114- mPainter(nullptr) 115+ mPainter(nullptr), 116+ mDirectPainting(false) 117 { 118 } 119 120@@ -84,6 +85,15 @@ bool QFbScreen::event(QEvent *event) 121 void QFbScreen::addWindow(QFbWindow *window) 122 { 123 mWindowStack.prepend(window); 124+ 125+#ifdef QT_FB_DIRECT_PAINTING 126+ // HACK: Only allow direct painting for single window 127+ if (windowCount() == 1) 128+ QFbBackingStore::setScreenImage(&mScreenImage); 129+ else 130+ QFbBackingStore::setScreenImage(NULL); 131+#endif 132+ 133 if (!mPendingBackingStores.isEmpty()) { 134 //check if we have a backing store for this window 135 for (int i = 0; i < mPendingBackingStores.size(); ++i) { 136@@ -106,6 +116,15 @@ void QFbScreen::addWindow(QFbWindow *window) 137 void QFbScreen::removeWindow(QFbWindow *window) 138 { 139 mWindowStack.removeOne(window); 140+ 141+#ifdef QT_FB_DIRECT_PAINTING 142+ // HACK: Only allow direct painting for single window 143+ if (windowCount() == 1) 144+ QFbBackingStore::setScreenImage(&mScreenImage); 145+ else 146+ QFbBackingStore::setScreenImage(NULL); 147+#endif 148+ 149 setDirty(window->geometry()); 150 QWindow *w = topWindow(); 151 QWindowSystemInterface::handleWindowActivated(w); 152@@ -208,16 +227,35 @@ QRegion QFbScreen::doRedraw() 153 return touchedRegion; 154 155 if (!mPainter) 156- mPainter = new QPainter(&mScreenImage); 157+ mPainter = new QPainter(); 158 159 const QRect screenRect = mGeometry.translated(-screenOffset); 160+ bool fully_repainted = mRepaintRegion.rectCount() == 1 && 161+ mRepaintRegion.boundingRect().contains(screenRect); 162+ 163+ if (fully_repainted && QFbBackingStore::hasScreenImage()) { 164+ // HACK: The screen(or fb) has been fully repainted 165+ touchedRegion += mRepaintRegion; 166+ mRepaintRegion = QRegion(); 167+ mDirectPainting = true; 168+ return touchedRegion; 169+ } 170+ 171+ // HACK: Ignore partial update in direct paiting mode 172+ if (mDirectPainting && !fully_repainted) 173+ return touchedRegion; 174+ 175+ mPainter->begin(&mScreenImage); 176+ 177 for (QRect rect : mRepaintRegion) { 178 rect = rect.intersected(screenRect); 179 if (rect.isEmpty()) 180 continue; 181 182 mPainter->setCompositionMode(QPainter::CompositionMode_Source); 183- mPainter->fillRect(rect, mScreenImage.hasAlphaChannel() ? Qt::transparent : Qt::black); 184+ 185+ if (!QFbBackingStore::hasScreenImage()) 186+ mPainter->fillRect(rect, mScreenImage.hasAlphaChannel() ? Qt::transparent : Qt::black); 187 188 for (int layerIndex = mWindowStack.size() - 1; layerIndex != -1; layerIndex--) { 189 if (!mWindowStack[layerIndex]->window()->isVisible()) 190@@ -241,6 +279,11 @@ QRegion QFbScreen::doRedraw() 191 touchedRegion += mRepaintRegion; 192 mRepaintRegion = QRegion(); 193 194+ // HACK: Force updating fb when not doing direct painting 195+ QFbBackingStore::setFbImage(NULL); 196+ 197+ mPainter->end(); 198+ 199 return touchedRegion; 200 } 201 202diff --git a/src/platformsupport/fbconvenience/qfbscreen_p.h b/src/platformsupport/fbconvenience/qfbscreen_p.h 203index eed615de..48ee4c23 100644 204--- a/src/platformsupport/fbconvenience/qfbscreen_p.h 205+++ b/src/platformsupport/fbconvenience/qfbscreen_p.h 206@@ -124,6 +124,8 @@ protected: 207 QSizeF mPhysicalSize; 208 QImage mScreenImage; 209 210+ bool mDirectPainting; 211+ 212 private: 213 QPainter *mPainter; 214 QList<QFbBackingStore*> mPendingBackingStores; 215diff --git a/src/plugins/platforms/linuxfb/qlinuxfbdrmscreen.cpp b/src/plugins/platforms/linuxfb/qlinuxfbdrmscreen.cpp 216index 0c4f6d2c..5745ef06 100644 217--- a/src/plugins/platforms/linuxfb/qlinuxfbdrmscreen.cpp 218+++ b/src/plugins/platforms/linuxfb/qlinuxfbdrmscreen.cpp 219@@ -52,6 +52,7 @@ 220 #include <QtCore/QRegularExpression> 221 #include <QtFbSupport/private/qfbcursor_p.h> 222 #include <QtFbSupport/private/qfbwindow_p.h> 223+#include <QtFbSupport/private/qfbbackingstore_p.h> 224 #include <QtKmsSupport/private/qkmsdevice_p.h> 225 #include <QtCore/private/qcore_unix_p.h> 226 #include <sys/mman.h> 227@@ -486,6 +487,10 @@ QRegion QLinuxFbDrmScreen::doRedraw() 228 return dirty; 229 230 QPainter pntr(&output->fb[output->backFb].wrapper); 231+ 232+ if (QFbBackingStore::hasScreenImage() && QFbBackingStore::hasFbImage()) 233+ goto swap; 234+ 235 // Image has alpha but no need for blending at this stage. 236 // Do not waste time with the default SourceOver. 237 pntr.setCompositionMode(QPainter::CompositionMode_Source); 238@@ -506,10 +511,19 @@ QRegion QLinuxFbDrmScreen::doRedraw() 239 } 240 pntr.end(); 241 242+swap: 243 output->dirty[output->backFb] = QRegion(); 244 245 m_device->swapBuffers(output); 246 247+ static int count_down = BUFFER_COUNT; 248+ if (count_down || m_rotation || m_device->outputCount() > 1) { 249+ count_down --; 250+ QFbBackingStore::setFbImage(NULL); 251+ } else { 252+ QFbBackingStore::setFbImage(&output->fb[output->backFb].wrapper); 253+ } 254+ 255 return dirty; 256 } 257 258-- 2592.20.1 260 261