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