mirror of https://github.com/mgba-emu/mgba.git
Qt: Asynchronous drawing startup
This commit is contained in:
parent
74edd964da
commit
cb7f150cc2
|
@ -57,6 +57,7 @@ public:
|
|||
std::shared_ptr<VideoProxy> videoProxy() { return m_videoProxy; }
|
||||
|
||||
signals:
|
||||
void drawingStarted();
|
||||
void showCursor();
|
||||
void hideCursor();
|
||||
|
||||
|
|
|
@ -74,25 +74,32 @@ void DisplayGL::startDrawing(std::shared_ptr<CoreController> controller) {
|
|||
videoProxy()->moveToThread(m_drawThread);
|
||||
}
|
||||
connect(m_drawThread, &QThread::started, m_painter.get(), &PainterGL::start);
|
||||
m_drawThread->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
|
||||
resizePainter();
|
||||
setUpdatesEnabled(false);
|
||||
}
|
||||
|
||||
void DisplayGL::stopDrawing() {
|
||||
if (m_drawThread) {
|
||||
m_isDrawing = false;
|
||||
m_hasStarted = false;
|
||||
CoreController::Interrupter interrupter(m_context);
|
||||
QMetaObject::invokeMethod(m_painter.get(), "stop", Qt::BlockingQueuedConnection);
|
||||
m_drawThread->exit();
|
||||
|
@ -187,18 +194,16 @@ void DisplayGL::clearShaders() {
|
|||
|
||||
void DisplayGL::resizeContext() {
|
||||
if (m_drawThread) {
|
||||
m_isDrawing = false;
|
||||
CoreController::Interrupter interrupter(m_context);
|
||||
QMetaObject::invokeMethod(m_painter.get(), "resizeContext", Qt::BlockingQueuedConnection);
|
||||
QMetaObject::invokeMethod(m_painter.get(), "resizeContext");
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayGL::setVideoScale(int scale) {
|
||||
if (m_drawThread) {
|
||||
m_isDrawing = false;
|
||||
CoreController::Interrupter interrupter(m_context);
|
||||
mCoreConfigSetIntValue(&m_context->thread()->core->config, "videoScale", scale);
|
||||
QMetaObject::invokeMethod(m_painter.get(), "resizeContext", Qt::BlockingQueuedConnection);
|
||||
QMetaObject::invokeMethod(m_painter.get(), "resizeContext");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -208,7 +213,7 @@ void DisplayGL::resizeEvent(QResizeEvent* event) {
|
|||
}
|
||||
|
||||
void DisplayGL::resizePainter() {
|
||||
if (m_drawThread) {
|
||||
if (m_drawThread && m_hasStarted) {
|
||||
QMetaObject::invokeMethod(m_painter.get(), "resize", Qt::BlockingQueuedConnection, Q_ARG(QSize, size()));
|
||||
}
|
||||
}
|
||||
|
@ -240,15 +245,19 @@ PainterGL::~PainterGL() {
|
|||
}
|
||||
}
|
||||
|
||||
void PainterGL::create() {
|
||||
m_gl = std::make_unique<QOpenGLContext>();
|
||||
m_gl->setFormat(m_format);
|
||||
m_gl->create();
|
||||
|
||||
void PainterGL::makeCurrent() {
|
||||
m_gl->makeCurrent(m_surface);
|
||||
#if defined(_WIN32) && defined(USE_EPOXY)
|
||||
epoxy_handle_external_wglMakeCurrent();
|
||||
#endif
|
||||
}
|
||||
|
||||
void PainterGL::create() {
|
||||
m_gl = std::make_unique<QOpenGLContext>();
|
||||
m_gl->setFormat(m_format);
|
||||
m_gl->create();
|
||||
makeCurrent();
|
||||
|
||||
auto version = m_gl->format().version();
|
||||
QStringList extensions = QString(reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS))).split(' ');
|
||||
|
||||
|
@ -261,10 +270,11 @@ void PainterGL::create() {
|
|||
QSurfaceFormat newFormat(m_format);
|
||||
newFormat.setVersion(1, 4);
|
||||
forceVersion = 1;
|
||||
m_gl->doneCurrent();
|
||||
m_gl->setFormat(newFormat);
|
||||
m_gl->create();
|
||||
makeCurrent();
|
||||
}
|
||||
m_gl->makeCurrent(m_surface);
|
||||
|
||||
#ifdef BUILD_GL
|
||||
mGLContext* glBackend;
|
||||
|
@ -274,9 +284,6 @@ void PainterGL::create() {
|
|||
#endif
|
||||
|
||||
m_window = std::make_unique<QOpenGLPaintDevice>();
|
||||
#if defined(_WIN32) && defined(USE_EPOXY)
|
||||
epoxy_handle_external_wglMakeCurrent();
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_GLES2
|
||||
version = m_gl->format().version();
|
||||
|
@ -303,10 +310,7 @@ void PainterGL::create() {
|
|||
return;
|
||||
}
|
||||
painter->m_gl->swapBuffers(painter->m_surface);
|
||||
painter->m_gl->makeCurrent(painter->m_surface);
|
||||
#if defined(_WIN32) && defined(USE_EPOXY)
|
||||
epoxy_handle_external_wglMakeCurrent();
|
||||
#endif
|
||||
painter->makeCurrent();
|
||||
};
|
||||
|
||||
m_backend->init(m_backend, 0);
|
||||
|
@ -326,10 +330,7 @@ void PainterGL::destroy() {
|
|||
if (!m_gl) {
|
||||
return;
|
||||
}
|
||||
m_gl->makeCurrent(m_surface);
|
||||
#if defined(_WIN32) && defined(USE_EPOXY)
|
||||
epoxy_handle_external_wglMakeCurrent();
|
||||
#endif
|
||||
makeCurrent();
|
||||
if (m_context) {
|
||||
if (m_videoProxy) {
|
||||
m_videoProxy->detach(m_context.get());
|
||||
|
@ -412,10 +413,7 @@ void PainterGL::start() {
|
|||
if (!m_gl) {
|
||||
create();
|
||||
}
|
||||
m_gl->makeCurrent(m_surface);
|
||||
#if defined(_WIN32) && defined(USE_EPOXY)
|
||||
epoxy_handle_external_wglMakeCurrent();
|
||||
#endif
|
||||
makeCurrent();
|
||||
|
||||
#ifdef BUILD_GLES2
|
||||
if (m_supportsShaders && m_shader.passes) {
|
||||
|
@ -427,6 +425,7 @@ void PainterGL::start() {
|
|||
m_buffer = nullptr;
|
||||
m_active = true;
|
||||
m_started = true;
|
||||
emit started();
|
||||
}
|
||||
|
||||
void PainterGL::draw() {
|
||||
|
@ -559,21 +558,14 @@ void PainterGL::setShaders(struct VDir* dir) {
|
|||
}
|
||||
#ifdef BUILD_GLES2
|
||||
if (!m_started) {
|
||||
m_gl->makeCurrent(m_surface);
|
||||
#if defined(_WIN32) && defined(USE_EPOXY)
|
||||
epoxy_handle_external_wglMakeCurrent();
|
||||
#endif
|
||||
return; // TODO
|
||||
}
|
||||
if (m_shader.passes) {
|
||||
mGLES2ShaderDetach(reinterpret_cast<mGLES2Context*>(m_backend));
|
||||
mGLES2ShaderFree(&m_shader);
|
||||
}
|
||||
mGLES2ShaderLoad(&m_shader, dir);
|
||||
if (m_started) {
|
||||
mGLES2ShaderAttach(reinterpret_cast<mGLES2Context*>(m_backend), static_cast<mGLES2Shader*>(m_shader.passes), m_shader.nPasses);
|
||||
} else {
|
||||
m_gl->doneCurrent();
|
||||
}
|
||||
mGLES2ShaderAttach(reinterpret_cast<mGLES2Context*>(m_backend), static_cast<mGLES2Shader*>(m_shader.passes), m_shader.nPasses);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -583,18 +575,12 @@ void PainterGL::clearShaders() {
|
|||
}
|
||||
#ifdef BUILD_GLES2
|
||||
if (!m_started) {
|
||||
m_gl->makeCurrent(m_surface);
|
||||
#if defined(_WIN32) && defined(USE_EPOXY)
|
||||
epoxy_handle_external_wglMakeCurrent();
|
||||
#endif
|
||||
return; // TODO
|
||||
}
|
||||
if (m_shader.passes) {
|
||||
mGLES2ShaderDetach(reinterpret_cast<mGLES2Context*>(m_backend));
|
||||
mGLES2ShaderFree(&m_shader);
|
||||
}
|
||||
if (!m_started) {
|
||||
m_gl->doneCurrent();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -74,6 +74,7 @@ private:
|
|||
void resizePainter();
|
||||
|
||||
bool m_isDrawing = false;
|
||||
bool m_hasStarted = false;
|
||||
std::unique_ptr<PainterGL> m_painter;
|
||||
QThread* m_drawThread = nullptr;
|
||||
std::shared_ptr<CoreController> m_context;
|
||||
|
@ -115,7 +116,11 @@ public slots:
|
|||
|
||||
int glTex();
|
||||
|
||||
signals:
|
||||
void started();
|
||||
|
||||
private:
|
||||
void makeCurrent();
|
||||
void performDraw();
|
||||
void dequeue();
|
||||
void dequeueAll();
|
||||
|
|
|
@ -28,6 +28,7 @@ void DisplayQt::startDrawing(std::shared_ptr<CoreController> controller) {
|
|||
m_oldBacking = std::move(QImage());
|
||||
m_isDrawing = true;
|
||||
m_context = controller;
|
||||
emit drawingStarted();
|
||||
}
|
||||
|
||||
void DisplayQt::stopDrawing() {
|
||||
|
|
|
@ -831,7 +831,6 @@ void Window::gameStopped() {
|
|||
m_controller.reset();
|
||||
updateTitle();
|
||||
|
||||
m_display->setVideoProxy({});
|
||||
if (m_pendingClose) {
|
||||
m_display.reset();
|
||||
close();
|
||||
|
@ -919,7 +918,6 @@ void Window::reloadDisplayDriver() {
|
|||
attachDisplay();
|
||||
|
||||
attachWidget(m_display.get());
|
||||
m_display->startDrawing(m_controller);
|
||||
}
|
||||
#ifdef M_CORE_GB
|
||||
m_display->setMinimumSize(GB_VIDEO_HORIZONTAL_PIXELS, GB_VIDEO_VERTICAL_PIXELS);
|
||||
|
@ -964,6 +962,7 @@ void Window::changeRenderer() {
|
|||
int fb = m_display->framebufferHandle();
|
||||
if (fb >= 0) {
|
||||
m_controller->setFramebufferHandle(fb);
|
||||
m_config->updateOption("videoScale");
|
||||
}
|
||||
} else {
|
||||
m_controller->setFramebufferHandle(-1);
|
||||
|
@ -1828,7 +1827,6 @@ void Window::setController(CoreController* controller, const QString& fname) {
|
|||
m_inputController.recalibrateAxes();
|
||||
m_controller->setInputController(&m_inputController);
|
||||
m_controller->setLogger(&m_log);
|
||||
m_display->startDrawing(m_controller);
|
||||
|
||||
connect(this, &Window::shutdown, [this]() {
|
||||
if (!m_controller) {
|
||||
|
@ -1862,9 +1860,6 @@ void Window::setController(CoreController* controller, const QString& fname) {
|
|||
connect(m_controller.get(), &CoreController::unpaused, [this]() {
|
||||
emit paused(false);
|
||||
});
|
||||
|
||||
attachDisplay();
|
||||
|
||||
connect(m_controller.get(), &CoreController::unpaused, &m_inputController, &InputController::suspendScreensaver);
|
||||
connect(m_controller.get(), &CoreController::frameAvailable, this, &Window::recordFrame);
|
||||
connect(m_controller.get(), &CoreController::crashed, this, &Window::gameCrashed);
|
||||
|
@ -1906,6 +1901,7 @@ void Window::setController(CoreController* controller, const QString& fname) {
|
|||
m_pendingPatch = QString();
|
||||
}
|
||||
|
||||
attachDisplay();
|
||||
m_controller->loadConfig(m_config);
|
||||
m_controller->start();
|
||||
|
||||
|
@ -1929,7 +1925,8 @@ void Window::attachDisplay() {
|
|||
connect(m_controller.get(), &CoreController::frameAvailable, m_display.get(), &Display::framePosted);
|
||||
connect(m_controller.get(), &CoreController::statusPosted, m_display.get(), &Display::showMessage);
|
||||
connect(m_controller.get(), &CoreController::didReset, m_display.get(), &Display::resizeContext);
|
||||
changeRenderer();
|
||||
connect(m_display.get(), &Display::drawingStarted, this, &Window::changeRenderer);
|
||||
m_display->startDrawing(m_controller);
|
||||
}
|
||||
|
||||
void Window::setLogo() {
|
||||
|
|
|
@ -131,6 +131,7 @@ private slots:
|
|||
|
||||
void reloadAudioDriver();
|
||||
void reloadDisplayDriver();
|
||||
void attachDisplay();
|
||||
void changeRenderer();
|
||||
|
||||
void tryMakePortable();
|
||||
|
@ -159,7 +160,6 @@ private:
|
|||
void updateMRU();
|
||||
|
||||
void openView(QWidget* widget);
|
||||
void attachDisplay();
|
||||
|
||||
template <typename T, typename... A> std::function<void()> openTView(A... arg);
|
||||
template <typename T, typename... A> std::function<void()> openControllerTView(A... arg);
|
||||
|
|
Loading…
Reference in New Issue