xref: /OK3568_Linux_fs/buildroot/package/qt5/qt5base/0016-HACK-linuxfb-Support-direct-painting.patch (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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 &region, const QPoint &offset) override;
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun     void resize(const QSize &size, const QRegion &region) 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