Qt: Discard additional frame draws if waiting fails
Vicki Pfau vi@endrift.com
Fri, 27 Nov 2020 18:31:13 -0800
3 files changed,
22 insertions(+),
5 deletions(-)
M
CHANGES
→
CHANGES
@@ -102,6 +102,7 @@ - Qt: Memory viewer now supports editing decimal values directly (closes mgba.io/i/1705)
- 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)
M
src/platform/qt/DisplayGL.cpp
→
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 @@ } else if (sync->audioWait || sync->videoFrameWait) {
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 @@ m_active = false;
} 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 @@ m_painter.endNativePainting();
if (m_showOSD && m_messagePainter) { m_messagePainter->paint(&m_painter); } + m_painter.end(); } void PainterGL::enqueue(const uint32_t* backing) {@@ -517,6 +529,7 @@ QSize size = m_context->screenDimensions();
memcpy(buffer, backing, size.width() * size.height() * BYTES_PER_PIXEL); } } + m_lagging = 0; m_queue.enqueue(buffer); }@@ -531,6 +544,7 @@ m_free.append(m_buffer);
m_buffer = nullptr; } m_buffer = buffer; + return; } void PainterGL::dequeueAll() {
M
src/platform/qt/DisplayGL.h
→
src/platform/qt/DisplayGL.h
@@ -16,6 +16,7 @@ #define GLdouble GLdouble
#endif #endif +#include <QAtomicInt> #include <QElapsedTimer> #include <QOpenGLContext> #include <QList>@@ -130,6 +131,7 @@
std::array<std::array<uint32_t, 0x100000>, 3> m_buffers; QList<uint32_t*> m_free; QQueue<uint32_t*> m_queue; + QAtomicInt m_lagging = 0; uint32_t* m_buffer; QPainter m_painter; QMutex m_mutex;