mirror of https://github.com/mgba-emu/mgba.git
Qt: Always start painter thread even if not in use
This commit is contained in:
parent
d44a26d962
commit
2f7232292c
|
@ -51,10 +51,23 @@ DisplayGL::DisplayGL(const QSurfaceFormat& format, QWidget* parent)
|
||||||
windowHandle()->create();
|
windowHandle()->create();
|
||||||
|
|
||||||
m_painter = std::make_unique<PainterGL>(windowHandle(), format);
|
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() {
|
DisplayGL::~DisplayGL() {
|
||||||
stopDrawing();
|
stopDrawing();
|
||||||
|
QMetaObject::invokeMethod(m_painter.get(), "destroy", Qt::BlockingQueuedConnection);
|
||||||
|
m_drawThread.exit();
|
||||||
|
m_drawThread.wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DisplayGL::supportsShaders() const {
|
bool DisplayGL::supportsShaders() const {
|
||||||
|
@ -63,34 +76,21 @@ bool DisplayGL::supportsShaders() const {
|
||||||
|
|
||||||
VideoShader* DisplayGL::shaders() {
|
VideoShader* DisplayGL::shaders() {
|
||||||
VideoShader* shaders = nullptr;
|
VideoShader* shaders = nullptr;
|
||||||
if (m_drawThread) {
|
|
||||||
QMetaObject::invokeMethod(m_painter.get(), "shaders", Qt::BlockingQueuedConnection, Q_RETURN_ARG(VideoShader*, shaders));
|
QMetaObject::invokeMethod(m_painter.get(), "shaders", Qt::BlockingQueuedConnection, Q_RETURN_ARG(VideoShader*, shaders));
|
||||||
} else {
|
|
||||||
shaders = m_painter->shaders();
|
|
||||||
}
|
|
||||||
return shaders;
|
return shaders;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisplayGL::startDrawing(std::shared_ptr<CoreController> controller) {
|
void DisplayGL::startDrawing(std::shared_ptr<CoreController> controller) {
|
||||||
if (m_drawThread) {
|
if (m_isDrawing) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_isDrawing = true;
|
m_isDrawing = true;
|
||||||
m_painter->setContext(controller);
|
m_painter->setContext(controller);
|
||||||
m_painter->setMessagePainter(messagePainter());
|
m_painter->setMessagePainter(messagePainter());
|
||||||
m_context = controller;
|
m_context = controller;
|
||||||
m_drawThread = new QThread(this);
|
|
||||||
m_drawThread->setObjectName("Painter Thread");
|
|
||||||
m_painter->moveToThread(m_drawThread);
|
|
||||||
if (videoProxy()) {
|
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());
|
lockAspectRatio(isAspectRatioLocked());
|
||||||
lockIntegerScaling(isIntegerScalingLocked());
|
lockIntegerScaling(isIntegerScalingLocked());
|
||||||
|
@ -98,13 +98,12 @@ void DisplayGL::startDrawing(std::shared_ptr<CoreController> controller) {
|
||||||
showOSDMessages(isShowOSD());
|
showOSDMessages(isShowOSD());
|
||||||
filter(isFiltered());
|
filter(isFiltered());
|
||||||
|
|
||||||
m_drawThread->start();
|
|
||||||
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
|
||||||
messagePainter()->resize(size(), isAspectRatioLocked(), devicePixelRatioF());
|
messagePainter()->resize(size(), isAspectRatioLocked(), devicePixelRatioF());
|
||||||
#else
|
#else
|
||||||
messagePainter()->resize(size(), isAspectRatioLocked(), devicePixelRatio());
|
messagePainter()->resize(size(), isAspectRatioLocked(), devicePixelRatio());
|
||||||
#endif
|
#endif
|
||||||
|
QMetaObject::invokeMethod(m_painter.get(), "start");
|
||||||
setUpdatesEnabled(false);
|
setUpdatesEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,21 +146,18 @@ bool DisplayGL::supportsFormat(const QSurfaceFormat& format) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisplayGL::stopDrawing() {
|
void DisplayGL::stopDrawing() {
|
||||||
if (m_drawThread) {
|
if (m_hasStarted || m_isDrawing) {
|
||||||
m_isDrawing = false;
|
m_isDrawing = false;
|
||||||
m_hasStarted = false;
|
m_hasStarted = false;
|
||||||
CoreController::Interrupter interrupter(m_context);
|
CoreController::Interrupter interrupter(m_context);
|
||||||
QMetaObject::invokeMethod(m_painter.get(), "stop", Qt::BlockingQueuedConnection);
|
QMetaObject::invokeMethod(m_painter.get(), "stop", Qt::BlockingQueuedConnection);
|
||||||
m_drawThread->exit();
|
|
||||||
m_drawThread->wait();
|
|
||||||
m_drawThread = nullptr;
|
|
||||||
setUpdatesEnabled(true);
|
setUpdatesEnabled(true);
|
||||||
}
|
}
|
||||||
m_context.reset();
|
m_context.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisplayGL::pauseDrawing() {
|
void DisplayGL::pauseDrawing() {
|
||||||
if (m_drawThread) {
|
if (m_hasStarted) {
|
||||||
m_isDrawing = false;
|
m_isDrawing = false;
|
||||||
CoreController::Interrupter interrupter(m_context);
|
CoreController::Interrupter interrupter(m_context);
|
||||||
QMetaObject::invokeMethod(m_painter.get(), "pause", Qt::BlockingQueuedConnection);
|
QMetaObject::invokeMethod(m_painter.get(), "pause", Qt::BlockingQueuedConnection);
|
||||||
|
@ -172,7 +168,7 @@ void DisplayGL::pauseDrawing() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisplayGL::unpauseDrawing() {
|
void DisplayGL::unpauseDrawing() {
|
||||||
if (m_drawThread) {
|
if (m_hasStarted) {
|
||||||
m_isDrawing = true;
|
m_isDrawing = true;
|
||||||
CoreController::Interrupter interrupter(m_context);
|
CoreController::Interrupter interrupter(m_context);
|
||||||
QMetaObject::invokeMethod(m_painter.get(), "unpause", Qt::BlockingQueuedConnection);
|
QMetaObject::invokeMethod(m_painter.get(), "unpause", Qt::BlockingQueuedConnection);
|
||||||
|
@ -183,78 +179,59 @@ void DisplayGL::unpauseDrawing() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisplayGL::forceDraw() {
|
void DisplayGL::forceDraw() {
|
||||||
if (m_drawThread) {
|
if (m_hasStarted) {
|
||||||
QMetaObject::invokeMethod(m_painter.get(), "forceDraw");
|
QMetaObject::invokeMethod(m_painter.get(), "forceDraw");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisplayGL::lockAspectRatio(bool lock) {
|
void DisplayGL::lockAspectRatio(bool lock) {
|
||||||
Display::lockAspectRatio(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) {
|
void DisplayGL::lockIntegerScaling(bool lock) {
|
||||||
Display::lockIntegerScaling(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) {
|
void DisplayGL::interframeBlending(bool enable) {
|
||||||
Display::interframeBlending(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) {
|
void DisplayGL::showOSDMessages(bool enable) {
|
||||||
Display::showOSDMessages(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) {
|
void DisplayGL::filter(bool filter) {
|
||||||
Display::filter(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() {
|
void DisplayGL::framePosted() {
|
||||||
if (m_drawThread) {
|
|
||||||
m_painter->enqueue(m_context->drawContext());
|
m_painter->enqueue(m_context->drawContext());
|
||||||
QMetaObject::invokeMethod(m_painter.get(), "draw");
|
QMetaObject::invokeMethod(m_painter.get(), "draw");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void DisplayGL::setShaders(struct VDir* shaders) {
|
void DisplayGL::setShaders(struct VDir* shaders) {
|
||||||
if (m_drawThread) {
|
|
||||||
QMetaObject::invokeMethod(m_painter.get(), "setShaders", Qt::BlockingQueuedConnection, Q_ARG(struct VDir*, shaders));
|
QMetaObject::invokeMethod(m_painter.get(), "setShaders", Qt::BlockingQueuedConnection, Q_ARG(struct VDir*, shaders));
|
||||||
} else {
|
|
||||||
m_painter->setShaders(shaders);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisplayGL::clearShaders() {
|
void DisplayGL::clearShaders() {
|
||||||
QMetaObject::invokeMethod(m_painter.get(), "clearShaders");
|
QMetaObject::invokeMethod(m_painter.get(), "clearShaders", Qt::BlockingQueuedConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisplayGL::resizeContext() {
|
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) {
|
void DisplayGL::setVideoScale(int scale) {
|
||||||
if (m_drawThread) {
|
if (m_context) {
|
||||||
CoreController::Interrupter interrupter(m_context);
|
CoreController::Interrupter interrupter(m_context);
|
||||||
mCoreConfigSetIntValue(&m_context->thread()->core->config, "videoScale", scale);
|
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) {
|
void DisplayGL::resizeEvent(QResizeEvent* event) {
|
||||||
|
@ -263,15 +240,15 @@ void DisplayGL::resizeEvent(QResizeEvent* event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisplayGL::resizePainter() {
|
void DisplayGL::resizePainter() {
|
||||||
if (m_drawThread && m_hasStarted) {
|
if (m_hasStarted) {
|
||||||
QMetaObject::invokeMethod(m_painter.get(), "resize", Qt::BlockingQueuedConnection, Q_ARG(QSize, size()));
|
QMetaObject::invokeMethod(m_painter.get(), "resize", Qt::BlockingQueuedConnection, Q_ARG(QSize, size()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisplayGL::setVideoProxy(std::shared_ptr<VideoProxy> proxy) {
|
void DisplayGL::setVideoProxy(std::shared_ptr<VideoProxy> proxy) {
|
||||||
Display::setVideoProxy(proxy);
|
Display::setVideoProxy(proxy);
|
||||||
if (m_drawThread && proxy) {
|
if (proxy) {
|
||||||
proxy->moveToThread(m_drawThread);
|
proxy->moveToThread(&m_drawThread);
|
||||||
}
|
}
|
||||||
m_painter->setVideoProxy(proxy);
|
m_painter->setVideoProxy(proxy);
|
||||||
}
|
}
|
||||||
|
@ -361,15 +338,6 @@ void PainterGL::destroy() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
makeCurrent();
|
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
|
#ifdef BUILD_GLES2
|
||||||
if (m_shader.passes) {
|
if (m_shader.passes) {
|
||||||
mGLES2ShaderFree(&m_shader);
|
mGLES2ShaderFree(&m_shader);
|
||||||
|
@ -394,6 +362,7 @@ void PainterGL::resizeContext() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_started) {
|
if (m_started) {
|
||||||
|
CoreController::Interrupter interrupter(m_context);
|
||||||
mCore* core = m_context->thread()->core;
|
mCore* core = m_context->thread()->core;
|
||||||
core->reloadConfigOption(core, "videoScale", NULL);
|
core->reloadConfigOption(core, "videoScale", NULL);
|
||||||
}
|
}
|
||||||
|
@ -440,9 +409,6 @@ void PainterGL::filter(bool filter) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PainterGL::start() {
|
void PainterGL::start() {
|
||||||
if (!m_gl) {
|
|
||||||
create();
|
|
||||||
}
|
|
||||||
makeCurrent();
|
makeCurrent();
|
||||||
|
|
||||||
#ifdef BUILD_GLES2
|
#ifdef BUILD_GLES2
|
||||||
|
@ -510,16 +476,23 @@ void PainterGL::stop() {
|
||||||
m_active = false;
|
m_active = false;
|
||||||
m_started = false;
|
m_started = false;
|
||||||
dequeueAll();
|
dequeueAll();
|
||||||
m_backend->clear(m_backend);
|
if (m_context) {
|
||||||
m_backend->swap(m_backend);
|
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) {
|
if (m_videoProxy) {
|
||||||
m_videoProxy->reset();
|
m_videoProxy->reset();
|
||||||
}
|
|
||||||
destroy();
|
|
||||||
moveToThread(m_surface->thread());
|
|
||||||
if (m_videoProxy) {
|
|
||||||
m_videoProxy->moveToThread(m_surface->thread());
|
m_videoProxy->moveToThread(m_surface->thread());
|
||||||
|
m_videoProxy.reset();
|
||||||
}
|
}
|
||||||
|
m_backend->clear(m_backend);
|
||||||
|
m_backend->swap(m_backend);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PainterGL::pause() {
|
void PainterGL::pause() {
|
||||||
|
@ -606,9 +579,6 @@ void PainterGL::setShaders(struct VDir* dir) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#ifdef BUILD_GLES2
|
#ifdef BUILD_GLES2
|
||||||
if (!m_started) {
|
|
||||||
return; // TODO
|
|
||||||
}
|
|
||||||
if (m_shader.passes) {
|
if (m_shader.passes) {
|
||||||
mGLES2ShaderDetach(reinterpret_cast<mGLES2Context*>(m_backend));
|
mGLES2ShaderDetach(reinterpret_cast<mGLES2Context*>(m_backend));
|
||||||
mGLES2ShaderFree(&m_shader);
|
mGLES2ShaderFree(&m_shader);
|
||||||
|
@ -623,9 +593,6 @@ void PainterGL::clearShaders() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#ifdef BUILD_GLES2
|
#ifdef BUILD_GLES2
|
||||||
if (!m_started) {
|
|
||||||
return; // TODO
|
|
||||||
}
|
|
||||||
if (m_shader.passes) {
|
if (m_shader.passes) {
|
||||||
mGLES2ShaderDetach(reinterpret_cast<mGLES2Context*>(m_backend));
|
mGLES2ShaderDetach(reinterpret_cast<mGLES2Context*>(m_backend));
|
||||||
mGLES2ShaderFree(&m_shader);
|
mGLES2ShaderFree(&m_shader);
|
||||||
|
|
|
@ -84,7 +84,7 @@ private:
|
||||||
bool m_isDrawing = false;
|
bool m_isDrawing = false;
|
||||||
bool m_hasStarted = false;
|
bool m_hasStarted = false;
|
||||||
std::unique_ptr<PainterGL> m_painter;
|
std::unique_ptr<PainterGL> m_painter;
|
||||||
QThread* m_drawThread = nullptr;
|
QThread m_drawThread;
|
||||||
std::shared_ptr<CoreController> m_context;
|
std::shared_ptr<CoreController> m_context;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -104,6 +104,9 @@ public:
|
||||||
void setVideoProxy(std::shared_ptr<VideoProxy>);
|
void setVideoProxy(std::shared_ptr<VideoProxy>);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
void create();
|
||||||
|
void destroy();
|
||||||
|
|
||||||
void forceDraw();
|
void forceDraw();
|
||||||
void draw();
|
void draw();
|
||||||
void start();
|
void start();
|
||||||
|
@ -132,8 +135,6 @@ private:
|
||||||
void performDraw();
|
void performDraw();
|
||||||
void dequeue();
|
void dequeue();
|
||||||
void dequeueAll();
|
void dequeueAll();
|
||||||
void create();
|
|
||||||
void destroy();
|
|
||||||
|
|
||||||
std::array<std::array<uint32_t, 0x100000>, 3> m_buffers;
|
std::array<std::array<uint32_t, 0x100000>, 3> m_buffers;
|
||||||
QList<uint32_t*> m_free;
|
QList<uint32_t*> m_free;
|
||||||
|
|
Loading…
Reference in New Issue