Qt: Always start painter thread even if not in use

This commit is contained in:
Vicki Pfau 2020-12-03 23:57:05 -08:00
parent d44a26d962
commit 2f7232292c
2 changed files with 54 additions and 86 deletions

View File

@ -51,10 +51,23 @@ DisplayGL::DisplayGL(const QSurfaceFormat& format, QWidget* parent)
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,34 +76,21 @@ bool DisplayGL::supportsShaders() const {
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();
}
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());
@ -98,13 +98,12 @@ void DisplayGL::startDrawing(std::shared_ptr<CoreController> controller) {
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 @@ bool DisplayGL::supportsFormat(const QSurfaceFormat& 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::pauseDrawing() {
}
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::unpauseDrawing() {
}
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));
}
}
void DisplayGL::lockIntegerScaling(bool lock) {
Display::lockIntegerScaling(lock);
if (m_drawThread) {
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));
}
}
void DisplayGL::showOSDMessages(bool enable) {
Display::showOSDMessages(enable);
if (m_drawThread) {
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));
}
}
void DisplayGL::framePosted() {
if (m_drawThread) {
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);
}
}
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");
}
}
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 @@ void DisplayGL::resizeEvent(QResizeEvent* event) {
}
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 @@ void PainterGL::destroy() {
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 @@ void PainterGL::resizeContext() {
}
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::filter(bool filter) {
}
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_context) {
if (m_videoProxy) {
m_videoProxy->detach(m_context.get());
}
m_context->setFramebufferHandle(-1);
m_context.reset();
if (m_videoProxy) {
m_videoProxy->processData();
}
}
if (m_videoProxy) {
m_videoProxy->reset();
}
destroy();
moveToThread(m_surface->thread());
if (m_videoProxy) {
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 @@ void PainterGL::setShaders(struct VDir* dir) {
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 @@ void PainterGL::clearShaders() {
return;
}
#ifdef BUILD_GLES2
if (!m_started) {
return; // TODO
}
if (m_shader.passes) {
mGLES2ShaderDetach(reinterpret_cast<mGLES2Context*>(m_backend));
mGLES2ShaderFree(&m_shader);

View File

@ -84,7 +84,7 @@ private:
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 @@ public:
void setVideoProxy(std::shared_ptr<VideoProxy>);
public slots:
void create();
void destroy();
void forceDraw();
void draw();
void start();
@ -132,8 +135,6 @@ private:
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;