diff --git a/3d-viewer/3d_canvas/eda_3d_canvas.cpp b/3d-viewer/3d_canvas/eda_3d_canvas.cpp index 0214ac0999..791d888a4b 100644 --- a/3d-viewer/3d_canvas/eda_3d_canvas.cpp +++ b/3d-viewer/3d_canvas/eda_3d_canvas.cpp @@ -187,7 +187,8 @@ void EDA_3D_CANVAS::releaseOpenGL() { if( m_glRC ) { - GL_CONTEXT_MANAGER::Get().LockCtx( m_glRC, this ); + GL_CONTEXT_MANAGER* gl_mgr = Pgm().GetGLContextManager(); + gl_mgr->LockCtx( m_glRC, this ); delete m_3d_render_raytracing; m_3d_render_raytracing = nullptr; @@ -198,8 +199,8 @@ void EDA_3D_CANVAS::releaseOpenGL() // This is just a copy of a pointer, can safely be set to NULL. m_3d_render = nullptr; - GL_CONTEXT_MANAGER::Get().UnlockCtx( m_glRC ); - GL_CONTEXT_MANAGER::Get().DestroyCtx( m_glRC ); + gl_mgr->UnlockCtx( m_glRC ); + gl_mgr->DestroyCtx( m_glRC ); m_glRC = nullptr; } } @@ -379,10 +380,11 @@ void EDA_3D_CANVAS::DoRePaint() if( !GetParent()->GetParent()->IsShownOnScreen() ) return; // The parent board editor frame is no more alive - wxString err_messages; - INFOBAR_REPORTER warningReporter( m_parentInfoBar ); - STATUSBAR_REPORTER activityReporter( m_parentStatusBar, EDA_3D_VIEWER_STATUSBAR::ACTIVITY ); - int64_t start_time = GetRunningMicroSecs(); + wxString err_messages; + INFOBAR_REPORTER warningReporter( m_parentInfoBar ); + STATUSBAR_REPORTER activityReporter( m_parentStatusBar, EDA_3D_VIEWER_STATUSBAR::ACTIVITY ); + int64_t start_time = GetRunningMicroSecs(); + GL_CONTEXT_MANAGER* gl_mgr = Pgm().GetGLContextManager(); // "Makes the OpenGL state that is represented by the OpenGL rendering // context context current, i.e. it will be used by all subsequent OpenGL calls. @@ -390,7 +392,7 @@ void EDA_3D_CANVAS::DoRePaint() // Explicitly create a new rendering context instance for this canvas. if( m_glRC == nullptr ) - m_glRC = GL_CONTEXT_MANAGER::Get().CreateCtx( this ); + m_glRC = gl_mgr->CreateCtx( this ); // CreateCtx could and does fail per sentry crash events, lets be graceful if( m_glRC == nullptr ) @@ -401,7 +403,7 @@ void EDA_3D_CANVAS::DoRePaint() return; } - GL_CONTEXT_MANAGER::Get().LockCtx( m_glRC, this ); + gl_mgr->LockCtx( m_glRC, this ); // Set the OpenGL viewport according to the client size of this canvas. // This is done here rather than in a wxSizeEvent handler because our @@ -418,7 +420,7 @@ void EDA_3D_CANVAS::DoRePaint() { if( !initializeOpenGL() ) { - GL_CONTEXT_MANAGER::Get().UnlockCtx( m_glRC ); + gl_mgr->UnlockCtx( m_glRC ); m_is_currently_painting.clear(); return; @@ -440,7 +442,7 @@ void EDA_3D_CANVAS::DoRePaint() SwapBuffers(); - GL_CONTEXT_MANAGER::Get().UnlockCtx( m_glRC ); + gl_mgr->UnlockCtx( m_glRC ); m_is_currently_painting.clear(); return; @@ -528,7 +530,7 @@ void EDA_3D_CANVAS::DoRePaint() m_is_opengl_version_supported = false; m_opengl_supports_raytracing = false; m_is_opengl_initialized = false; - GL_CONTEXT_MANAGER::Get().UnlockCtx( m_glRC ); + gl_mgr->UnlockCtx( m_glRC ); m_is_currently_painting.clear(); return; } @@ -553,7 +555,7 @@ void EDA_3D_CANVAS::DoRePaint() // commands is displayed on the window." SwapBuffers(); - GL_CONTEXT_MANAGER::Get().UnlockCtx( m_glRC ); + gl_mgr->UnlockCtx( m_glRC ); if( m_mouse_was_moved || m_camera_is_moving ) { diff --git a/3d-viewer/3d_model_viewer/eda_3d_model_viewer.cpp b/3d-viewer/3d_model_viewer/eda_3d_model_viewer.cpp index 632449ad5c..be34740111 100644 --- a/3d-viewer/3d_model_viewer/eda_3d_model_viewer.cpp +++ b/3d-viewer/3d_model_viewer/eda_3d_model_viewer.cpp @@ -109,16 +109,17 @@ EDA_3D_MODEL_VIEWER::EDA_3D_MODEL_VIEWER( wxWindow* aParent, const wxGLAttribute EDA_3D_MODEL_VIEWER::~EDA_3D_MODEL_VIEWER() { wxLogTrace( m_logTrace, wxT( "EDA_3D_MODEL_VIEWER::~EDA_3D_MODEL_VIEWER" ) ); + GL_CONTEXT_MANAGER* gl_mgr = Pgm().GetGLContextManager(); if( m_glRC ) { - GL_CONTEXT_MANAGER::Get().LockCtx( m_glRC, this ); + gl_mgr->LockCtx( m_glRC, this ); delete m_ogl_3dmodel; m_ogl_3dmodel = nullptr; - GL_CONTEXT_MANAGER::Get().UnlockCtx( m_glRC ); - GL_CONTEXT_MANAGER::Get().DestroyCtx( m_glRC ); + gl_mgr->UnlockCtx( m_glRC ); + gl_mgr->DestroyCtx( m_glRC ); } } @@ -256,7 +257,7 @@ void EDA_3D_MODEL_VIEWER::OnPaint( wxPaintEvent& event ) // context context current, i.e. it will be used by all subsequent OpenGL calls. // This function may only be called when the window is shown on screen" if( m_glRC == nullptr ) - m_glRC = GL_CONTEXT_MANAGER::Get().CreateCtx( this ); + m_glRC = Pgm().GetGLContextManager()->CreateCtx( this ); // CreateCtx could and does fail per sentry crash events, lets be graceful if( m_glRC == nullptr ) @@ -265,7 +266,7 @@ void EDA_3D_MODEL_VIEWER::OnPaint( wxPaintEvent& event ) return; } - GL_CONTEXT_MANAGER::Get().LockCtx( m_glRC, this ); + Pgm().GetGLContextManager()->LockCtx( m_glRC, this ); // Set the OpenGL viewport according to the client size of this canvas. // This is done here rather than in a wxSizeEvent handler because our @@ -383,7 +384,7 @@ void EDA_3D_MODEL_VIEWER::OnPaint( wxPaintEvent& event ) // commands is displayed on the window." SwapBuffers(); - GL_CONTEXT_MANAGER::Get().UnlockCtx( m_glRC ); + Pgm().GetGLContextManager()->UnlockCtx( m_glRC ); } diff --git a/3d-viewer/3d_rendering/opengl/render_3d_opengl.cpp b/3d-viewer/3d_rendering/opengl/render_3d_opengl.cpp index d776a6e93d..dc6ea15fd5 100644 --- a/3d-viewer/3d_rendering/opengl/render_3d_opengl.cpp +++ b/3d-viewer/3d_rendering/opengl/render_3d_opengl.cpp @@ -36,6 +36,7 @@ #include <3d_math.h> #include #include +#include #include // for KiROUND #include #include @@ -490,7 +491,7 @@ bool RENDER_3D_OPENGL::Redraw( bool aIsMoving, REPORTER* aStatusReporter, // Careful here! // We are in the middle of rendering and the reload method may show // a dialog box that requires the opengl context for a redraw - GL_CONTEXT_MANAGER::Get().RunWithoutCtxLock( [this, aStatusReporter, aWarningReporter]() + Pgm().GetGLContextManager()->RunWithoutCtxLock( [this, aStatusReporter, aWarningReporter]() { reload( aStatusReporter, aWarningReporter ); } ); diff --git a/common/gal/opengl/gl_context_mgr.cpp b/common/gal/opengl/gl_context_mgr.cpp index 2a4d22d964..83ca6f60f3 100644 --- a/common/gal/opengl/gl_context_mgr.cpp +++ b/common/gal/opengl/gl_context_mgr.cpp @@ -27,14 +27,6 @@ #include -GL_CONTEXT_MANAGER& GL_CONTEXT_MANAGER::Get() -{ - static GL_CONTEXT_MANAGER instance; - - return instance; -} - - wxGLContext* GL_CONTEXT_MANAGER::CreateCtx( wxGLCanvas* aCanvas, const wxGLContext* aOther ) { wxGLContext* context = new wxGLContext( aCanvas, aOther ); @@ -124,9 +116,3 @@ void GL_CONTEXT_MANAGER::UnlockCtx( wxGLContext* aContext ) } } - -GL_CONTEXT_MANAGER::GL_CONTEXT_MANAGER() - : m_glCtx( nullptr ) -{ -} - diff --git a/common/gal/opengl/opengl_gal.cpp b/common/gal/opengl/opengl_gal.cpp index ef063e1a9c..62b8904d7b 100644 --- a/common/gal/opengl/opengl_gal.cpp +++ b/common/gal/opengl/opengl_gal.cpp @@ -43,6 +43,7 @@ #include #include #include // for KiROUND +#include #include #include @@ -332,7 +333,7 @@ OPENGL_GAL::OPENGL_GAL( const KIGFX::VC_SETTINGS& aVcSettings, GAL_DISPLAY_OPTIO { if( m_glMainContext == nullptr ) { - m_glMainContext = GL_CONTEXT_MANAGER::Get().CreateCtx( this ); + m_glMainContext = Pgm().GetGLContextManager()->CreateCtx( this ); if( !m_glMainContext ) throw std::runtime_error( "Could not create the main OpenGL context" ); @@ -341,7 +342,7 @@ OPENGL_GAL::OPENGL_GAL( const KIGFX::VC_SETTINGS& aVcSettings, GAL_DISPLAY_OPTIO } else { - m_glPrivContext = GL_CONTEXT_MANAGER::Get().CreateCtx( this, m_glMainContext ); + m_glPrivContext = Pgm().GetGLContextManager()->CreateCtx( this, m_glMainContext ); if( !m_glPrivContext ) throw std::runtime_error( "Could not create a private OpenGL context" ); @@ -421,7 +422,9 @@ OPENGL_GAL::OPENGL_GAL( const KIGFX::VC_SETTINGS& aVcSettings, GAL_DISPLAY_OPTIO OPENGL_GAL::~OPENGL_GAL() { - GL_CONTEXT_MANAGER::Get().LockCtx( m_glPrivContext, this ); + + GL_CONTEXT_MANAGER* gl_mgr = Pgm().GetGLContextManager(); + gl_mgr->LockCtx( m_glPrivContext, this ); --m_instanceCounter; glFlush(); @@ -438,19 +441,19 @@ OPENGL_GAL::~OPENGL_GAL() delete m_tempManager; } - GL_CONTEXT_MANAGER::Get().UnlockCtx( m_glPrivContext ); + gl_mgr->UnlockCtx( m_glPrivContext ); // If it was the main context, then it will be deleted // when the last OpenGL GAL instance is destroyed (a few lines below) if( m_glPrivContext != m_glMainContext ) - GL_CONTEXT_MANAGER::Get().DestroyCtx( m_glPrivContext ); + gl_mgr->DestroyCtx( m_glPrivContext ); delete m_shader; // Are we destroying the last GAL instance? if( m_instanceCounter == 0 ) { - GL_CONTEXT_MANAGER::Get().LockCtx( m_glMainContext, this ); + gl_mgr->LockCtx( m_glMainContext, this ); if( m_isBitmapFontLoaded ) { @@ -458,8 +461,8 @@ OPENGL_GAL::~OPENGL_GAL() m_isBitmapFontLoaded = false; } - GL_CONTEXT_MANAGER::Get().UnlockCtx( m_glMainContext ); - GL_CONTEXT_MANAGER::Get().DestroyCtx( m_glMainContext ); + gl_mgr->UnlockCtx( m_glMainContext ); + gl_mgr->DestroyCtx( m_glMainContext ); m_glMainContext = nullptr; } } @@ -777,7 +780,7 @@ void OPENGL_GAL::LockContext( int aClientCookie ) m_isContextLocked = true; m_lockClientCookie = aClientCookie; - GL_CONTEXT_MANAGER::Get().LockCtx( m_glPrivContext, this ); + Pgm().GetGLContextManager()->LockCtx( m_glPrivContext, this ); } @@ -791,7 +794,7 @@ void OPENGL_GAL::UnlockContext( int aClientCookie ) m_isContextLocked = false; - GL_CONTEXT_MANAGER::Get().UnlockCtx( m_glPrivContext ); + Pgm().GetGLContextManager()->UnlockCtx( m_glPrivContext ); } diff --git a/include/gal/opengl/gl_context_mgr.h b/include/gal/opengl/gl_context_mgr.h index 88398f1764..96a8d2f543 100644 --- a/include/gal/opengl/gl_context_mgr.h +++ b/include/gal/opengl/gl_context_mgr.h @@ -27,19 +27,17 @@ #ifndef GL_CONTEXT_MANAGER_H #define GL_CONTEXT_MANAGER_H -#include +#include #include #include #include #include -class APIEXPORT GL_CONTEXT_MANAGER +class KICOMMON_API GL_CONTEXT_MANAGER { public: - /** - * Return the GL_CONTEXT_MANAGER instance (singleton). - */ - static GL_CONTEXT_MANAGER& Get(); + + GL_CONTEXT_MANAGER() : m_glCtx( nullptr ) {} /** * Create a managed OpenGL context. @@ -49,7 +47,7 @@ public: * * @return Created OpenGL context. */ - APIEXPORT wxGLContext* CreateCtx( wxGLCanvas* aCanvas, const wxGLContext* aOther = nullptr ); + wxGLContext* CreateCtx( wxGLCanvas* aCanvas, const wxGLContext* aOther = nullptr ); /** * Destroy a managed OpenGL context. @@ -58,14 +56,14 @@ public: * * @param aContext is the OpenGL context to be destroyed. It will not be managed anymore. */ - APIEXPORT void DestroyCtx( wxGLContext* aContext ); + void DestroyCtx( wxGLContext* aContext ); /** * Destroy all managed OpenGL contexts. * * This method should be called in the final deinitialization routine. */ - APIEXPORT void DeleteAll(); + void DeleteAll(); /** * Set a context as current and prevents other canvases from switching it. @@ -77,7 +75,7 @@ public: * @param aCanvas (optional) allows caller to bind the context to a non-parent canvas * (e.g. when a few canvases share a single GL context). */ - APIEXPORT void LockCtx( wxGLContext* aContext, wxGLCanvas* aCanvas ); + void LockCtx( wxGLContext* aContext, wxGLCanvas* aCanvas ); /** * Allow other canvases to bind an OpenGL context. @@ -85,14 +83,14 @@ public: * @param aContext is the currently bound context. It is only a check to assure the right * canvas wants to unlock GL context. */ - APIEXPORT void UnlockCtx( wxGLContext* aContext ); + void UnlockCtx( wxGLContext* aContext ); /** * Get the currently bound GL context. * * @return the currently bound GL context. */ - APIEXPORT wxGLContext* GetCurrentCtx() const + wxGLContext* GetCurrentCtx() const { return m_glCtx; } @@ -102,7 +100,7 @@ public: * * @return the currently bound GL canvas. */ - APIEXPORT wxGLCanvas* GetCurrentCanvas() const + wxGLCanvas* GetCurrentCanvas() const { auto it = m_glContexts.find( m_glCtx ); return it != m_glContexts.end() ? it->second : nullptr; @@ -114,7 +112,7 @@ public: * @param aFunction is the function to be executed. */ template - APIEXPORT auto RunWithoutCtxLock( Func&& aFunction, Args&&... args ) + auto RunWithoutCtxLock( Func&& aFunction, Args&&... args ) { wxGLContext* currentCtx = GetCurrentCtx(); wxGLCanvas* currentCanvas = GetCurrentCanvas(); @@ -143,11 +141,6 @@ private: ///< Lock to prevent unexpected GL context switching. std::mutex m_glCtxMutex; - - // Singleton - GL_CONTEXT_MANAGER(); - GL_CONTEXT_MANAGER( const GL_CONTEXT_MANAGER& ); - void operator=( const GL_CONTEXT_MANAGER& ); }; #endif /* GL_CONTEXT_MANAGER_H */ diff --git a/include/pgm_base.h b/include/pgm_base.h index e43906fca9..2952ce5f90 100644 --- a/include/pgm_base.h +++ b/include/pgm_base.h @@ -112,6 +112,8 @@ public: BS::thread_pool& GetThreadPool() { return *m_singleton.m_ThreadPool; } + GL_CONTEXT_MANAGER* GetGLContextManager() { return m_singleton.m_GLContextManager; } + /** * Specific to MacOSX (not used under Linux or Windows). * diff --git a/include/singleton.h b/include/singleton.h index 04e934540b..f24c1454e3 100644 --- a/include/singleton.h +++ b/include/singleton.h @@ -35,6 +35,10 @@ public: delete m_ThreadPool; m_ThreadPool = nullptr; + + m_GLContextManager->DeleteAll(); + delete m_GLContextManager; + m_GLContextManager = nullptr; }; @@ -42,9 +46,12 @@ public: { int num_threads = std::max( 0, ADVANCED_CFG::GetCfg().m_MaximumThreads ); m_ThreadPool = new BS::thread_pool( num_threads ); + m_GLContextManager = new GL_CONTEXT_MANAGER(); } BS::thread_pool* m_ThreadPool; + GL_CONTEXT_MANAGER* m_GLContextManager; + };