mirror of https://github.com/mgba-emu/mgba.git
Qt: Improve GL sync (really)
This commit is contained in:
parent
44c9be7060
commit
3920c6191f
|
@ -12,7 +12,9 @@
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QOpenGLContext>
|
#include <QOpenGLContext>
|
||||||
#include <QOpenGLPaintDevice>
|
#include <QOpenGLPaintDevice>
|
||||||
|
#include <QMutexLocker>
|
||||||
#include <QResizeEvent>
|
#include <QResizeEvent>
|
||||||
|
#include <QScreen>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QWindow>
|
#include <QWindow>
|
||||||
|
|
||||||
|
@ -278,9 +280,14 @@ PainterGL::PainterGL(QWindow* surface, QOpenGLContext* parent, int forceVersion)
|
||||||
#endif
|
#endif
|
||||||
m_backend->swap = [](VideoBackend* v) {
|
m_backend->swap = [](VideoBackend* v) {
|
||||||
PainterGL* painter = static_cast<PainterGL*>(v->user);
|
PainterGL* painter = static_cast<PainterGL*>(v->user);
|
||||||
if (!painter->m_swapTimer.isActive()) {
|
if (!painter->m_gl->isValid()) {
|
||||||
QMetaObject::invokeMethod(&painter->m_swapTimer, "start");
|
return;
|
||||||
}
|
}
|
||||||
|
painter->m_gl->swapBuffers(painter->m_surface);
|
||||||
|
painter->m_gl->makeCurrent(painter->m_surface);
|
||||||
|
#if defined(_WIN32) && defined(USE_EPOXY)
|
||||||
|
epoxy_handle_external_wglMakeCurrent();
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
m_backend->init(m_backend, 0);
|
m_backend->init(m_backend, 0);
|
||||||
|
@ -289,6 +296,7 @@ PainterGL::PainterGL(QWindow* surface, QOpenGLContext* parent, int forceVersion)
|
||||||
m_shader.preprocessShader = static_cast<void*>(&reinterpret_cast<mGLES2Context*>(m_backend)->initialShader);
|
m_shader.preprocessShader = static_cast<void*>(&reinterpret_cast<mGLES2Context*>(m_backend)->initialShader);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
m_gl->doneCurrent();
|
||||||
|
|
||||||
m_backend->user = this;
|
m_backend->user = this;
|
||||||
m_backend->filter = false;
|
m_backend->filter = false;
|
||||||
|
@ -298,10 +306,6 @@ PainterGL::PainterGL(QWindow* surface, QOpenGLContext* parent, int forceVersion)
|
||||||
for (int i = 0; i < 2; ++i) {
|
for (int i = 0; i < 2; ++i) {
|
||||||
m_free.append(new uint32_t[1024 * 2048]);
|
m_free.append(new uint32_t[1024 * 2048]);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_swapTimer.setInterval(16);
|
|
||||||
m_swapTimer.setSingleShot(true);
|
|
||||||
connect(&m_swapTimer, &QTimer::timeout, this, &PainterGL::swap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PainterGL::~PainterGL() {
|
PainterGL::~PainterGL() {
|
||||||
|
@ -390,32 +394,35 @@ void PainterGL::start() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PainterGL::draw() {
|
void PainterGL::draw() {
|
||||||
if (m_queue.isEmpty()) {
|
if (!m_active || m_queue.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
mCoreSync* sync = &m_context->thread()->impl->sync;
|
||||||
if (m_needsUnlock) {
|
mCoreSyncWaitFrameStart(sync);
|
||||||
QTimer::singleShot(0, this, &PainterGL::draw);
|
dequeue();
|
||||||
return;
|
if (!m_delayTimer.isValid()) {
|
||||||
}
|
m_delayTimer.start();
|
||||||
|
} else if (sync->audioWait || sync->videoFrameWait) {
|
||||||
if (mCoreSyncWaitFrameStart(&m_context->thread()->impl->sync) || !m_queue.isEmpty()) {
|
while (m_delayTimer.nsecsElapsed() + 2000000 < 1000000000 / sync->fpsTarget) {
|
||||||
dequeue();
|
QThread::usleep(500);
|
||||||
forceDraw();
|
|
||||||
if (m_context->thread()->impl->sync.videoFrameWait) {
|
|
||||||
m_needsUnlock = true;
|
|
||||||
} else {
|
|
||||||
mCoreSyncWaitFrameEnd(&m_context->thread()->impl->sync);
|
|
||||||
}
|
}
|
||||||
} else {
|
m_delayTimer.restart();
|
||||||
mCoreSyncWaitFrameEnd(&m_context->thread()->impl->sync);
|
|
||||||
}
|
}
|
||||||
|
mCoreSyncWaitFrameEnd(sync);
|
||||||
|
|
||||||
|
forceDraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PainterGL::forceDraw() {
|
void PainterGL::forceDraw() {
|
||||||
m_painter.begin(m_window);
|
m_painter.begin(m_window);
|
||||||
performDraw();
|
performDraw();
|
||||||
m_painter.end();
|
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;
|
||||||
|
}
|
||||||
|
m_delayTimer.restart();
|
||||||
|
}
|
||||||
m_backend->swap(m_backend);
|
m_backend->swap(m_backend);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -425,10 +432,6 @@ void PainterGL::stop() {
|
||||||
dequeueAll();
|
dequeueAll();
|
||||||
m_backend->clear(m_backend);
|
m_backend->clear(m_backend);
|
||||||
m_backend->swap(m_backend);
|
m_backend->swap(m_backend);
|
||||||
if (m_swapTimer.isActive()) {
|
|
||||||
swap();
|
|
||||||
m_swapTimer.stop();
|
|
||||||
}
|
|
||||||
if (m_videoProxy) {
|
if (m_videoProxy) {
|
||||||
m_videoProxy->reset();
|
m_videoProxy->reset();
|
||||||
}
|
}
|
||||||
|
@ -458,28 +461,6 @@ void PainterGL::performDraw() {
|
||||||
if (m_messagePainter) {
|
if (m_messagePainter) {
|
||||||
m_messagePainter->paint(&m_painter);
|
m_messagePainter->paint(&m_painter);
|
||||||
}
|
}
|
||||||
m_frameReady = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PainterGL::swap() {
|
|
||||||
if (!m_gl->isValid()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (m_frameReady) {
|
|
||||||
m_gl->swapBuffers(m_surface);
|
|
||||||
m_gl->makeCurrent(m_surface);
|
|
||||||
#if defined(_WIN32) && defined(USE_EPOXY)
|
|
||||||
epoxy_handle_external_wglMakeCurrent();
|
|
||||||
#endif
|
|
||||||
m_frameReady = false;
|
|
||||||
}
|
|
||||||
if (m_needsUnlock) {
|
|
||||||
mCoreSyncWaitFrameEnd(&m_context->thread()->impl->sync);
|
|
||||||
m_needsUnlock = false;
|
|
||||||
}
|
|
||||||
if (!m_queue.isEmpty()) {
|
|
||||||
QMetaObject::invokeMethod(this, "draw", Qt::QueuedConnection);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PainterGL::enqueue(const uint32_t* backing) {
|
void PainterGL::enqueue(const uint32_t* backing) {
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <QElapsedTimer>
|
||||||
#include <QOpenGLContext>
|
#include <QOpenGLContext>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
|
@ -108,9 +109,6 @@ public slots:
|
||||||
|
|
||||||
int glTex();
|
int glTex();
|
||||||
|
|
||||||
private slots:
|
|
||||||
void swap();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void performDraw();
|
void performDraw();
|
||||||
void dequeue();
|
void dequeue();
|
||||||
|
@ -131,9 +129,7 @@ private:
|
||||||
VideoBackend* m_backend = nullptr;
|
VideoBackend* m_backend = nullptr;
|
||||||
QSize m_size;
|
QSize m_size;
|
||||||
MessagePainter* m_messagePainter = nullptr;
|
MessagePainter* m_messagePainter = nullptr;
|
||||||
QTimer m_swapTimer{this};
|
QElapsedTimer m_delayTimer;
|
||||||
bool m_needsUnlock = false;
|
|
||||||
bool m_frameReady = false;
|
|
||||||
std::shared_ptr<VideoProxy> m_videoProxy;
|
std::shared_ptr<VideoProxy> m_videoProxy;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue