all repos — mgba @ 2f7232292c79ddaefaef9db3b950b40720b3d6e2

mGBA Game Boy Advance Emulator

Qt: Always start painter thread even if not in use
Vicki Pfau vi@endrift.com
Thu, 03 Dec 2020 23:57:05 -0800
commit

2f7232292c79ddaefaef9db3b950b40720b3d6e2

parent

d44a26d96227b025031cc323bd8efe2aca7e7b30

2 files changed, 54 insertions(+), 86 deletions(-)

jump to
M src/platform/qt/DisplayGL.cppsrc/platform/qt/DisplayGL.cpp

@@ -51,10 +51,23 @@ setAttribute(Qt::WA_NativeWindow);

windowHandle()->create(); m_painter = std::make_unique<PainterGL>(windowHandle(), format); + m_drawThread.setObjectName("Painter Thread"); + m_painter->moveToThread(&m_drawThread); + + connect(&m_drawThread, &QThread::started, m_painter.get(), &PainterGL::create); + connect(m_painter.get(), &PainterGL::started, this, [this] { + m_hasStarted = true; + resizePainter(); + emit drawingStarted(); + }); + m_drawThread.start(); } DisplayGL::~DisplayGL() { stopDrawing(); + QMetaObject::invokeMethod(m_painter.get(), "destroy", Qt::BlockingQueuedConnection); + m_drawThread.exit(); + m_drawThread.wait(); } bool DisplayGL::supportsShaders() const {

@@ -63,48 +76,34 @@ }

