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