From 025e909773a2761cad8a3954498fe800f6f94963 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Wed, 3 Oct 2018 23:03:33 +1000 Subject: [PATCH] GLContext: Use destructor instead of Shutdown() to cleanup Also uses the Initialize() method to make the context current. --- Source/Core/Common/GL/GLContext.cpp | 4 -- Source/Core/Common/GL/GLContext.h | 5 +- Source/Core/Common/GL/GLInterface/AGL.h | 5 +- Source/Core/Common/GL/GLInterface/AGL.mm | 31 +++++--- Source/Core/Common/GL/GLInterface/EGL.cpp | 42 ++++++----- Source/Core/Common/GL/GLInterface/EGL.h | 10 +-- .../Core/Common/GL/GLInterface/EGLAndroid.h | 2 +- Source/Core/Common/GL/GLInterface/EGLX11.cpp | 8 ++- Source/Core/Common/GL/GLInterface/EGLX11.h | 2 +- Source/Core/Common/GL/GLInterface/GLX.cpp | 25 ++++--- Source/Core/Common/GL/GLInterface/GLX.h | 7 +- Source/Core/Common/GL/GLInterface/WGL.cpp | 72 +++++++++---------- Source/Core/Common/GL/GLInterface/WGL.h | 5 +- Source/Core/VideoBackends/OGL/Render.cpp | 6 +- Source/Core/VideoBackends/OGL/main.cpp | 1 - .../VideoBackends/Software/SWOGLWindow.cpp | 12 +--- 16 files changed, 122 insertions(+), 115 deletions(-) diff --git a/Source/Core/Common/GL/GLContext.cpp b/Source/Core/Common/GL/GLContext.cpp index 90cb833302..23f0255cd3 100644 --- a/Source/Core/Common/GL/GLContext.cpp +++ b/Source/Core/Common/GL/GLContext.cpp @@ -50,10 +50,6 @@ bool GLContext::ClearCurrent() return false; } -void GLContext::Shutdown() -{ -} - void GLContext::Update() { } diff --git a/Source/Core/Common/GL/GLContext.h b/Source/Core/Common/GL/GLContext.h index 48e261bae7..376999e0ac 100644 --- a/Source/Core/Common/GL/GLContext.h +++ b/Source/Core/Common/GL/GLContext.h @@ -31,7 +31,6 @@ public: virtual bool IsHeadless() const; virtual std::unique_ptr CreateSharedContext(); - virtual void Shutdown(); virtual bool MakeCurrent(); virtual bool ClearCurrent(); @@ -44,7 +43,8 @@ public: virtual void* GetFuncAddress(const std::string& name); - // Creates an instance of GLInterface specific to the platform we are running on. + // Creates an instance of GLContext specific to the platform we are running on. + // If successful, the context is made current on the calling thread. static std::unique_ptr Create(const WindowSystemInfo& wsi, bool stereo = false, bool core = true); @@ -56,6 +56,5 @@ protected: // Window dimensions. u32 m_backbuffer_width = 0; u32 m_backbuffer_height = 0; - bool m_is_core_context = false; bool m_is_shared = false; }; diff --git a/Source/Core/Common/GL/GLInterface/AGL.h b/Source/Core/Common/GL/GLInterface/AGL.h index 5e4052caa8..59d0116954 100644 --- a/Source/Core/Common/GL/GLInterface/AGL.h +++ b/Source/Core/Common/GL/GLInterface/AGL.h @@ -14,13 +14,14 @@ struct NSView; #include "Common/GL/GLContext.h" -class GLContextAGL : public GLContext +class GLContextAGL final : public GLContext { public: + ~GLContextAGL() override; + bool IsHeadless() const override; std::unique_ptr CreateSharedContext() override; - void Shutdown() override; bool MakeCurrent() override; bool ClearCurrent() override; diff --git a/Source/Core/Common/GL/GLInterface/AGL.mm b/Source/Core/Common/GL/GLInterface/AGL.mm index 2cd0cb7f60..7216946dae 100644 --- a/Source/Core/Common/GL/GLInterface/AGL.mm +++ b/Source/Core/Common/GL/GLInterface/AGL.mm @@ -43,6 +43,20 @@ static bool AttachContextToView(NSOpenGLContext* context, NSView* view, u32* wid return true; } +GLContextAGL::~GLContextAGL() +{ + if ([NSOpenGLContext currentContext] == m_context) + [NSOpenGLContext clearCurrentContext]; + + if (m_context) + { + [m_context clearDrawable]; + [m_context release]; + } + if (m_pixel_format) + [m_pixel_format release]; +} + bool GLContextAGL::IsHeadless() const { return !m_view; @@ -83,7 +97,11 @@ bool GLContextAGL::Initialize(void* display_handle, void* window_handle, bool st m_view = static_cast(window_handle); m_opengl_mode = Mode::OpenGL; - return AttachContextToView(m_context, m_view, &m_backbuffer_width, &m_backbuffer_height); + if (!AttachContextToView(m_context, m_view, &m_backbuffer_width, &m_backbuffer_height)) + return false; + + [m_context makeCurrentContext]; + return true; } std::unique_ptr GLContextAGL::CreateSharedContext() @@ -100,6 +118,7 @@ std::unique_ptr GLContextAGL::CreateSharedContext() new_context->m_context = new_agl_context; new_context->m_pixel_format = m_pixel_format; [new_context->m_pixel_format retain]; + new_context->m_is_shared = true; return new_context; } @@ -115,16 +134,6 @@ bool GLContextAGL::ClearCurrent() return true; } -// Close backend -void GLContextAGL::Shutdown() -{ - [m_context clearDrawable]; - [m_context release]; - m_context = nil; - [m_pixel_format release]; - m_pixel_format = nil; -} - void GLContextAGL::Update() { if (!m_view) diff --git a/Source/Core/Common/GL/GLInterface/EGL.cpp b/Source/Core/Common/GL/GLInterface/EGL.cpp index 534bf82ec5..4af719de40 100644 --- a/Source/Core/Common/GL/GLInterface/EGL.cpp +++ b/Source/Core/Common/GL/GLInterface/EGL.cpp @@ -28,7 +28,11 @@ #define EGL_OPENGL_ES3_BIT_KHR 0x00000040 #endif /* EGL_KHR_create_context */ -GLContextEGL::~GLContextEGL() = default; +GLContextEGL::~GLContextEGL() +{ + DestroyWindowSurface(); + DestroyContext(); +} bool GLContextEGL::IsHeadless() const { @@ -162,7 +166,6 @@ bool GLContextEGL::Initialize(void* display_handle, void* window_handle, bool st m_host_display = display_handle; m_host_window = window_handle; m_egl_display = OpenEGLDisplay(); - m_is_core_context = core; if (!m_egl_display) { @@ -268,7 +271,6 @@ bool GLContextEGL::Initialize(void* display_handle, void* window_handle, bool st if (!m_egl_context) { - m_is_core_context = false; m_egl_context = eglCreateContext(m_egl_display, m_config, EGL_NO_CONTEXT, &ctx_attribs[0]); m_attribs = std::move(ctx_attribs); } @@ -284,7 +286,8 @@ bool GLContextEGL::Initialize(void* display_handle, void* window_handle, bool st ERROR_LOG(VIDEO, "Error: CreateWindowSurface failed 0x%04x", eglGetError()); return false; } - return true; + + return MakeCurrent(); } std::unique_ptr GLContextEGL::CreateSharedContext() @@ -303,7 +306,6 @@ std::unique_ptr GLContextEGL::CreateSharedContext() new_context->m_egl_context = new_egl_context; new_context->m_host_display = m_host_display; new_context->m_egl_display = m_egl_display; - new_context->m_is_core_context = m_is_core_context; new_context->m_config = m_config; new_context->m_supports_surfaceless = m_supports_surfaceless; new_context->m_is_shared = true; @@ -349,7 +351,12 @@ bool GLContextEGL::CreateWindowSurface() void GLContextEGL::DestroyWindowSurface() { - if (m_egl_surface != EGL_NO_SURFACE && !eglDestroySurface(m_egl_display, m_egl_surface)) + if (m_egl_surface == EGL_NO_SURFACE) + return; + + if (eglGetCurrentSurface(EGL_DRAW) == m_egl_surface) + eglMakeCurrent(m_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + if (!eglDestroySurface(m_egl_display, m_egl_surface)) NOTICE_LOG(VIDEO, "Could not destroy window surface."); m_egl_surface = EGL_NO_SURFACE; } @@ -374,18 +381,17 @@ bool GLContextEGL::ClearCurrent() } // Close backend -void GLContextEGL::Shutdown() +void GLContextEGL::DestroyContext() { - if (m_egl_context) - { - if (!eglMakeCurrent(m_egl_display, m_egl_surface, m_egl_surface, m_egl_context)) - NOTICE_LOG(VIDEO, "Could not release drawing context."); + if (!m_egl_context) + return; + + if (eglGetCurrentContext() == m_egl_context) eglMakeCurrent(m_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - if (!eglDestroyContext(m_egl_display, m_egl_context)) - NOTICE_LOG(VIDEO, "Could not destroy drawing context."); - DestroyWindowSurface(); - if (!m_is_shared && !eglTerminate(m_egl_display)) - NOTICE_LOG(VIDEO, "Could not destroy display connection."); - m_egl_context = nullptr; - } + if (!eglDestroyContext(m_egl_display, m_egl_context)) + NOTICE_LOG(VIDEO, "Could not destroy drawing context."); + if (!m_is_shared && !eglTerminate(m_egl_display)) + NOTICE_LOG(VIDEO, "Could not destroy display connection."); + m_egl_context = EGL_NO_CONTEXT; + m_egl_display = EGL_NO_DISPLAY; } diff --git a/Source/Core/Common/GL/GLInterface/EGL.h b/Source/Core/Common/GL/GLInterface/EGL.h index c20552f126..51dd3fda35 100644 --- a/Source/Core/Common/GL/GLInterface/EGL.h +++ b/Source/Core/Common/GL/GLInterface/EGL.h @@ -14,12 +14,11 @@ class GLContextEGL : public GLContext { public: - virtual ~GLContextEGL(); + virtual ~GLContextEGL() override; bool IsHeadless() const override; std::unique_ptr CreateSharedContext() override; - virtual void Shutdown() override; bool MakeCurrent() override; bool ClearCurrent() override; @@ -40,6 +39,7 @@ protected: bool CreateWindowSurface(); void DestroyWindowSurface(); void DetectMode(bool has_handle); + void DestroyContext(); void* m_host_display = nullptr; void* m_host_window = nullptr; @@ -48,7 +48,7 @@ protected: bool m_supports_surfaceless = false; std::vector m_attribs; - EGLSurface m_egl_surface; - EGLContext m_egl_context; - EGLDisplay m_egl_display; + EGLSurface m_egl_surface = EGL_NO_SURFACE; + EGLContext m_egl_context = EGL_NO_CONTEXT; + EGLDisplay m_egl_display = EGL_NO_DISPLAY; }; diff --git a/Source/Core/Common/GL/GLInterface/EGLAndroid.h b/Source/Core/Common/GL/GLInterface/EGLAndroid.h index 0139bae91c..f743f2fb32 100644 --- a/Source/Core/Common/GL/GLInterface/EGLAndroid.h +++ b/Source/Core/Common/GL/GLInterface/EGLAndroid.h @@ -6,7 +6,7 @@ #include "Common/GL/GLInterface/EGL.h" -class GLContextEGLAndroid : public GLContextEGL +class GLContextEGLAndroid final : public GLContextEGL { protected: EGLDisplay OpenEGLDisplay() override; diff --git a/Source/Core/Common/GL/GLInterface/EGLX11.cpp b/Source/Core/Common/GL/GLInterface/EGLX11.cpp index bc87769440..bd59033738 100644 --- a/Source/Core/Common/GL/GLInterface/EGLX11.cpp +++ b/Source/Core/Common/GL/GLInterface/EGLX11.cpp @@ -4,7 +4,13 @@ #include "Common/GL/GLInterface/EGLX11.h" -GLContextEGLX11::~GLContextEGLX11() = default; +GLContextEGLX11::~GLContextEGLX11() +{ + // The context must be destroyed before the window. + DestroyWindowSurface(); + DestroyContext(); + m_render_window.reset(); +} void GLContextEGLX11::Update() { diff --git a/Source/Core/Common/GL/GLInterface/EGLX11.h b/Source/Core/Common/GL/GLInterface/EGLX11.h index 6254d7ca0a..f4be040fae 100644 --- a/Source/Core/Common/GL/GLInterface/EGLX11.h +++ b/Source/Core/Common/GL/GLInterface/EGLX11.h @@ -9,7 +9,7 @@ #include "Common/GL/GLInterface/EGL.h" #include "Common/GL/GLX11Window.h" -class GLContextEGLX11 : public GLContextEGL +class GLContextEGLX11 final : public GLContextEGL { public: ~GLContextEGLX11() override; diff --git a/Source/Core/Common/GL/GLInterface/GLX.cpp b/Source/Core/Common/GL/GLInterface/GLX.cpp index 7a8e67f109..d74bccf8a4 100644 --- a/Source/Core/Common/GL/GLInterface/GLX.cpp +++ b/Source/Core/Common/GL/GLInterface/GLX.cpp @@ -30,9 +30,21 @@ static int ctxErrorHandler(Display* dpy, XErrorEvent* ev) return 0; } +GLContextGLX::~GLContextGLX() +{ + DestroyWindowSurface(); + if (m_context) + { + if (glXGetCurrentContext() == m_context) + glXMakeCurrent(m_display, None, nullptr); + + glXDestroyContext(m_display, m_context); + } +} + bool GLContextGLX::IsHeadless() const { - return m_render_window == nullptr; + return !m_render_window; } void GLContextGLX::SwapInterval(int Interval) @@ -202,7 +214,7 @@ bool GLContextGLX::Initialize(void* display_handle, void* window_handle, bool st XSetErrorHandler(oldHandler); m_opengl_mode = Mode::OpenGL; - return true; + return MakeCurrent(); } std::unique_ptr GLContextGLX::CreateSharedContext() @@ -227,6 +239,7 @@ std::unique_ptr GLContextGLX::CreateSharedContext() new_context->m_supports_pbuffer = m_supports_pbuffer; new_context->m_display = m_display; new_context->m_fbconfig = m_fbconfig; + new_context->m_is_shared = true; if (m_supports_pbuffer && !new_context->CreateWindowSurface(None)) { @@ -286,14 +299,6 @@ bool GLContextGLX::ClearCurrent() return glXMakeCurrent(m_display, None, nullptr); } -// Close backend -void GLContextGLX::Shutdown() -{ - DestroyWindowSurface(); - if (m_context) - glXDestroyContext(m_display, m_context); -} - void GLContextGLX::Update() { m_render_window->UpdateDimensions(); diff --git a/Source/Core/Common/GL/GLInterface/GLX.h b/Source/Core/Common/GL/GLInterface/GLX.h index 16443b706a..1b74e53f60 100644 --- a/Source/Core/Common/GL/GLInterface/GLX.h +++ b/Source/Core/Common/GL/GLInterface/GLX.h @@ -13,13 +13,14 @@ #include "Common/GL/GLContext.h" #include "Common/GL/GLX11Window.h" -class GLContextGLX : public GLContext +class GLContextGLX final : public GLContext { public: + ~GLContextGLX() override; + bool IsHeadless() const override; std::unique_ptr CreateSharedContext() override; - void Shutdown() override; bool MakeCurrent() override; bool ClearCurrent() override; @@ -38,7 +39,7 @@ protected: std::unique_ptr m_render_window; GLXDrawable m_drawable = {}; - GLXContext m_context = {}; + GLXContext m_context = nullptr; GLXFBConfig m_fbconfig = {}; bool m_supports_pbuffer = false; GLXPbufferSGIX m_pbuffer = 0; diff --git a/Source/Core/Common/GL/GLInterface/WGL.cpp b/Source/Core/Common/GL/GLInterface/WGL.cpp index 032657cf69..98b6bd5a3a 100644 --- a/Source/Core/Common/GL/GLInterface/WGL.cpp +++ b/Source/Core/Common/GL/GLInterface/WGL.cpp @@ -157,6 +157,39 @@ static void ClearWGLExtensionPointers() wglDestroyPbufferARB = nullptr; } +GLContextWGL::~GLContextWGL() +{ + if (m_rc) + { + if (wglGetCurrentContext() == m_rc && !wglMakeCurrent(m_dc, nullptr)) + NOTICE_LOG(VIDEO, "Could not release drawing context."); + + if (!wglDeleteContext(m_rc)) + ERROR_LOG(VIDEO, "Attempt to release rendering context failed."); + + m_rc = nullptr; + } + + if (m_dc) + { + if (m_pbuffer_handle) + { + wglReleasePbufferDCARB(static_cast(m_pbuffer_handle), m_dc); + m_dc = nullptr; + + wglDestroyPbufferARB(static_cast(m_pbuffer_handle)); + m_pbuffer_handle = nullptr; + } + else + { + if (!ReleaseDC(m_window_handle, m_dc)) + ERROR_LOG(VIDEO, "Attempt to release device context failed."); + + m_dc = nullptr; + } + } +} + bool GLContextWGL::IsHeadless() const { return !m_window_handle; @@ -295,7 +328,6 @@ bool GLContextWGL::Initialize(void* display_handle, void* window_handle, bool st { wglDeleteContext(m_rc); m_rc = core_context; - m_is_core_context = true; } else { @@ -303,7 +335,7 @@ bool GLContextWGL::Initialize(void* display_handle, void* window_handle, bool st } } - return true; + return MakeCurrent(); } std::unique_ptr GLContextWGL::CreateSharedContext() @@ -327,7 +359,7 @@ std::unique_ptr GLContextWGL::CreateSharedContext() context->m_dc = dc; context->m_rc = rc; context->m_opengl_mode = m_opengl_mode; - context->m_is_core_context = m_is_core_context; + context->m_is_shared = true; return context; } @@ -468,37 +500,3 @@ void GLContextWGL::Update() m_backbuffer_width = rcWindow.right - rcWindow.left; m_backbuffer_height = rcWindow.bottom - rcWindow.top; } - -// Close backend -void GLContextWGL::Shutdown() -{ - if (m_rc) - { - if (!wglMakeCurrent(m_dc, nullptr)) - NOTICE_LOG(VIDEO, "Could not release drawing context."); - - if (!wglDeleteContext(m_rc)) - ERROR_LOG(VIDEO, "Attempt to release rendering context failed."); - - m_rc = nullptr; - } - - if (m_dc) - { - if (m_pbuffer_handle) - { - wglReleasePbufferDCARB(static_cast(m_pbuffer_handle), m_dc); - m_dc = nullptr; - - wglDestroyPbufferARB(static_cast(m_pbuffer_handle)); - m_pbuffer_handle = nullptr; - } - else - { - if (!ReleaseDC(m_window_handle, m_dc)) - ERROR_LOG(VIDEO, "Attempt to release device context failed."); - - m_dc = nullptr; - } - } -} diff --git a/Source/Core/Common/GL/GLInterface/WGL.h b/Source/Core/Common/GL/GLInterface/WGL.h index 40d86ee6d0..9e3f9d86ef 100644 --- a/Source/Core/Common/GL/GLInterface/WGL.h +++ b/Source/Core/Common/GL/GLInterface/WGL.h @@ -8,16 +8,17 @@ #include #include "Common/GL/GLContext.h" -class GLContextWGL : public GLContext +class GLContextWGL final : public GLContext { public: + ~GLContextWGL(); + bool IsHeadless() const; std::unique_ptr CreateSharedContext() override; bool MakeCurrent() override; bool ClearCurrent() override; - void Shutdown() override; void Update() override; diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index b28df12c6a..360d4c2dcc 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -803,11 +803,7 @@ Renderer::Renderer(std::unique_ptr main_gl_context) ClearEFBCache(); } -Renderer::~Renderer() -{ - m_main_gl_context->ClearCurrent(); - m_main_gl_context->Shutdown(); -} +Renderer::~Renderer() = default; bool Renderer::IsHeadless() const { diff --git a/Source/Core/VideoBackends/OGL/main.cpp b/Source/Core/VideoBackends/OGL/main.cpp index 2c38986aa9..e087c39462 100644 --- a/Source/Core/VideoBackends/OGL/main.cpp +++ b/Source/Core/VideoBackends/OGL/main.cpp @@ -166,7 +166,6 @@ bool VideoBackend::Initialize(const WindowSystemInfo& wsi) if (!main_gl_context) return false; - main_gl_context->MakeCurrent(); if (!InitializeGLExtensions(main_gl_context.get()) || !FillBackendInfo()) return false; diff --git a/Source/Core/VideoBackends/Software/SWOGLWindow.cpp b/Source/Core/VideoBackends/Software/SWOGLWindow.cpp index 4936d1a13c..81216ff7ef 100644 --- a/Source/Core/VideoBackends/Software/SWOGLWindow.cpp +++ b/Source/Core/VideoBackends/Software/SWOGLWindow.cpp @@ -13,15 +13,7 @@ #include "VideoBackends/Software/SWTexture.h" SWOGLWindow::SWOGLWindow() = default; - -SWOGLWindow::~SWOGLWindow() -{ - if (m_gl_context) - { - m_gl_context->ClearCurrent(); - m_gl_context->Shutdown(); - } -} +SWOGLWindow::~SWOGLWindow() = default; std::unique_ptr SWOGLWindow::Create(const WindowSystemInfo& wsi) { @@ -46,8 +38,6 @@ bool SWOGLWindow::Initialize(const WindowSystemInfo& wsi) if (!m_gl_context) return false; - m_gl_context->MakeCurrent(); - // Init extension support. if (!GLExtensions::Init(m_gl_context.get())) {