From 8e096916b1dc1aacc17236e8d2bf6eda4edb5edf Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 27 Nov 2020 18:31:13 -0800 Subject: [PATCH] Qt: Discard additional frame draws if waiting fails --- CHANGES | 1 + src/platform/qt/DisplayGL.cpp | 24 +++++++++++++++++++----- src/platform/qt/DisplayGL.h | 2 ++ 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/CHANGES b/CHANGES index 843d9e530..dc94b316d 100644 --- a/CHANGES +++ b/CHANGES @@ -102,6 +102,7 @@ Misc: - Qt: Add copy button to GB printer dialog - Qt: Window title updates can be disabled (closes mgba.io/i/1912) - Qt: Redo OpenGL context thread handling (fixes mgba.io/i/1724) + - Qt: Discard additional frame draws if waiting fails - Util: Reset vector size on deinit - VFS: Change semantics of VFile.sync on mapped files (fixes mgba.io/i/1730) diff --git a/src/platform/qt/DisplayGL.cpp b/src/platform/qt/DisplayGL.cpp index 17e1ea360..350aec1f1 100644 --- a/src/platform/qt/DisplayGL.cpp +++ b/src/platform/qt/DisplayGL.cpp @@ -432,8 +432,18 @@ void PainterGL::draw() { if (!m_active || m_queue.isEmpty()) { return; } + if (m_lagging >= 1) { + return; + } mCoreSync* sync = &m_context->thread()->impl->sync; - mCoreSyncWaitFrameStart(sync); + if (!mCoreSyncWaitFrameStart(sync)) { + mCoreSyncWaitFrameEnd(sync); + ++m_lagging; + if (m_delayTimer.elapsed() < 1000 / m_surface->screen()->refreshRate()) { + QTimer::singleShot(1, this, &PainterGL::draw); + } + return; + } dequeue(); if (m_videoProxy) { // Only block on the next frame if we're trying to run at roughly 60fps via audio @@ -445,17 +455,16 @@ void PainterGL::draw() { while (m_delayTimer.nsecsElapsed() + 2000000 < 1000000000 / sync->fpsTarget) { QThread::usleep(500); } - m_delayTimer.restart(); } mCoreSyncWaitFrameEnd(sync); - forceDraw(); + performDraw(); + m_backend->swap(m_backend); + m_delayTimer.restart(); } void PainterGL::forceDraw() { - m_painter.begin(m_window.get()); performDraw(); - m_painter.end(); if (!m_context->thread()->impl->sync.audioWait && !m_context->thread()->impl->sync.videoFrameWait) { if (m_delayTimer.elapsed() < 1000 / m_surface->screen()->refreshRate()) { return; @@ -486,10 +495,12 @@ void PainterGL::pause() { } void PainterGL::unpause() { + m_lagging = 0; m_active = true; } void PainterGL::performDraw() { + m_painter.begin(m_window.get()); m_painter.beginNativePainting(); float r = m_surface->devicePixelRatio(); m_backend->resized(m_backend, m_size.width() * r, m_size.height() * r); @@ -501,6 +512,7 @@ void PainterGL::performDraw() { if (m_showOSD && m_messagePainter) { m_messagePainter->paint(&m_painter); } + m_painter.end(); } void PainterGL::enqueue(const uint32_t* backing) { @@ -517,6 +529,7 @@ void PainterGL::enqueue(const uint32_t* backing) { memcpy(buffer, backing, size.width() * size.height() * BYTES_PER_PIXEL); } } + m_lagging = 0; m_queue.enqueue(buffer); } @@ -531,6 +544,7 @@ void PainterGL::dequeue() { m_buffer = nullptr; } m_buffer = buffer; + return; } void PainterGL::dequeueAll() { diff --git a/src/platform/qt/DisplayGL.h b/src/platform/qt/DisplayGL.h index be982b006..5af24e478 100644 --- a/src/platform/qt/DisplayGL.h +++ b/src/platform/qt/DisplayGL.h @@ -16,6 +16,7 @@ #endif #endif +#include #include #include #include @@ -130,6 +131,7 @@ private: std::array, 3> m_buffers; QList m_free; QQueue m_queue; + QAtomicInt m_lagging = 0; uint32_t* m_buffer; QPainter m_painter; QMutex m_mutex;