VideoShader* DisplayGL::shaders() { VideoShader* shaders = nullptr; - if (m_drawThread) { - QMetaObject::invokeMethod(m_painter.get(), "shaders", Qt::BlockingQueuedConnection, Q_RETURN_ARG(VideoShader*, shaders)); - } else { - shaders = m_painter->shaders(); - } + QMetaObject::invokeMethod(m_painter.get(), "shaders", Qt::BlockingQueuedConnection, Q_RETURN_ARG(VideoShader*, shaders)); return shaders; } void DisplayGL::startDrawing(std::shared_ptr<CoreController> controller) { - if (m_drawThread) { + if (m_isDrawing) { return; } m_isDrawing = true; m_painter->setContext(controller); m_painter->setMessagePainter(messagePainter()); m_context = controller; - m_drawThread = new QThread(this); - m_drawThread->setObjectName("Painter Thread"); - m_painter->moveToThread(m_drawThread); if (videoProxy()) { - videoProxy()->moveToThread(m_drawThread); + videoProxy()->moveToThread(&m_drawThread); } - connect(m_drawThread, &QThread::started, m_painter.get(), &PainterGL::start); - connect(m_painter.get(), &PainterGL::started, this, [this] { - m_hasStarted = true; - resizePainter(); - emit drawingStarted(); - }); lockAspectRatio(isAspectRatioLocked()); lockIntegerScaling(isIntegerScalingLocked()); interframeBlending(hasInterframeBlending()); showOSDMessages(isShowOSD()); filter(isFiltered()); - - m_drawThread->start(); #if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)) messagePainter()->resize(size(), isAspectRatioLocked(), devicePixelRatioF()); #else messagePainter()->resize(size(), isAspectRatioLocked(), devicePixelRatio()); #endif + QMetaObject::invokeMethod(m_painter.get(), "start"); setUpdatesEnabled(false); }

@@ -147,21 +146,18 @@ return s_supports[format];

} void DisplayGL::stopDrawing() { - if (m_drawThread) { + if (m_hasStarted || m_isDrawing) { m_isDrawing = false; m_hasStarted = false; CoreController::Interrupter interrupter(m_context); QMetaObject::invokeMethod(m_painter.get(), "stop", Qt::BlockingQueuedConnection); - m_drawThread->exit(); - m_drawThread->wait(); - m_drawThread = nullptr; setUpdatesEnabled(true); } m_context.reset(); } void DisplayGL::pauseDrawing() { - if (m_drawThread) { + if (m_hasStarted) { m_isDrawing = false; CoreController::Interrupter interrupter(m_context); QMetaObject::invokeMethod(m_painter.get(), "pause", Qt::BlockingQueuedConnection);

@@ -172,7 +168,7 @@ }

} void DisplayGL::unpauseDrawing() { - if (m_drawThread) { + if (m_hasStarted) { m_isDrawing = true; CoreController::Interrupter interrupter(m_context); QMetaObject::invokeMethod(m_painter.get(), "unpause", Qt::BlockingQueuedConnection);

@@ -183,78 +179,59 @@ }

} void DisplayGL::forceDraw() { - if (m_drawThread) { + if (m_hasStarted) { QMetaObject::invokeMethod(m_painter.get(), "forceDraw"); } } void DisplayGL::lockAspectRatio(bool lock) { Display::lockAspectRatio(lock); - if (m_drawThread) { - QMetaObject::invokeMethod(m_painter.get(), "lockAspectRatio", Q_ARG(bool, lock)); - } + QMetaObject::invokeMethod(m_painter.get(), "lockAspectRatio", Q_ARG(bool, lock)); } void DisplayGL::lockIntegerScaling(bool lock) { Display::lockIntegerScaling(lock); - if (m_drawThread) { - QMetaObject::invokeMethod(m_painter.get(), "lockIntegerScaling", Q_ARG(bool, lock)); - } + QMetaObject::invokeMethod(m_painter.get(), "lockIntegerScaling", Q_ARG(bool, lock)); } void DisplayGL::interframeBlending(bool enable) { Display::interframeBlending(enable); - if (m_drawThread) { - QMetaObject::invokeMethod(m_painter.get(), "interframeBlending", Q_ARG(bool, enable)); - } + QMetaObject::invokeMethod(m_painter.get(), "interframeBlending", Q_ARG(bool, enable)); } void DisplayGL::showOSDMessages(bool enable) { Display::showOSDMessages(enable); - if (m_drawThread) { - QMetaObject::invokeMethod(m_painter.get(), "showOSD", Q_ARG(bool, enable)); - } + QMetaObject::invokeMethod(m_painter.get(), "showOSD", Q_ARG(bool, enable)); } void DisplayGL::filter(bool filter) { Display::filter(filter); - if (m_drawThread) { - QMetaObject::invokeMethod(m_painter.get(), "filter", Q_ARG(bool, filter)); - } + QMetaObject::invokeMethod(m_painter.get(), "filter", Q_ARG(bool, filter)); } void DisplayGL::framePosted() { - if (m_drawThread) { - m_painter->enqueue(m_context->drawContext()); - QMetaObject::invokeMethod(m_painter.get(), "draw"); - } + m_painter->enqueue(m_context->drawContext()); + QMetaObject::invokeMethod(m_painter.get(), "draw"); } void DisplayGL::setShaders(struct VDir* shaders) { - if (m_drawThread) { - QMetaObject::invokeMethod(m_painter.get(), "setShaders", Qt::BlockingQueuedConnection, Q_ARG(struct VDir*, shaders)); - } else { - m_painter->setShaders(shaders); - } + QMetaObject::invokeMethod(m_painter.get(), "setShaders", Qt::BlockingQueuedConnection, Q_ARG(struct VDir*, shaders)); } void DisplayGL::clearShaders() { - QMetaObject::invokeMethod(m_painter.get(), "clearShaders"); + QMetaObject::invokeMethod(m_painter.get(), "clearShaders", Qt::BlockingQueuedConnection); } void DisplayGL::resizeContext() { - if (m_drawThread) { - CoreController::Interrupter interrupter(m_context); - QMetaObject::invokeMethod(m_painter.get(), "resizeContext"); - } + QMetaObject::invokeMethod(m_painter.get(), "resizeContext"); } void DisplayGL::setVideoScale(int scale) { - if (m_drawThread) { + if (m_context) { CoreController::Interrupter interrupter(m_context); mCoreConfigSetIntValue(&m_context->thread()->core->config, "videoScale", scale); - QMetaObject::invokeMethod(m_painter.get(), "resizeContext"); } + QMetaObject::invokeMethod(m_painter.get(), "resizeContext"); } void DisplayGL::resizeEvent(QResizeEvent* event) {

@@ -263,15 +240,15 @@ resizePainter();

} void DisplayGL::resizePainter() { - if (m_drawThread && m_hasStarted) { + if (m_hasStarted) { QMetaObject::invokeMethod(m_painter.get(), "resize", Qt::BlockingQueuedConnection, Q_ARG(QSize, size())); } } void DisplayGL::setVideoProxy(std::shared_ptr<VideoProxy> proxy) { Display::setVideoProxy(proxy); - if (m_drawThread && proxy) { - proxy->moveToThread(m_drawThread); + if (proxy) { + proxy->moveToThread(&m_drawThread); } m_painter->setVideoProxy(proxy); }

@@ -361,15 +338,6 @@ if (!m_gl) {

return; } makeCurrent(); - if (m_context) { - if (m_videoProxy) { - m_videoProxy->detach(m_context.get()); - } - m_context->setFramebufferHandle(-1); - if (m_videoProxy) { - m_videoProxy->processData(); - } - } #ifdef BUILD_GLES2 if (m_shader.passes) { mGLES2ShaderFree(&m_shader);

@@ -394,6 +362,7 @@ return;

} if (m_started) { + CoreController::Interrupter interrupter(m_context); mCore* core = m_context->thread()->core; core->reloadConfigOption(core, "videoScale", NULL); }

@@ -440,9 +409,6 @@ }

} void PainterGL::start() { - if (!m_gl) { - create(); - } makeCurrent(); #ifdef BUILD_GLES2

@@ -510,16 +476,23 @@ void PainterGL::stop() {

m_active = false; m_started = false; dequeueAll(); - m_backend->clear(m_backend); - m_backend->swap(m_backend); - if (m_videoProxy) { - m_videoProxy->reset(); + if (m_context) { + if (m_videoProxy) { + m_videoProxy->detach(m_context.get()); + } + m_context->setFramebufferHandle(-1); + m_context.reset(); + if (m_videoProxy) { + m_videoProxy->processData(); + } } - destroy(); - moveToThread(m_surface->thread()); if (m_videoProxy) { + m_videoProxy->reset(); m_videoProxy->moveToThread(m_surface->thread()); + m_videoProxy.reset(); } + m_backend->clear(m_backend); + m_backend->swap(m_backend); } void PainterGL::pause() {

@@ -606,9 +579,6 @@ if (!supportsShaders()) {

return; } #ifdef BUILD_GLES2 - if (!m_started) { - return; // TODO - } if (m_shader.passes) { mGLES2ShaderDetach(reinterpret_cast<mGLES2Context*>(m_backend)); mGLES2ShaderFree(&m_shader);

@@ -623,9 +593,6 @@ if (!supportsShaders()) {

return; } #ifdef BUILD_GLES2 - if (!m_started) { - return; // TODO - } if (m_shader.passes) { mGLES2ShaderDetach(reinterpret_cast<mGLES2Context*>(m_backend)); mGLES2ShaderFree(&m_shader);
M src/platform/qt/DisplayGL.hsrc/platform/qt/DisplayGL.h

@@ -84,7 +84,7 @@

bool m_isDrawing = false; bool m_hasStarted = false; std::unique_ptr<PainterGL> m_painter; - QThread* m_drawThread = nullptr; + QThread m_drawThread; std::shared_ptr<CoreController> m_context; };

@@ -104,6 +104,9 @@

void setVideoProxy(std::shared_ptr<VideoProxy>); public slots: + void create(); + void destroy(); + void forceDraw(); void draw(); void start();

@@ -132,8 +135,6 @@ void makeCurrent();

void performDraw(); void dequeue(); void dequeueAll(); - void create(); - void destroy(); std::array<std::array<uint32_t, 0x100000>, 3> m_buffers; QList<uint32_t*> m_free;