GL_CONTEXT_MANAGER class to avoid unexpected GL context switches.
This commit is contained in:
parent
4f7bb4c0f7
commit
01f32dd52c
|
@ -48,6 +48,7 @@
|
|||
#include <info3d_visu.h>
|
||||
#include <trackball.h>
|
||||
#include <3d_viewer_id.h>
|
||||
#include <gl_context_mgr.h>
|
||||
|
||||
#include <textures/text_silk.h>
|
||||
#include <textures/text_pcb.h>
|
||||
|
@ -108,7 +109,7 @@ EDA_3D_CANVAS::EDA_3D_CANVAS( EDA_3D_FRAME* parent, int* attribList ) :
|
|||
m_glLists[ii] = 0;
|
||||
|
||||
// Explicitly create a new rendering context instance for this canvas.
|
||||
m_glRC = new wxGLContext( this );
|
||||
m_glRC = GL_CONTEXT_MANAGER::Get().CreateCtx( this );
|
||||
|
||||
DisplayStatus();
|
||||
}
|
||||
|
@ -116,21 +117,16 @@ EDA_3D_CANVAS::EDA_3D_CANVAS( EDA_3D_FRAME* parent, int* attribList ) :
|
|||
|
||||
EDA_3D_CANVAS::~EDA_3D_CANVAS()
|
||||
{
|
||||
#ifdef __LINUX__
|
||||
if( IsShownOnScreen() )
|
||||
SetCurrent( *m_glRC );
|
||||
#else
|
||||
SetCurrent( *m_glRC );
|
||||
#endif
|
||||
GL_CONTEXT_MANAGER::Get().LockCtx( m_glRC );
|
||||
|
||||
ClearLists();
|
||||
m_init = false;
|
||||
delete m_glRC;
|
||||
|
||||
// Free the list of parsers list
|
||||
for( unsigned int i = 0; i < m_model_parsers_list.size(); i++ )
|
||||
delete m_model_parsers_list[i];
|
||||
|
||||
GL_CONTEXT_MANAGER::Get().UnlockCtx( m_glRC );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
#include <trackball.h>
|
||||
#include <3d_draw_basic_functions.h>
|
||||
#include "3d_rendering/3d_render_ogl_legacy/ogl_legacy_utils.h"
|
||||
#include <gl_context_mgr.h>
|
||||
|
||||
#include <cimage.h>
|
||||
#include <reporter.h>
|
||||
|
@ -301,7 +302,7 @@ void EDA_3D_CANVAS::Redraw()
|
|||
// Display build time at the end of build
|
||||
unsigned strtime = GetRunningMicroSecs();
|
||||
|
||||
SetCurrent( *m_glRC );
|
||||
GL_CONTEXT_MANAGER::Get().LockCtx( m_glRC );
|
||||
|
||||
// Set the OpenGL viewport according to the client size of this canvas.
|
||||
// This is done here rather than in a wxSizeEvent handler because our
|
||||
|
@ -318,7 +319,7 @@ void EDA_3D_CANVAS::Redraw()
|
|||
generateFakeShadowsTextures( &errorReporter, &activityReporter );
|
||||
}
|
||||
|
||||
// *MUST* be called *after* SetCurrent( ):
|
||||
// *MUST* be called *after* GL_CONTEXT_MANAGER::LockCtx():
|
||||
glViewport( 0, 0, size.x, size.y );
|
||||
|
||||
// clear color and depth buffers
|
||||
|
@ -609,6 +610,7 @@ void EDA_3D_CANVAS::Redraw()
|
|||
*/
|
||||
|
||||
SwapBuffers();
|
||||
GL_CONTEXT_MANAGER::Get().UnlockCtx( m_glRC );
|
||||
|
||||
// Show calculation time if some activity was reported
|
||||
if( activityReporter.HasMessage() )
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "common_ogl/ogl_utils.h"
|
||||
#include <wx/dcclient.h>
|
||||
#include "convert_to_biu.h"
|
||||
#include <gl_context_mgr.h>
|
||||
|
||||
#define UNITS3D_TO_UNITSPCB (IU_PER_MM)
|
||||
|
||||
|
@ -202,7 +203,7 @@ void C3D_MODEL_VIEWER::OnPaint( wxPaintEvent &event )
|
|||
// "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.
|
||||
// This function may only be called when the window is shown on screen"
|
||||
SetCurrent( *m_glRC );
|
||||
GL_CONTEXT_MANAGER::Get().LockCtx( m_glRC );
|
||||
|
||||
// Set the OpenGL viewport according to the client size of this canvas.
|
||||
// This is done here rather than in a wxSizeEvent handler because our
|
||||
|
@ -311,6 +312,7 @@ void C3D_MODEL_VIEWER::OnPaint( wxPaintEvent &event )
|
|||
// front-buffer and vice versa, so that the output of the previous OpenGL
|
||||
// commands is displayed on the window."
|
||||
SwapBuffers();
|
||||
GL_CONTEXT_MANAGER::Get().UnlockCtx( m_glRC );
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ set( GAL_SRCS
|
|||
newstroke_font.cpp
|
||||
worksheet_viewitem.cpp
|
||||
origin_viewitem.cpp
|
||||
gl_context_mgr.cpp
|
||||
gal/graphics_abstraction_layer.cpp
|
||||
gal/stroke_font.cpp
|
||||
gal/color4d.cpp
|
||||
|
|
|
@ -126,8 +126,11 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWin
|
|||
|
||||
EDA_DRAW_PANEL_GAL::~EDA_DRAW_PANEL_GAL()
|
||||
{
|
||||
StopDrawing();
|
||||
SaveGalSettings();
|
||||
|
||||
assert( !m_drawing );
|
||||
|
||||
delete m_painter;
|
||||
delete m_viewControls;
|
||||
delete m_view;
|
||||
|
@ -288,7 +291,6 @@ void EDA_DRAW_PANEL_GAL::StopDrawing()
|
|||
m_drawingEnabled = false;
|
||||
Disconnect( wxEVT_PAINT, wxPaintEventHandler( EDA_DRAW_PANEL_GAL::onPaint ), NULL, this );
|
||||
m_pendingRefresh = false;
|
||||
m_drawing = true;
|
||||
m_refreshTimer.Stop();
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <gal/opengl/opengl_gal.h>
|
||||
#include <gal/opengl/utils.h>
|
||||
#include <gal/definitions.h>
|
||||
#include <gl_context_mgr.h>
|
||||
|
||||
#include <macros.h>
|
||||
|
||||
|
@ -49,8 +50,9 @@ using namespace KIGFX;
|
|||
static void InitTesselatorCallbacks( GLUtesselator* aTesselator );
|
||||
static const int glAttributes[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 8, 0 };
|
||||
|
||||
wxGLContext* OPENGL_GAL::glContext = NULL;
|
||||
wxGLContext* OPENGL_GAL::glMainContext = NULL;
|
||||
int OPENGL_GAL::instanceCounter = 0;
|
||||
GLuint OPENGL_GAL::fontTexture = 0;
|
||||
bool OPENGL_GAL::isBitmapFontLoaded = false;
|
||||
|
||||
|
||||
|
@ -64,8 +66,15 @@ OPENGL_GAL::OPENGL_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener,
|
|||
nonCachedManager( false ),
|
||||
overlayManager( false )
|
||||
{
|
||||
if( glContext == NULL )
|
||||
glContext = new wxGLContext( this );
|
||||
if( glMainContext == NULL )
|
||||
{
|
||||
glMainContext = GL_CONTEXT_MANAGER::Get().CreateCtx( this );
|
||||
glPrivContext = glMainContext;
|
||||
}
|
||||
else
|
||||
{
|
||||
glPrivContext = GL_CONTEXT_MANAGER::Get().CreateCtx( this, glMainContext );
|
||||
}
|
||||
|
||||
// Check if OpenGL requirements are met
|
||||
runTest();
|
||||
|
@ -129,16 +138,10 @@ OPENGL_GAL::OPENGL_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener,
|
|||
|
||||
OPENGL_GAL::~OPENGL_GAL()
|
||||
{
|
||||
GL_CONTEXT_MANAGER::Get().LockCtx( glPrivContext );
|
||||
|
||||
gluDeleteTess( tesselator );
|
||||
ClearCache();
|
||||
|
||||
#ifdef __LINUX__
|
||||
if( IsShownOnScreen() )
|
||||
SetCurrent( *OPENGL_GAL::glContext );
|
||||
#else
|
||||
SetCurrent( *OPENGL_GAL::glContext );
|
||||
#endif
|
||||
|
||||
glFlush();
|
||||
|
||||
if( --instanceCounter == 0 )
|
||||
|
@ -148,10 +151,9 @@ OPENGL_GAL::~OPENGL_GAL()
|
|||
glDeleteTextures( 1, &fontTexture );
|
||||
isBitmapFontLoaded = false;
|
||||
}
|
||||
|
||||
delete OPENGL_GAL::glContext;
|
||||
glContext = NULL;
|
||||
}
|
||||
|
||||
GL_CONTEXT_MANAGER::Get().UnlockCtx( glPrivContext );
|
||||
}
|
||||
|
||||
|
||||
|
@ -165,7 +167,7 @@ void OPENGL_GAL::BeginDrawing()
|
|||
prof_start( &totalRealTime );
|
||||
#endif /* __WXDEBUG__ */
|
||||
|
||||
SetCurrent( *glContext );
|
||||
GL_CONTEXT_MANAGER::Get().LockCtx( glPrivContext );
|
||||
|
||||
#ifdef RETINA_OPENGL_PATCH
|
||||
const float scaleFactor = GetBackingScaleFactor();
|
||||
|
@ -237,6 +239,7 @@ void OPENGL_GAL::BeginDrawing()
|
|||
// Keep bitmap font texture always bound to the second texturing unit
|
||||
const GLint FONT_TEXTURE_UNIT = 2;
|
||||
|
||||
// Either load the font atlas to video memory, or simply bind it to a texture unit
|
||||
if( !isBitmapFontLoaded )
|
||||
{
|
||||
glActiveTexture( GL_TEXTURE0 + FONT_TEXTURE_UNIT );
|
||||
|
@ -253,6 +256,12 @@ void OPENGL_GAL::BeginDrawing()
|
|||
|
||||
isBitmapFontLoaded = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
glActiveTexture( GL_TEXTURE0 + FONT_TEXTURE_UNIT );
|
||||
glBindTexture( GL_TEXTURE_2D, fontTexture );
|
||||
glActiveTexture( GL_TEXTURE0 );
|
||||
}
|
||||
|
||||
// Set shader parameter
|
||||
GLint ufm_fontTexture = shader.AddParameter( "fontTexture" );
|
||||
|
@ -300,6 +309,7 @@ void OPENGL_GAL::EndDrawing()
|
|||
blitCursor();
|
||||
|
||||
SwapBuffers();
|
||||
GL_CONTEXT_MANAGER::Get().UnlockCtx( glPrivContext );
|
||||
|
||||
#ifdef __WXDEBUG__
|
||||
prof_end( &totalRealTime );
|
||||
|
@ -310,7 +320,7 @@ void OPENGL_GAL::EndDrawing()
|
|||
|
||||
void OPENGL_GAL::BeginUpdate()
|
||||
{
|
||||
SetCurrent( *OPENGL_GAL::glContext );
|
||||
GL_CONTEXT_MANAGER::Get().LockCtx( glPrivContext );
|
||||
cachedManager.Map();
|
||||
}
|
||||
|
||||
|
@ -318,6 +328,7 @@ void OPENGL_GAL::BeginUpdate()
|
|||
void OPENGL_GAL::EndUpdate()
|
||||
{
|
||||
cachedManager.Unmap();
|
||||
GL_CONTEXT_MANAGER::Get().UnlockCtx( glPrivContext );
|
||||
}
|
||||
|
||||
|
||||
|
@ -1454,7 +1465,7 @@ bool OPENGL_GAL::runTest()
|
|||
{
|
||||
wxDialog dlgtest( GetParent(), -1, wxT( "opengl test" ), wxPoint( 50, 50 ),
|
||||
wxDLG_UNIT( GetParent(), wxSize( 50, 50 ) ) );
|
||||
OPENGL_TEST* test = new OPENGL_TEST( &dlgtest, this );
|
||||
OPENGL_TEST* test = new OPENGL_TEST( &dlgtest, this, glPrivContext );
|
||||
|
||||
dlgtest.Raise(); // on Linux, on some windows managers (Unity for instance) this is needed to actually show the dialog
|
||||
dlgtest.ShowModal();
|
||||
|
@ -1471,10 +1482,10 @@ bool OPENGL_GAL::runTest()
|
|||
}
|
||||
|
||||
|
||||
OPENGL_GAL::OPENGL_TEST::OPENGL_TEST( wxDialog* aParent, OPENGL_GAL* aGal ) :
|
||||
OPENGL_GAL::OPENGL_TEST::OPENGL_TEST( wxDialog* aParent, OPENGL_GAL* aGal, wxGLContext* aContext ) :
|
||||
wxGLCanvas( aParent, wxID_ANY, glAttributes, wxDefaultPosition,
|
||||
wxDefaultSize, 0, wxT( "GLCanvas" ) ),
|
||||
m_parent( aParent ), m_gal( aGal ), m_tested( false ), m_result( false )
|
||||
m_parent( aParent ), m_gal( aGal ), m_context( aContext ), m_tested( false ), m_result( false )
|
||||
{
|
||||
m_timeoutTimer.SetOwner( this );
|
||||
Connect( wxEVT_PAINT, wxPaintEventHandler( OPENGL_GAL::OPENGL_TEST::Render ) );
|
||||
|
@ -1497,7 +1508,7 @@ void OPENGL_GAL::OPENGL_TEST::Render( wxPaintEvent& WXUNUSED( aEvent ) )
|
|||
Disconnect( wxEVT_PAINT, wxPaintEventHandler( OPENGL_GAL::OPENGL_TEST::Render ) );
|
||||
CallAfter( boost::bind( &wxDialog::EndModal, m_parent, wxID_NONE ) );
|
||||
|
||||
SetCurrent( *OPENGL_GAL::glContext );
|
||||
GL_CONTEXT_MANAGER::Get().LockCtx( m_context, this );
|
||||
GLenum err = glewInit();
|
||||
|
||||
if( GLEW_OK != err )
|
||||
|
@ -1536,6 +1547,7 @@ void OPENGL_GAL::OPENGL_TEST::Render( wxPaintEvent& WXUNUSED( aEvent ) )
|
|||
error( "Requested texture size is not supported" );
|
||||
}
|
||||
|
||||
GL_CONTEXT_MANAGER::Get().UnlockCtx( m_context );
|
||||
m_tested = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 CERN
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <gl_context_mgr.h>
|
||||
|
||||
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 );
|
||||
assert( context /* && context->IsOK() */ ); // IsOK() is available in wx3.1+
|
||||
assert( m_glContexts.count( context ) == 0 );
|
||||
m_glContexts.insert( std::make_pair( context, aCanvas ) );
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
|
||||
void GL_CONTEXT_MANAGER::DeleteAll()
|
||||
{
|
||||
for( auto& ctx : m_glContexts )
|
||||
delete ctx.first;
|
||||
|
||||
m_glContexts.clear();
|
||||
}
|
||||
|
||||
|
||||
void GL_CONTEXT_MANAGER::LockCtx( wxGLContext* aContext, wxGLCanvas* aCanvas )
|
||||
{
|
||||
assert( aCanvas || m_glContexts.count( aContext ) > 0 );
|
||||
|
||||
m_glCtxMutex.lock();
|
||||
wxGLCanvas* canvas = aCanvas ? aCanvas : m_glContexts.at( aContext );
|
||||
canvas->SetCurrent( *aContext );
|
||||
m_glCtx = aContext;
|
||||
}
|
||||
|
||||
|
||||
void GL_CONTEXT_MANAGER::UnlockCtx( wxGLContext* aContext )
|
||||
{
|
||||
assert( m_glContexts.count( aContext ) > 0 );
|
||||
|
||||
if( m_glCtx == aContext ){
|
||||
m_glCtxMutex.unlock();
|
||||
m_glCtx = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogDebug( "Trying to unlock GL context mutex from a wrong context" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GL_CONTEXT_MANAGER::GL_CONTEXT_MANAGER()
|
||||
: m_glCtx( NULL )
|
||||
{
|
||||
}
|
||||
|
|
@ -273,12 +273,13 @@ private:
|
|||
static const int CIRCLE_POINTS = 64; ///< The number of points for circle approximation
|
||||
static const int CURVE_POINTS = 32; ///< The number of points for curve approximation
|
||||
|
||||
static wxGLContext* glContext; ///< OpenGL context of wxWidgets
|
||||
static wxGLContext* glMainContext; ///< Parent OpenGL context
|
||||
wxGLContext* glPrivContext; ///< Canvas-specific OpenGL context
|
||||
wxEvtHandler* mouseListener;
|
||||
wxEvtHandler* paintListener;
|
||||
static int instanceCounter;
|
||||
|
||||
GLuint fontTexture; ///< Bitmap font texture handle
|
||||
static GLuint fontTexture; ///< Bitmap font texture handle (shared)
|
||||
|
||||
// Vertex buffer objects related fields
|
||||
typedef std::map< unsigned int, boost::shared_ptr<VERTEX_ITEM> > GROUPS_MAP;
|
||||
|
@ -415,7 +416,7 @@ private:
|
|||
class OPENGL_TEST: public wxGLCanvas
|
||||
{
|
||||
public:
|
||||
OPENGL_TEST( wxDialog* aParent, OPENGL_GAL* aGal );
|
||||
OPENGL_TEST( wxDialog* aParent, OPENGL_GAL* aGal, wxGLContext* aContext );
|
||||
|
||||
void Render( wxPaintEvent& aEvent );
|
||||
void OnTimeout( wxTimerEvent& aEvent );
|
||||
|
@ -430,6 +431,7 @@ private:
|
|||
|
||||
wxDialog* m_parent;
|
||||
OPENGL_GAL* m_gal;
|
||||
wxGLContext* m_context;
|
||||
bool m_tested;
|
||||
bool m_result;
|
||||
std::string m_error;
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 CERN
|
||||
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef GL_CONTEXT_MANAGER_H
|
||||
#define GL_CONTEXT_MANAGER_H
|
||||
|
||||
#include <wx/glcanvas.h>
|
||||
#include <ki_mutex.h>
|
||||
#include <map>
|
||||
|
||||
class GL_CONTEXT_MANAGER
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Function Get
|
||||
* returns the GL_CONTEXT_MANAGER instance (singleton).
|
||||
*/
|
||||
static GL_CONTEXT_MANAGER& Get();
|
||||
|
||||
/**
|
||||
* Function CreateCtx
|
||||
* creates a managed OpenGL context. It is assured that the created context is freed upon
|
||||
* exit.
|
||||
* See wxGLContext documentation for the parameters description.
|
||||
* @return Created OpenGL context.
|
||||
*/
|
||||
wxGLContext* CreateCtx( wxGLCanvas* aCanvas, const wxGLContext* aOther = NULL );
|
||||
|
||||
/**
|
||||
* Function DeleteAll
|
||||
* destroys all managed OpenGL contexts. This method should be called in the
|
||||
* final deinitialization routine.
|
||||
*/
|
||||
void DeleteAll();
|
||||
|
||||
/**
|
||||
* Function LockCtx
|
||||
* sets a context as current and prevents other canvases from switching it.
|
||||
* Requires calling UnlockCtx() when there are no more GL calls for the context.
|
||||
* If another canvas has already locked a GL context, then the calling process is blocked.
|
||||
* @param aContext is the GL context to be bound.
|
||||
* @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).
|
||||
*/
|
||||
void LockCtx( wxGLContext* aContext, wxGLCanvas* aCanvas = NULL );
|
||||
|
||||
/**
|
||||
* Function UnlockCtx
|
||||
* allows other canvases to bind an OpenGL context.
|
||||
* @param aContext is the currently bound context. It is only a check to assure the right
|
||||
* canvas wants to unlock GL context.
|
||||
*/
|
||||
void UnlockCtx( wxGLContext* aContext );
|
||||
|
||||
private:
|
||||
///> Map of GL contexts & their parent canvases.
|
||||
std::map<wxGLContext*, wxGLCanvas*> m_glContexts;
|
||||
|
||||
///> Currently bound GL context.
|
||||
wxGLContext* m_glCtx;
|
||||
|
||||
///> Lock to prevent unexpected GL context switching.
|
||||
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 */
|
||||
|
|
@ -57,6 +57,7 @@
|
|||
#include <module_editor_frame.h>
|
||||
#include <modview_frame.h>
|
||||
#include <footprint_wizard_frame.h>
|
||||
#include <gl_context_mgr.h>
|
||||
|
||||
extern bool IsWxPythonLoaded();
|
||||
|
||||
|
@ -367,8 +368,12 @@ bool IFACE::OnKifaceStart( PGM_BASE* aProgram, int aCtlBits )
|
|||
|
||||
void IFACE::OnKifaceEnd()
|
||||
{
|
||||
end_common();
|
||||
// This function deletes OpenGL contexts used (if any) by wxGLCanvas objects.
|
||||
// It can be called only when closing the application, because it deletes an OpenGL context
|
||||
// which can still be in usage. Destroying OpenGL contexts earlier may crash the application.
|
||||
GL_CONTEXT_MANAGER::Get().DeleteAll();
|
||||
|
||||
end_common();
|
||||
#if defined( KICAD_SCRIPTING_WXPYTHON )
|
||||
// Restore the thread state and tell Python to cleanup after itself.
|
||||
// wxPython will do its own cleanup as part of that process.
|
||||
|
|
Loading…
Reference in New Issue