Qt: Always start painter thread even if not in use
Vicki Pfau vi@endrift.com
Thu, 03 Dec 2020 23:57:05 -0800
2 files changed,
54 insertions(+),
86 deletions(-)
M
src/platform/qt/DisplayGL.cpp
→
src/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.h
→
src/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;