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