From 75504b3f5e5d60d43152f0ea255db069e96fad97 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Fri, 3 Nov 2017 20:43:11 +0300 Subject: [PATCH] rsx: Rework context handling and stop leaking the GL ccontext - GL contexts are external handles that require manual lifecycle management --- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 2 +- rpcs3/Emu/RSX/GSRender.cpp | 23 ++++++++++++----------- rpcs3/Emu/RSX/GSRender.h | 9 ++++----- rpcs3/rpcs3qt/gl_gs_frame.cpp | 16 +++++++++------- rpcs3/rpcs3qt/gl_gs_frame.h | 4 ++-- rpcs3/rpcs3qt/gs_frame.cpp | 4 ++-- rpcs3/rpcs3qt/gs_frame.h | 7 ++++--- 7 files changed, 34 insertions(+), 31 deletions(-) diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 33867d09dd..ce27833442 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -836,7 +836,7 @@ void GLGSRender::on_exit() glDeleteQueries(1, &query.handle); } - return GSRender::on_exit(); + GSRender::on_exit(); } void GLGSRender::clear_surface(u32 arg) diff --git a/rpcs3/Emu/RSX/GSRender.cpp b/rpcs3/Emu/RSX/GSRender.cpp index 86f1e33f4c..0969294a72 100644 --- a/rpcs3/Emu/RSX/GSRender.cpp +++ b/rpcs3/Emu/RSX/GSRender.cpp @@ -4,16 +4,6 @@ #include "GSRender.h" -draw_context_t GSFrameBase::new_context() -{ - if (void* context = make_context()) - { - return std::shared_ptr(context, [this](void* ctxt) { delete_context(ctxt); }); - } - - return nullptr; -} - GSRender::GSRender() { m_frame = Emu.GetCallbacks().get_gs_frame().release(); @@ -42,11 +32,22 @@ void GSRender::on_init_thread() { if (m_frame) { - m_context = m_frame->new_context(); + m_context = m_frame->make_context(); m_frame->set_current(m_context); } } +void GSRender::on_exit() +{ + if (m_frame) + { + m_frame->delete_context(m_context); + m_context = nullptr; + } + + rsx::thread::on_exit(); +} + void GSRender::flip(int buffer) { if (m_frame) diff --git a/rpcs3/Emu/RSX/GSRender.h b/rpcs3/Emu/RSX/GSRender.h index ebac990b37..c5cee1429a 100644 --- a/rpcs3/Emu/RSX/GSRender.h +++ b/rpcs3/Emu/RSX/GSRender.h @@ -32,7 +32,7 @@ enum wm_event using RSXDebuggerPrograms = std::vector; -using draw_context_t = std::shared_ptr; +using draw_context_t = void*; class GSFrameBase { @@ -45,8 +45,8 @@ public: virtual void hide() = 0; virtual void show() = 0; - draw_context_t new_context(); - + virtual void delete_context(draw_context_t ctx) = 0; + virtual draw_context_t make_context() = 0; virtual void set_current(draw_context_t ctx) = 0; virtual void flip(draw_context_t ctx, bool skip_frame=false) = 0; virtual int client_width() = 0; @@ -55,8 +55,6 @@ public: virtual void* handle() const = 0; protected: - virtual void delete_context(void* ctx) = 0; - virtual void* make_context() = 0; //window manager event management wm_event m_raised_event; @@ -111,6 +109,7 @@ public: void on_init_rsx() override; void on_init_thread() override; + void on_exit() override; void flip(int buffer) override; }; diff --git a/rpcs3/rpcs3qt/gl_gs_frame.cpp b/rpcs3/rpcs3qt/gl_gs_frame.cpp index f3ec3c58e1..a373871654 100644 --- a/rpcs3/rpcs3qt/gl_gs_frame.cpp +++ b/rpcs3/rpcs3qt/gl_gs_frame.cpp @@ -22,7 +22,7 @@ gl_gs_frame::gl_gs_frame(int w, int h, QIcon appIcon, bool disableMouse) setFormat(m_format); } -void* gl_gs_frame::make_context() +draw_context_t gl_gs_frame::make_context() { auto context = new QOpenGLContext(); context->setFormat(m_format); @@ -33,16 +33,18 @@ void* gl_gs_frame::make_context() void gl_gs_frame::set_current(draw_context_t ctx) { - if (!((QOpenGLContext*)ctx.get())->makeCurrent(this)) + if (!((QOpenGLContext*)ctx)->makeCurrent(this)) { create(); - ((QOpenGLContext*)ctx.get())->makeCurrent(this); + ((QOpenGLContext*)ctx)->makeCurrent(this); } } -void gl_gs_frame::delete_context(void* ctx) +void gl_gs_frame::delete_context(draw_context_t ctx) { - ((QOpenGLContext*)ctx)->deleteLater(); + auto gl_ctx = (QOpenGLContext*)ctx; + gl_ctx->doneCurrent(); + delete gl_ctx; } void gl_gs_frame::flip(draw_context_t context, bool skip_frame) @@ -52,6 +54,6 @@ void gl_gs_frame::flip(draw_context_t context, bool skip_frame) //Do not swap buffers if frame skip is active if (skip_frame) return; - ((QOpenGLContext*)context.get())->makeCurrent(this); - ((QOpenGLContext*)context.get())->swapBuffers(this); + ((QOpenGLContext*)context)->makeCurrent(this); + ((QOpenGLContext*)context)->swapBuffers(this); } diff --git a/rpcs3/rpcs3qt/gl_gs_frame.h b/rpcs3/rpcs3qt/gl_gs_frame.h index 239225d04e..6d01af4d80 100644 --- a/rpcs3/rpcs3qt/gl_gs_frame.h +++ b/rpcs3/rpcs3qt/gl_gs_frame.h @@ -11,8 +11,8 @@ private: public: gl_gs_frame(int w, int h, QIcon appIcon, bool disableMouse); - void* make_context() override; + draw_context_t make_context() override; void set_current(draw_context_t context) override; - void delete_context(void* context) override; + void delete_context(draw_context_t context) override; void flip(draw_context_t context, bool skip_frame=false) override; }; diff --git a/rpcs3/rpcs3qt/gs_frame.cpp b/rpcs3/rpcs3qt/gs_frame.cpp index 2a189e774b..06406da00b 100644 --- a/rpcs3/rpcs3qt/gs_frame.cpp +++ b/rpcs3/rpcs3qt/gs_frame.cpp @@ -154,7 +154,7 @@ void* gs_frame::handle() const #endif } -void* gs_frame::make_context() +draw_context_t gs_frame::make_context() { return nullptr; } @@ -164,7 +164,7 @@ void gs_frame::set_current(draw_context_t ctx) Q_UNUSED(ctx); } -void gs_frame::delete_context(void* ctx) +void gs_frame::delete_context(draw_context_t ctx) { Q_UNUSED(ctx); } diff --git a/rpcs3/rpcs3qt/gs_frame.h b/rpcs3/rpcs3qt/gs_frame.h index 06517c92d0..4f30e447b8 100644 --- a/rpcs3/rpcs3qt/gs_frame.h +++ b/rpcs3/rpcs3qt/gs_frame.h @@ -22,6 +22,10 @@ class gs_frame : public QWindow, public GSFrameBase public: gs_frame(const QString& title, int w, int h, QIcon appIcon, bool disableMouse); + draw_context_t make_context() override; + void set_current(draw_context_t context) override; + void delete_context(draw_context_t context) override; + wm_event get_default_wm_event() const override; protected: virtual void paintEvent(QPaintEvent *event); @@ -38,9 +42,6 @@ protected: void* handle() const override; - void* make_context() override; - void set_current(draw_context_t context) override; - void delete_context(void* context) override; void flip(draw_context_t context, bool skip_frame=false) override; int client_width() override; int client_height() override;