Qt: Fix VideoProxy lifetime

This commit is contained in:
Vicki Pfau 2019-05-28 21:52:15 -07:00
parent 33d13b3757
commit fcb5a4168f
4 changed files with 33 additions and 18 deletions

View File

@ -49,9 +49,11 @@ public:
virtual bool isDrawing() const = 0; virtual bool isDrawing() const = 0;
virtual bool supportsShaders() const = 0; virtual bool supportsShaders() const = 0;
virtual VideoShader* shaders() = 0; virtual VideoShader* shaders() = 0;
virtual VideoProxy* videoProxy() { return nullptr; }
virtual int framebufferHandle() { return -1; } virtual int framebufferHandle() { return -1; }
virtual void setVideoProxy(std::shared_ptr<VideoProxy> proxy) { m_videoProxy = proxy; }
std::shared_ptr<VideoProxy> videoProxy() { return m_videoProxy; }
signals: signals:
void showCursor(); void showCursor();
void hideCursor(); void hideCursor();
@ -88,6 +90,7 @@ private:
bool m_interframeBlending = false; bool m_interframeBlending = false;
bool m_filter = false; bool m_filter = false;
QTimer m_mouseTimer; QTimer m_mouseTimer;
std::shared_ptr<VideoProxy> m_videoProxy;
}; };
} }

View File

