all repos — mgba @ 8e096916b1dc1aacc17236e8d2bf6eda4edb5edf

mGBA Game Boy Advance Emulator

Qt: Discard additional frame draws if waiting fails
Vicki Pfau vi@endrift.com
Fri, 27 Nov 2020 18:31:13 -0800
commit

8e096916b1dc1aacc17236e8d2bf6eda4edb5edf

parent

fc3e47a4bab1465b91e7368c6396b222f65f51cb

3 files changed, 22 insertions(+), 5 deletions(-)

jump to
M CHANGESCHANGES

@@ -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.cppsrc/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.hsrc/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;