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