Qt: Fix OpenGL renderer lagging behind when fast-forwarding (fixes #2094)

This commit is contained in:
Vicki Pfau 2021-04-11 23:31:29 -07:00
parent 509ab561c9
commit d5138bf885
4 changed files with 11 additions and 15 deletions

View File

@ -14,6 +14,7 @@ Other fixes:
- GBA Video: Fix mode 5 frame 1 caching (fixes mgba.io/i/2075) - GBA Video: Fix mode 5 frame 1 caching (fixes mgba.io/i/2075)
- GBA Video: Don't attempt to copy invalid registers when switching renderer - GBA Video: Don't attempt to copy invalid registers when switching renderer
- Qt: Fix crash when switching from high-resolution OpenGL renderer to software - Qt: Fix crash when switching from high-resolution OpenGL renderer to software
- Qt: Fix OpenGL renderer lagging behind when fast-forwarding (fixes mgba.io/i/2094)
Misc: Misc:
- Core: Truncate preloading ROMs that slightly exceed max size (fixes mgba.io/i/2093) - Core: Truncate preloading ROMs that slightly exceed max size (fixes mgba.io/i/2093)
- GBA: Default-enable VBA bug compat for Ruby and Emerald ROM hacks - GBA: Default-enable VBA bug compat for Ruby and Emerald ROM hacks

View File

@ -432,23 +432,16 @@ void PainterGL::draw() {
if (!m_active || m_queue.isEmpty()) { if (!m_active || m_queue.isEmpty()) {
return; return;
} }
if (m_lagging >= 1) {
return;
}
mCoreSync* sync = &m_context->thread()->impl->sync; mCoreSync* sync = &m_context->thread()->impl->sync;
if (!mCoreSyncWaitFrameStart(sync)) { if (!mCoreSyncWaitFrameStart(sync)) {
mCoreSyncWaitFrameEnd(sync); mCoreSyncWaitFrameEnd(sync);
++m_lagging;
if ((sync->audioWait || sync->videoFrameWait) && m_delayTimer.elapsed() < 1000 / m_surface->screen()->refreshRate()) { if ((sync->audioWait || sync->videoFrameWait) && m_delayTimer.elapsed() < 1000 / m_surface->screen()->refreshRate()) {
QTimer::singleShot(1, this, &PainterGL::draw); QTimer::singleShot(1, this, &PainterGL::draw);
} }
return; return;
} }
dequeue(); dequeue();
if (m_videoProxy) { bool forceRedraw = !m_videoProxy;
// Only block on the next frame if we're trying to run at roughly 60fps via audio
m_videoProxy->setBlocking(sync->audioWait && std::abs(60.f - sync->fpsTarget) < 0.1f);
}
if (!m_delayTimer.isValid()) { if (!m_delayTimer.isValid()) {
m_delayTimer.start(); m_delayTimer.start();
} else { } else {
@ -456,13 +449,18 @@ void PainterGL::draw() {
while (m_delayTimer.nsecsElapsed() + 2000000 < 1000000000 / sync->fpsTarget) { while (m_delayTimer.nsecsElapsed() + 2000000 < 1000000000 / sync->fpsTarget) {
QThread::usleep(500); QThread::usleep(500);
} }
forceRedraw = true;
} else if (!forceRedraw) {
forceRedraw = m_delayTimer.nsecsElapsed() + 2000000 >= 1000000000 / m_surface->screen()->refreshRate();
} }
m_delayTimer.restart();
} }
mCoreSyncWaitFrameEnd(sync); mCoreSyncWaitFrameEnd(sync);
performDraw(); if (forceRedraw) {
m_backend->swap(m_backend); m_delayTimer.restart();
performDraw();
m_backend->swap(m_backend);
}
} }
void PainterGL::forceDraw() { void PainterGL::forceDraw() {
@ -504,7 +502,6 @@ void PainterGL::pause() {
} }
void PainterGL::unpause() { void PainterGL::unpause() {
m_lagging = 0;
m_active = true; m_active = true;
} }
@ -538,7 +535,6 @@ void PainterGL::enqueue(const uint32_t* backing) {
memcpy(buffer, backing, size.width() * size.height() * BYTES_PER_PIXEL); memcpy(buffer, backing, size.width() * size.height() * BYTES_PER_PIXEL);
} }
} }
m_lagging = 0;
m_queue.enqueue(buffer); m_queue.enqueue(buffer);
} }

View File

@ -141,7 +141,6 @@ private:
std::array<std::array<uint32_t, 0x100000>, 3> m_buffers; std::array<std::array<uint32_t, 0x100000>, 3> m_buffers;
QList<uint32_t*> m_free; QList<uint32_t*> m_free;
QQueue<uint32_t*> m_queue; QQueue<uint32_t*> m_queue;
QAtomicInt m_lagging = 0;
uint32_t* m_buffer = nullptr; uint32_t* m_buffer = nullptr;
QPainter m_painter; QPainter m_painter;
QMutex m_mutex; QMutex m_mutex;

View File

@ -14,7 +14,7 @@ using namespace QGBA;
VideoProxy::VideoProxy() { VideoProxy::VideoProxy() {
mVideoLoggerRendererCreate(&m_logger.d, false); mVideoLoggerRendererCreate(&m_logger.d, false);
m_logger.d.block = true; m_logger.d.block = true;
m_logger.d.waitOnFlush = false; m_logger.d.waitOnFlush = true;
m_logger.d.init = &cbind<&VideoProxy::init>; m_logger.d.init = &cbind<&VideoProxy::init>;
m_logger.d.reset = &cbind<&VideoProxy::reset>; m_logger.d.reset = &cbind<&VideoProxy::reset>;