Qt: Improve sync code

This commit is contained in:
Vicki Pfau 2019-05-23 00:04:26 -07:00
parent 5b040e236d
commit 13ffd13cdd
4 changed files with 50 additions and 27 deletions

View File

@ -70,6 +70,7 @@ Misc:
- FFmpeg: Support audio-only recording - FFmpeg: Support audio-only recording
- Qt: Increase maximum magnifications and scaling - Qt: Increase maximum magnifications and scaling
- Qt: Add native FPS button to settings view - Qt: Add native FPS button to settings view
- Qt: Improve sync code
0.7.1: (2019-02-24) 0.7.1: (2019-02-24)
Bugfixes: Bugfixes:

View File

@ -20,7 +20,7 @@ Display* Display::create(QWidget* parent) {
#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(USE_EPOXY) #if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(USE_EPOXY)
QSurfaceFormat format; QSurfaceFormat format;
format.setSwapInterval(1); format.setSwapInterval(1);
format.setSwapBehavior(QSurfaceFormat::SingleBuffer); format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
#endif #endif
switch (s_driver) { switch (s_driver) {

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2013-2015 Jeffrey Pfau /* Copyright (c) 2013-2019 Jeffrey Pfau
* *
* This Source Code Form is subject to the terms of the Mozilla Public * This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -261,15 +261,9 @@ PainterGL::PainterGL(VideoProxy* proxy, QWindow* surface, QOpenGLContext* parent
#endif #endif
m_backend->swap = [](VideoBackend* v) { m_backend->swap = [](VideoBackend* v) {
PainterGL* painter = static_cast<PainterGL*>(v->user); PainterGL* painter = static_cast<PainterGL*>(v->user);
if (!painter->m_gl->isValid()) { if (!painter->m_swapTimer.isActive()) {
return; QMetaObject::invokeMethod(&painter->m_swapTimer, "start");
} }
painter->m_gl->swapBuffers(painter->m_surface);
painter->m_gl->doneCurrent();
painter->m_gl->makeCurrent(painter->m_surface);
#if defined(_WIN32) && defined(USE_EPOXY)
epoxy_handle_external_wglMakeCurrent();
#endif
}; };
m_backend->init(m_backend, 0); m_backend->init(m_backend, 0);
@ -287,6 +281,10 @@ PainterGL::PainterGL(VideoProxy* proxy, QWindow* surface, QOpenGLContext* parent
for (int i = 0; i < 2; ++i) { for (int i = 0; i < 2; ++i) {
m_free.append(new uint32_t[1024 * 2048]); m_free.append(new uint32_t[1024 * 2048]);
} }
m_swapTimer.setInterval(16);
m_swapTimer.setSingleShot(true);
connect(&m_swapTimer, &QTimer::timeout, this, &PainterGL::swap);
} }
PainterGL::~PainterGL() { PainterGL::~PainterGL() {
@ -375,27 +373,22 @@ void PainterGL::draw() {
return; return;
} }
if (m_needsUnlock) {
QTimer::singleShot(0, this, &PainterGL::draw);
return;
}
if (mCoreSyncWaitFrameStart(&m_context->thread()->impl->sync) || !m_queue.isEmpty()) { if (mCoreSyncWaitFrameStart(&m_context->thread()->impl->sync) || !m_queue.isEmpty()) {
dequeue(); dequeue();
mCoreSyncWaitFrameEnd(&m_context->thread()->impl->sync); forceDraw();
m_painter.begin(m_window); if (m_context->thread()->impl->sync.videoFrameWait) {
performDraw(); m_needsUnlock = true;
m_painter.end(); } else {
m_backend->swap(m_backend); mCoreSyncWaitFrameEnd(&m_context->thread()->impl->sync);
if (!m_delayTimer.isValid()) {
m_delayTimer.start();
} else if (m_gl->format().swapInterval() && m_context->videoSync()) {
while (m_delayTimer.elapsed() < 15) {
QThread::usleep(100);
}
m_delayTimer.restart();
} }
} else { } else {
mCoreSyncWaitFrameEnd(&m_context->thread()->impl->sync); mCoreSyncWaitFrameEnd(&m_context->thread()->impl->sync);
} }
if (!m_queue.isEmpty()) {
QMetaObject::invokeMethod(this, "draw", Qt::QueuedConnection);
}
} }
void PainterGL::forceDraw() { void PainterGL::forceDraw() {
@ -438,6 +431,30 @@ void PainterGL::performDraw() {
if (m_messagePainter) { if (m_messagePainter) {
m_messagePainter->paint(&m_painter); m_messagePainter->paint(&m_painter);
} }
m_frameReady = true;
}
void PainterGL::swap() {
if (!m_gl->isValid()) {
return;
}
if (m_frameReady) {
m_gl->swapBuffers(m_surface);
m_gl->makeCurrent(m_surface);
#if defined(_WIN32) && defined(USE_EPOXY)
epoxy_handle_external_wglMakeCurrent();
#endif
m_frameReady = false;
}
if (m_needsUnlock) {
mCoreSyncWaitFrameEnd(&m_context->thread()->impl->sync);
m_needsUnlock = false;
}
if (!m_queue.isEmpty()) {
QMetaObject::invokeMethod(this, "draw", Qt::QueuedConnection);
} else {
m_swapTimer.start();
}
} }
void PainterGL::enqueue(const uint32_t* backing) { void PainterGL::enqueue(const uint32_t* backing) {

View File

@ -16,13 +16,13 @@
#endif #endif
#endif #endif
#include <QElapsedTimer>
#include <QOpenGLContext> #include <QOpenGLContext>
#include <QList> #include <QList>
#include <QMouseEvent> #include <QMouseEvent>
#include <QPainter> #include <QPainter>
#include <QQueue> #include <QQueue>
#include <QThread> #include <QThread>
#include <QTimer>
#include "VideoProxy.h" #include "VideoProxy.h"
@ -105,6 +105,9 @@ public slots:
int glTex(); int glTex();
private slots:
void swap();
private: private:
void performDraw(); void performDraw();
void dequeue(); void dequeue();
@ -125,7 +128,9 @@ private:
VideoBackend* m_backend = nullptr; VideoBackend* m_backend = nullptr;
QSize m_size; QSize m_size;
MessagePainter* m_messagePainter = nullptr; MessagePainter* m_messagePainter = nullptr;
QElapsedTimer m_delayTimer; QTimer m_swapTimer{this};
bool m_needsUnlock = false;
bool m_frameReady = false;
VideoProxy* m_videoProxy; VideoProxy* m_videoProxy;
}; };