xref: /OK3568_Linux_fs/buildroot/package/qt5/qt5base/0013-linuxfb-Use-triple-buffer-by-default.patch (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1From cc8100277871e7fc13556149ca111272db6fd2d0 Mon Sep 17 00:00:00 2001
2From: Jeffy Chen <jeffy.chen@rock-chips.com>
3Date: Tue, 16 Apr 2019 18:46:49 +0800
4Subject: [PATCH 13/28] linuxfb: Use triple buffer by default
5
6Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
7---
8 .../platforms/linuxfb/qlinuxfbdrmscreen.cpp   | 56 +++++++++++++++----
9 1 file changed, 44 insertions(+), 12 deletions(-)
10
11diff --git a/src/plugins/platforms/linuxfb/qlinuxfbdrmscreen.cpp b/src/plugins/platforms/linuxfb/qlinuxfbdrmscreen.cpp
12index dcc1ef27..29d146f4 100644
13--- a/src/plugins/platforms/linuxfb/qlinuxfbdrmscreen.cpp
14+++ b/src/plugins/platforms/linuxfb/qlinuxfbdrmscreen.cpp
15@@ -59,7 +59,13 @@ QT_BEGIN_NAMESPACE
16
17 Q_LOGGING_CATEGORY(qLcFbDrm, "qt.qpa.fb")
18
19+#define TRIPLE_BUFFER
20+
21+#ifdef TRIPLE_BUFFER
22+static const int BUFFER_COUNT = 3;
23+#else
24 static const int BUFFER_COUNT = 2;
25+#endif
26
27 class QLinuxFbDevice : public QKmsDevice
28 {
29@@ -75,12 +81,12 @@ public:
30     };
31
32     struct Output {
33-        Output() : backFb(0), flipped(false) { }
34+        Output() : backFb(0), flipPending(false) { }
35         QKmsOutput kmsOutput;
36         Framebuffer fb[BUFFER_COUNT];
37         QRegion dirty[BUFFER_COUNT];
38         int backFb;
39-        bool flipped;
40+        bool flipPending;
41         QSize currentRes() const {
42             const drmModeModeInfo &modeInfo(kmsOutput.modes[kmsOutput.mode]);
43             return QSize(modeInfo.hdisplay, modeInfo.vdisplay);
44@@ -97,6 +103,7 @@ public:
45     void setMode();
46
47     void swapBuffers(Output *output);
48+    void waitForFlip(Output *output);
49
50     int outputCount() const { return m_outputs.count(); }
51     Output *output(int idx) { return &m_outputs[idx]; }
52@@ -301,7 +308,7 @@ void QLinuxFbDevice::createFramebuffers()
53                 return;
54         }
55         output.backFb = 0;
56-        output.flipped = false;
57+        output.flipPending = false;
58     }
59 }
60
61@@ -355,19 +362,18 @@ void QLinuxFbDevice::pageFlipHandler(int fd, unsigned int sequence,
62     Q_UNUSED(tv_usec);
63
64     Output *output = static_cast<Output *>(user_data);
65+
66+#ifndef TRIPLE_BUFFER
67+    // The next buffer would be available after flipped
68     output->backFb = (output->backFb + 1) % BUFFER_COUNT;
69+#endif
70+
71+    output->flipPending = false;
72 }
73
74-void QLinuxFbDevice::swapBuffers(Output *output)
75+void QLinuxFbDevice::waitForFlip(Output *output)
76 {
77-    Framebuffer &fb(output->fb[output->backFb]);
78-    if (drmModePageFlip(fd(), output->kmsOutput.crtc_id, fb.fb, DRM_MODE_PAGE_FLIP_EVENT, output) == -1) {
79-        qErrnoWarning(errno, "Page flip failed");
80-        return;
81-    }
82-
83-    const int fbIdx = output->backFb;
84-    while (output->backFb == fbIdx) {
85+    while (output->flipPending) {
86         drmEventContext drmEvent;
87         memset(&drmEvent, 0, sizeof(drmEvent));
88         drmEvent.version = 2;
89@@ -379,6 +385,27 @@ void QLinuxFbDevice::swapBuffers(Output *output)
90     }
91 }
92
93+void QLinuxFbDevice::swapBuffers(Output *output)
94+{
95+#ifdef TRIPLE_BUFFER
96+    // Wait flip to make sure last buffer displayed
97+    waitForFlip(output);
98+#endif
99+
100+    Framebuffer &fb(output->fb[output->backFb]);
101+    if (drmModePageFlip(fd(), output->kmsOutput.crtc_id, fb.fb, DRM_MODE_PAGE_FLIP_EVENT, output) == -1) {
102+        qErrnoWarning(errno, "Page flip failed");
103+        return;
104+    }
105+
106+    output->flipPending = true;
107+
108+#ifdef TRIPLE_BUFFER
109+    // The next buffer should always available in triple buffer case.
110+    output->backFb = (output->backFb + 1) % BUFFER_COUNT;
111+#endif
112+}
113+
114 QLinuxFbDrmScreen::QLinuxFbDrmScreen(const QStringList &args)
115     : m_screenConfig(nullptr),
116       m_device(nullptr)
117@@ -436,6 +463,11 @@ QRegion QLinuxFbDrmScreen::doRedraw()
118     for (int i = 0; i < BUFFER_COUNT; ++i)
119         output->dirty[i] += dirty;
120
121+#ifndef TRIPLE_BUFFER
122+    // Wait flip before accessing new buffer
123+    m_device->waitForFlip(output);
124+#endif
125+
126     if (output->fb[output->backFb].wrapper.isNull())
127         return dirty;
128
129--
1302.20.1
131
132