@ -57,7 +57,7 @@ DisplayGL::DisplayGL(const QSurfaceFormat& format, QWidget* parent)
m_gl->create(); m_gl->create();
} }
m_painter = new PainterGL(&m_videoProxy, windowHandle(), m_gl); m_painter = new PainterGL(windowHandle(), m_gl);
setUpdatesEnabled(false); // Prevent paint events, which can cause race conditions setUpdatesEnabled(false); // Prevent paint events, which can cause race conditions
} }
@ -95,7 +95,9 @@ void DisplayGL::startDrawing(std::shared_ptr<CoreController> controller) {
m_gl->doneCurrent(); m_gl->doneCurrent();
m_gl->moveToThread(m_drawThread); m_gl->moveToThread(m_drawThread);
m_painter->moveToThread(m_drawThread); m_painter->moveToThread(m_drawThread);
m_videoProxy.moveToThread(m_drawThread); if (videoProxy()) {
videoProxy()->moveToThread(m_drawThread);
}
connect(m_drawThread, &QThread::started, m_painter, &PainterGL::start); connect(m_drawThread, &QThread::started, m_painter, &PainterGL::start);
m_drawThread->start(); m_drawThread->start();
@ -217,21 +219,21 @@ void DisplayGL::resizePainter() {
} }
} }
VideoProxy* DisplayGL::videoProxy() { void DisplayGL::setVideoProxy(std::shared_ptr<VideoProxy> proxy) {
if (supportsShaders()) { Display::setVideoProxy(proxy);
return &m_videoProxy; if (m_drawThread && proxy) {
proxy->moveToThread(m_drawThread);
} }
return nullptr; m_painter->setVideoProxy(proxy);
} }
int DisplayGL::framebufferHandle() { int DisplayGL::framebufferHandle() {
return m_painter->glTex(); return m_painter->glTex();
} }
PainterGL::PainterGL(VideoProxy* proxy, QWindow* surface, QOpenGLContext* parent) PainterGL::PainterGL(QWindow* surface, QOpenGLContext* parent)
: m_gl(parent) : m_gl(parent)
, m_surface(surface) , m_surface(surface)
, m_videoProxy(proxy)
{ {
#ifdef BUILD_GL #ifdef BUILD_GL
mGLContext* glBackend; mGLContext* glBackend;
@ -425,7 +427,9 @@ void PainterGL::stop() {
m_gl->moveToThread(m_surface->thread()); m_gl->moveToThread(m_surface->thread());
m_context.reset(); m_context.reset();
moveToThread(m_gl->thread()); moveToThread(m_gl->thread());
m_videoProxy->moveToThread(m_gl->thread()); if (m_videoProxy) {
m_videoProxy->moveToThread(m_gl->thread());
}
} }
void PainterGL::pause() { void PainterGL::pause() {
@ -516,6 +520,10 @@ void PainterGL::dequeueAll() {
m_mutex.unlock(); m_mutex.unlock();
} }
void PainterGL::setVideoProxy(std::shared_ptr<VideoProxy> proxy) {
m_videoProxy = proxy;
}
void PainterGL::setShaders(struct VDir* dir) { void PainterGL::setShaders(struct VDir* dir) {
if (!supportsShaders()) { if (!supportsShaders()) {
return; return;

View File

@ -42,7 +42,7 @@ public:
bool isDrawing() const override { return m_isDrawing; } bool isDrawing() const override { return m_isDrawing; }
bool supportsShaders() const override; bool supportsShaders() const override;
VideoShader* shaders() override; VideoShader* shaders() override;
VideoProxy* videoProxy() override; void setVideoProxy(std::shared_ptr<VideoProxy>) override;
int framebufferHandle() override; int framebufferHandle() override;
public slots: public slots:
@ -71,14 +71,13 @@ private:
PainterGL* m_painter; PainterGL* m_painter;
QThread* m_drawThread = nullptr; QThread* m_drawThread = nullptr;
std::shared_ptr<CoreController> m_context; std::shared_ptr<CoreController> m_context;
VideoProxy m_videoProxy;
}; };
class PainterGL : public QObject { class PainterGL : public QObject {
Q_OBJECT Q_OBJECT
public: public:
PainterGL(VideoProxy* proxy, QWindow* surface, QOpenGLContext* parent); PainterGL(QWindow* surface, QOpenGLContext* parent);
~PainterGL(); ~PainterGL();
void setContext(std::shared_ptr<CoreController>); void setContext(std::shared_ptr<CoreController>);
@ -87,6 +86,8 @@ public:
bool supportsShaders() const { return m_supportsShaders; } bool supportsShaders() const { return m_supportsShaders; }
void setVideoProxy(std::shared_ptr<VideoProxy>);
public slots: public slots:
void forceDraw(); void forceDraw();
void draw(); void draw();
@ -133,7 +134,7 @@ private:
QTimer m_swapTimer{this}; QTimer m_swapTimer{this};
bool m_needsUnlock = false; bool m_needsUnlock = false;
bool m_frameReady = false; bool m_frameReady = false;
VideoProxy* m_videoProxy; std::shared_ptr<VideoProxy> m_videoProxy;
}; };
} }

View File

@ -780,7 +780,6 @@ void Window::gameStarted() {
} }
void Window::gameStopped() { void Window::gameStopped() {
m_controller.reset();
#ifdef M_CORE_GBA #ifdef M_CORE_GBA
for (Action* action : m_platformActions) { for (Action* action : m_platformActions) {
action->setEnabled(true); action->setEnabled(true);
@ -816,6 +815,10 @@ void Window::gameStopped() {
m_audioProcessor.reset(); m_audioProcessor.reset();
} }
m_display->stopDrawing(); m_display->stopDrawing();
m_controller.reset();
m_display->setVideoProxy({});
if (m_pendingClose) { if (m_pendingClose) {
m_display.reset(); m_display.reset();
close(); close();
@ -1739,9 +1742,9 @@ void Window::setController(CoreController* controller, const QString& fname) {
} }
if (m_config->getOption("hwaccelVideo").toInt() && m_display->supportsShaders() && controller->supportsFeature(CoreController::Feature::OPENGL)) { if (m_config->getOption("hwaccelVideo").toInt() && m_display->supportsShaders() && controller->supportsFeature(CoreController::Feature::OPENGL)) {
if (m_display->videoProxy()) { std::shared_ptr<VideoProxy> proxy = std::make_shared<VideoProxy>();
m_display->videoProxy()->attach(controller); m_display->setVideoProxy(proxy);
} proxy->attach(controller);
int fb = m_display->framebufferHandle(); int fb = m_display->framebufferHandle();
if (fb >= 0) { if (fb >= 0) {