all repos — mgba @ 13ffd13cdd841571b5c2c0547611b7a3ea4467e8

mGBA Game Boy Advance Emulator

Qt: Improve sync code
Vicki Pfau vi@endrift.com
Thu, 23 May 2019 00:04:26 -0700
commit

13ffd13cdd841571b5c2c0547611b7a3ea4467e8

parent

5b040e236db0dd39e2e29ad7724b9712ac84c57a

4 files changed, 50 insertions(+), 27 deletions(-)

jump to
M CHANGESCHANGES

@@ -70,6 +70,7 @@ - GBA Video: Clean up dead code in sprite rendering loop

- FFmpeg: Support audio-only recording - Qt: Increase maximum magnifications and scaling - Qt: Add native FPS button to settings view + - Qt: Improve sync code 0.7.1: (2019-02-24) Bugfixes:
M src/platform/qt/Display.cppsrc/platform/qt/Display.cpp

@@ -20,7 +20,7 @@ Display* Display::create(QWidget* parent) {

#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(USE_EPOXY) QSurfaceFormat format; format.setSwapInterval(1); - format.setSwapBehavior(QSurfaceFormat::SingleBuffer); + format.setSwapBehavior(QSurfaceFormat::DoubleBuffer); #endif switch (s_driver) {
M src/platform/qt/DisplayGL.cppsrc/platform/qt/DisplayGL.cpp

@@ -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 * License, v. 2.0. If a copy of the MPL was not distributed with this

@@ -261,15 +261,9 @@ }

#endif m_backend->swap = [](VideoBackend* v) { PainterGL* painter = static_cast<PainterGL*>(v->user); - if (!painter->m_gl->isValid()) { - return; + if (!painter->m_swapTimer.isActive()) { + 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);

@@ -287,6 +281,10 @@

for (int i = 0; i < 2; ++i) { 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() {

@@ -375,26 +373,21 @@ if (m_queue.isEmpty()) {

return; } + if (m_needsUnlock) { + QTimer::singleShot(0, this, &PainterGL::draw); + return; + } + if (mCoreSyncWaitFrameStart(&m_context->thread()->impl->sync) || !m_queue.isEmpty()) { dequeue(); - mCoreSyncWaitFrameEnd(&m_context->thread()->impl->sync); - m_painter.begin(m_window); - performDraw(); - m_painter.end(); - m_backend->swap(m_backend); - 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(); + forceDraw(); + if (m_context->thread()->impl->sync.videoFrameWait) { + m_needsUnlock = true; + } else { + mCoreSyncWaitFrameEnd(&m_context->thread()->impl->sync); } } else { mCoreSyncWaitFrameEnd(&m_context->thread()->impl->sync); - } - if (!m_queue.isEmpty()) { - QMetaObject::invokeMethod(this, "draw", Qt::QueuedConnection); } }

@@ -437,6 +430,30 @@ m_backend->drawFrame(m_backend);

m_painter.endNativePainting(); if (m_messagePainter) { 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(); } }
M src/platform/qt/DisplayGL.hsrc/platform/qt/DisplayGL.h

@@ -16,13 +16,13 @@ #define GLdouble GLdouble

#endif #endif -#include <QElapsedTimer> #include <QOpenGLContext> #include <QList> #include <QMouseEvent> #include <QPainter> #include <QQueue> #include <QThread> +#include <QTimer> #include "VideoProxy.h"

@@ -105,6 +105,9 @@ VideoShader* shaders();

int glTex(); +private slots: + void swap(); + private: void performDraw(); void dequeue();

@@ -125,7 +128,9 @@ VideoShader m_shader{};

VideoBackend* m_backend = nullptr; QSize m_size; MessagePainter* m_messagePainter = nullptr; - QElapsedTimer m_delayTimer; + QTimer m_swapTimer{this}; + bool m_needsUnlock = false; + bool m_frameReady = false; VideoProxy* m_videoProxy; };