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();
|
||||
|
||||
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();
|
||||
}
|
||||
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());
|
||||
|
@ -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));
|
||||
}
|
||||
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 @@ 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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue