mirror of https://github.com/mgba-emu/mgba.git
Qt: Improve frame pacing, maybe
This commit is contained in:
parent
9bcfd248e9
commit
76d6055bb0
|
@ -25,10 +25,10 @@ void mCoreSyncPostFrame(struct mCoreSync* sync) {
|
|||
MutexLock(&sync->videoFrameMutex);
|
||||
++sync->videoFramePending;
|
||||
do {
|
||||
ConditionWake(&sync->videoFrameAvailableCond);
|
||||
if (sync->videoFrameWait) {
|
||||
ConditionWait(&sync->videoFrameRequiredCond, &sync->videoFrameMutex);
|
||||
}
|
||||
ConditionWake(&sync->videoFrameAvailableCond);
|
||||
} while (sync->videoFrameWait && sync->videoFramePending);
|
||||
MutexUnlock(&sync->videoFrameMutex);
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ bool mCoreSyncWaitFrameStart(struct mCoreSync* sync) {
|
|||
}
|
||||
if (sync->videoFrameWait) {
|
||||
ConditionWake(&sync->videoFrameRequiredCond);
|
||||
if (ConditionWaitTimed(&sync->videoFrameAvailableCond, &sync->videoFrameMutex, 50)) {
|
||||
if (ConditionWaitTimed(&sync->videoFrameAvailableCond, &sync->videoFrameMutex, 4)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -619,11 +619,12 @@ void PainterGL::start() {
|
|||
m_buffer = nullptr;
|
||||
m_active = true;
|
||||
m_started = true;
|
||||
resetTiming();
|
||||
emit started();
|
||||
}
|
||||
|
||||
void PainterGL::draw() {
|
||||
if (!m_started || m_queue.isEmpty()) {
|
||||
if (!m_started) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -636,14 +637,16 @@ void PainterGL::draw() {
|
|||
}
|
||||
|
||||
mCoreSync* sync = &m_context->thread()->impl->sync;
|
||||
|
||||
qint64 targetNsec = 1000000000 / sync->fpsTarget;
|
||||
qint64 refreshNsec = 1000000000 / m_window->screen()->refreshRate();
|
||||
qint64 delay = m_timerResidue;
|
||||
|
||||
if (!mCoreSyncWaitFrameStart(sync)) {
|
||||
mCoreSyncWaitFrameEnd(sync);
|
||||
if (!sync->audioWait && !sync->videoFrameWait) {
|
||||
return;
|
||||
}
|
||||
if (m_delayTimer.elapsed() >= 1000 / m_window->screen()->refreshRate()) {
|
||||
return;
|
||||
}
|
||||
if (!m_drawTimer.isActive()) {
|
||||
m_drawTimer.start(1);
|
||||
}
|
||||
|
@ -651,23 +654,30 @@ void PainterGL::draw() {
|
|||
}
|
||||
dequeue();
|
||||
bool forceRedraw = !m_videoProxy;
|
||||
if (!m_delayTimer.isValid()) {
|
||||
m_delayTimer.start();
|
||||
} else {
|
||||
if (sync->audioWait || sync->videoFrameWait) {
|
||||
while (m_delayTimer.nsecsElapsed() + OVERHEAD_NSEC < 1000000000 / sync->fpsTarget) {
|
||||
QThread::usleep(500);
|
||||
while (delay + m_delayTimer.nsecsElapsed() + OVERHEAD_NSEC < targetNsec) {
|
||||
QThread::usleep(200);
|
||||
}
|
||||
forceRedraw = sync->videoFrameWait;
|
||||
}
|
||||
if (!forceRedraw) {
|
||||
forceRedraw = m_delayTimer.nsecsElapsed() + OVERHEAD_NSEC >= 1000000000 / m_window->screen()->refreshRate();
|
||||
}
|
||||
forceRedraw = delay + m_delayTimer.nsecsElapsed() + OVERHEAD_NSEC >= refreshNsec;
|
||||
}
|
||||
mCoreSyncWaitFrameEnd(sync);
|
||||
|
||||
if (forceRedraw) {
|
||||
delay += m_delayTimer.nsecsElapsed();
|
||||
m_delayTimer.restart();
|
||||
|
||||
delay -= targetNsec;
|
||||
m_timerResidue = (m_timerResidue + delay) / 2;
|
||||
|
||||
if (m_timerResidue > refreshNsec) {
|
||||
if (!m_drawTimer.isActive()) {
|
||||
m_drawTimer.start(1);
|
||||
}
|
||||
}
|
||||
|
||||
performDraw();
|
||||
m_backend->swap(m_backend);
|
||||
}
|
||||
|
@ -679,11 +689,16 @@ void PainterGL::forceDraw() {
|
|||
if (m_delayTimer.elapsed() < 1000 / m_window->screen()->refreshRate()) {
|
||||
return;
|
||||
}
|
||||
m_delayTimer.restart();
|
||||
resetTiming();
|
||||
}
|
||||
m_backend->swap(m_backend);
|
||||
}
|
||||
|
||||
void PainterGL::resetTiming() {
|
||||
m_delayTimer.restart();
|
||||
m_timerResidue = 0;
|
||||
}
|
||||
|
||||
void PainterGL::stop() {
|
||||
m_started = false;
|
||||
QMetaObject::invokeMethod(this, "doStop", Qt::BlockingQueuedConnection);
|
||||
|
@ -721,6 +736,7 @@ void PainterGL::pause() {
|
|||
|
||||
void PainterGL::unpause() {
|
||||
m_active = true;
|
||||
resetTiming();
|
||||
}
|
||||
|
||||
void PainterGL::performDraw() {
|
||||
|
|
|
@ -176,8 +176,9 @@ private:
|
|||
void performDraw();
|
||||
void dequeue();
|
||||
void dequeueAll(bool keep = false);
|
||||
void resetTiming();
|
||||
|
||||
std::array<std::array<uint32_t, 0x100000>, 3> m_buffers;
|
||||
std::array<std::array<uint32_t, 0x100000>, 8> m_buffers;
|
||||
QList<uint32_t*> m_free;
|
||||
QQueue<uint32_t*> m_queue;
|
||||
uint32_t* m_buffer = nullptr;
|
||||
|
@ -194,6 +195,7 @@ private:
|
|||
bool m_active = false;
|
||||
bool m_started = false;
|
||||
QTimer m_drawTimer;
|
||||
qint64 m_timerResidue;
|
||||
std::shared_ptr<CoreController> m_context;
|
||||
CoreController::Interrupter m_interrupter;
|
||||
bool m_supportsShaders;
|
||||
|
|
Loading…
Reference in New Issue