Kaydet (Commit) 2e512773 authored tarafından Louis-Francis Ratté-Boulianne's avatar Louis-Francis Ratté-Boulianne Kaydeden (comit) Markus Mohrhard

vcl: Reset context when the backend window is destroyed

Conflicts:
	vcl/source/opengl/OpenGLContext.cxx

Change-Id: Ie2b93de8efe5ea56b0420adf23639c0153103385
üst f0f5f502
...@@ -204,6 +204,7 @@ public: ...@@ -204,6 +204,7 @@ public:
#elif defined( _WIN32 ) #elif defined( _WIN32 )
bool init( HDC hDC, HWND hWnd ); bool init( HDC hDC, HWND hWnd );
#endif #endif
void reset();
// use these methods right after setting a context to make sure drawing happens // use these methods right after setting a context to make sure drawing happens
// in the right FBO (default one is for onscreen painting) // in the right FBO (default one is for onscreen painting)
...@@ -218,6 +219,7 @@ public: ...@@ -218,6 +219,7 @@ public:
OpenGLProgram* GetProgram( const OUString& rVertexShader, const OUString& rFragmentShader ); OpenGLProgram* GetProgram( const OUString& rVertexShader, const OUString& rFragmentShader );
OpenGLProgram* UseProgram( const OUString& rVertexShader, const OUString& rFragmentShader ); OpenGLProgram* UseProgram( const OUString& rVertexShader, const OUString& rFragmentShader );
bool isCurrent();
void makeCurrent(); void makeCurrent();
void resetCurrent(); void resetCurrent();
void swapBuffers(); void swapBuffers();
......
...@@ -471,6 +471,8 @@ void OpenGLSalBitmap::makeCurrent() ...@@ -471,6 +471,8 @@ void OpenGLSalBitmap::makeCurrent()
// TODO: make sure we can really use the last used context // TODO: make sure we can really use the last used context
mpContext = pSVData->maGDIData.mpLastContext; mpContext = pSVData->maGDIData.mpLastContext;
while( mpContext && !mpContext->isInitialized() )
mpContext = mpContext->mpPrevContext;
if( !mpContext ) if( !mpContext )
mpContext = GetBitmapContext(); mpContext = GetBitmapContext();
assert(mpContext && "Couldn't get an OpenGL context"); assert(mpContext && "Couldn't get an OpenGL context");
......
...@@ -84,6 +84,8 @@ OpenGLContext::OpenGLContext(): ...@@ -84,6 +84,8 @@ OpenGLContext::OpenGLContext():
OpenGLContext::~OpenGLContext() OpenGLContext::~OpenGLContext()
{ {
SAL_INFO("vcl.opengl", "delete context: " << this); SAL_INFO("vcl.opengl", "delete context: " << this);
reset();
ImplSVData* pSVData = ImplGetSVData(); ImplSVData* pSVData = ImplGetSVData();
if( mpPrevContext ) if( mpPrevContext )
mpPrevContext->mpNextContext = mpNextContext; mpPrevContext->mpNextContext = mpNextContext;
...@@ -93,39 +95,6 @@ OpenGLContext::~OpenGLContext() ...@@ -93,39 +95,6 @@ OpenGLContext::~OpenGLContext()
mpNextContext->mpPrevContext = mpPrevContext; mpNextContext->mpPrevContext = mpPrevContext;
else else
pSVData->maGDIData.mpLastContext = mpPrevContext; pSVData->maGDIData.mpLastContext = mpPrevContext;
#if defined( WNT )
if (m_aGLWin.hRC)
{
std::vector<HGLRC>::iterator itr = std::remove(g_vShareList.begin(), g_vShareList.end(), m_aGLWin.hRC);
if (itr != g_vShareList.end())
g_vShareList.erase(itr);
wglMakeCurrent( m_aGLWin.hDC, 0 );
wglDeleteContext( m_aGLWin.hRC );
ReleaseDC( m_aGLWin.hWnd, m_aGLWin.hDC );
}
#elif defined( MACOSX )
OpenGLWrapper::resetCurrent();
#elif defined( IOS ) || defined( ANDROID )
// nothing
#elif defined( UNX )
if(m_aGLWin.ctx)
{
std::vector<GLXContext>::iterator itr = std::remove( g_vShareList.begin(), g_vShareList.end(), m_aGLWin.ctx );
if (itr != g_vShareList.end())
g_vShareList.erase(itr);
glXMakeCurrent(m_aGLWin.dpy, None, NULL);
if( glGetError() != GL_NO_ERROR )
{
SAL_WARN("vcl.opengl", "glError: " << (char *)gluErrorString(glGetError()));
}
glXDestroyContext(m_aGLWin.dpy, m_aGLWin.ctx);
if (mbPixmap && m_aGLWin.glPix != None)
glXDestroyPixmap(m_aGLWin.dpy, m_aGLWin.glPix);
}
#endif
} }
void OpenGLContext::AddRef() void OpenGLContext::AddRef()
...@@ -1162,6 +1131,86 @@ void OpenGLContext::initGLWindow(Visual* pVisual) ...@@ -1162,6 +1131,86 @@ void OpenGLContext::initGLWindow(Visual* pVisual)
#endif #endif
void OpenGLContext::reset()
{
if( !mbInitialized )
return;
// reset the clip region
maClipRegion.SetEmpty();
// destroy all framebuffers
if( mpLastFramebuffer )
{
OpenGLFramebuffer* pFramebuffer = mpLastFramebuffer;
makeCurrent();
while( pFramebuffer )
{
OpenGLFramebuffer* pPrevFramebuffer = pFramebuffer->mpPrevFramebuffer;
delete pFramebuffer;
pFramebuffer = pPrevFramebuffer;
}
mpFirstFramebuffer = NULL;
mpLastFramebuffer = NULL;
}
// destroy all programs
if( !maPrograms.empty() )
{
boost::unordered_map<ProgramKey, OpenGLProgram*>::iterator it;
makeCurrent();
it = maPrograms.begin();
while( it != maPrograms.end() )
{
delete it->second;
it++;
}
maPrograms.clear();
}
if( isCurrent() )
resetCurrent();
mbInitialized = false;
// destroy the context itself
#if defined( WNT )
if (m_aGLWin.hRC)
{
std::vector<HGLRC>::iterator itr = std::remove(g_vShareList.begin(), g_vShareList.end(), m_aGLWin.hRC);
if (itr != g_vShareList.end())
g_vShareList.erase(itr);
wglMakeCurrent( m_aGLWin.hDC, 0 );
wglDeleteContext( m_aGLWin.hRC );
ReleaseDC( m_aGLWin.hWnd, m_aGLWin.hDC );
}
#elif defined( MACOSX )
OpenGLWrapper::resetCurrent();
#elif defined( IOS ) || defined( ANDROID )
// nothing
#elif defined( UNX )
if(m_aGLWin.ctx)
{
std::vector<GLXContext>::iterator itr = std::remove( g_vShareList.begin(), g_vShareList.end(), m_aGLWin.ctx );
if (itr != g_vShareList.end())
g_vShareList.erase(itr);
glXMakeCurrent(m_aGLWin.dpy, None, NULL);
if( glGetError() != GL_NO_ERROR )
{
SAL_WARN("vcl.opengl", "glError: " << (char *)gluErrorString(glGetError()));
}
glXDestroyContext(m_aGLWin.dpy, m_aGLWin.ctx);
if (mbPixmap && m_aGLWin.glPix != None)
glXDestroyPixmap(m_aGLWin.dpy, m_aGLWin.glPix);
}
#endif
}
#if defined( WNT ) || defined( MACOSX ) || defined( IOS ) || defined( ANDROID ) #if defined( WNT ) || defined( MACOSX ) || defined( IOS ) || defined( ANDROID )
SystemWindowData OpenGLContext::generateWinData(vcl::Window* /*pParent*/, bool bRequestLegacyContext) SystemWindowData OpenGLContext::generateWinData(vcl::Window* /*pParent*/, bool bRequestLegacyContext)
...@@ -1217,17 +1266,33 @@ SystemWindowData OpenGLContext::generateWinData(vcl::Window* pParent, bool) ...@@ -1217,17 +1266,33 @@ SystemWindowData OpenGLContext::generateWinData(vcl::Window* pParent, bool)
#endif #endif
bool OpenGLContext::isCurrent()
{
#if defined( WNT )
return (wglGetCurrentContext() == m_aGLWin.hRC &&
wglGetCurrentDC() == m_aGLWin.hDC);
#elif defined( MACOSX )
return false;
#elif defined( IOS ) || defined( ANDROID )
return false;
#elif defined( UNX )
GLXDrawable nDrawable = mbPixmap ? m_aGLWin.glPix : m_aGLWin.win;
return (glXGetCurrentContext() == m_aGLWin.ctx &&
glXGetCurrentDrawable() == nDrawable);
#endif
}
void OpenGLContext::makeCurrent() void OpenGLContext::makeCurrent()
{ {
ImplSVData* pSVData = ImplGetSVData();
if (isCurrent())
return;
#if defined( WNT ) #if defined( WNT )
if (wglGetCurrentContext() == m_aGLWin.hRC && if (!wglMakeCurrent(m_aGLWin.hDC, m_aGLWin.hRC))
wglGetCurrentDC() == m_aGLWin.hDC)
{
SAL_INFO("vcl.opengl", "OpenGLContext::makeCurrent(): Avoid setting the same context");
}
else if (!wglMakeCurrent(m_aGLWin.hDC, m_aGLWin.hRC))
{ {
SAL_WARN("vcl.opengl", "OpenGLContext::makeCurrent(): wglMakeCurrent failed: " << GetLastError()); SAL_WARN("vcl.opengl", "OpenGLContext::makeCurrent(): wglMakeCurrent failed: " << GetLastError());
return;
} }
#elif defined( MACOSX ) #elif defined( MACOSX )
NSOpenGLView* pView = getOpenGLView(); NSOpenGLView* pView = getOpenGLView();
...@@ -1236,33 +1301,29 @@ void OpenGLContext::makeCurrent() ...@@ -1236,33 +1301,29 @@ void OpenGLContext::makeCurrent()
// nothing // nothing
#elif defined( UNX ) #elif defined( UNX )
GLXDrawable nDrawable = mbPixmap ? m_aGLWin.glPix : m_aGLWin.win; GLXDrawable nDrawable = mbPixmap ? m_aGLWin.glPix : m_aGLWin.win;
static int nSwitch = 0; if (!glXMakeCurrent( m_aGLWin.dpy, nDrawable, m_aGLWin.ctx ))
if (glXGetCurrentContext() == m_aGLWin.ctx &&
glXGetCurrentDrawable() == nDrawable)
{ {
; // no-op
}
else if (!glXMakeCurrent( m_aGLWin.dpy, nDrawable, m_aGLWin.ctx ))
SAL_WARN("vcl.opengl", "OpenGLContext::makeCurrent failed on drawable " << nDrawable << " pixmap? " << mbPixmap); SAL_WARN("vcl.opengl", "OpenGLContext::makeCurrent failed on drawable " << nDrawable << " pixmap? " << mbPixmap);
else return;
}
#endif
// move the context at the end of the contexts list
static int nSwitch = 0;
SAL_INFO("vcl.opengl", "******* CONTEXT SWITCH " << ++nSwitch << " *********");
if( mpNextContext )
{ {
SAL_INFO("vcl.opengl", "******* CONTEXT SWITCH " << ++nSwitch << " *********"); if( mpPrevContext )
ImplSVData* pSVData = ImplGetSVData(); mpPrevContext->mpNextContext = mpNextContext;
if( mpNextContext ) else
{ pSVData->maGDIData.mpFirstContext = mpNextContext;
if( mpPrevContext ) mpNextContext->mpPrevContext = mpPrevContext;
mpPrevContext->mpNextContext = mpNextContext;
else
pSVData->maGDIData.mpFirstContext = mpNextContext;
mpNextContext->mpPrevContext = mpPrevContext;
mpPrevContext = pSVData->maGDIData.mpLastContext; mpPrevContext = pSVData->maGDIData.mpLastContext;
mpNextContext = NULL; mpNextContext = NULL;
pSVData->maGDIData.mpLastContext->mpNextContext = this; pSVData->maGDIData.mpLastContext->mpNextContext = this;
pSVData->maGDIData.mpLastContext = this; pSVData->maGDIData.mpLastContext = this;
}
} }
#endif
} }
void OpenGLContext::resetCurrent() void OpenGLContext::resetCurrent()
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "vcl/printerinfomanager.hxx" #include "vcl/printerinfomanager.hxx"
#include "vcl/settings.hxx" #include "vcl/settings.hxx"
#include "vcl/bmpacc.hxx" #include "vcl/bmpacc.hxx"
#include "vcl/opengl/OpenGLContext.hxx"
#include <prex.h> #include <prex.h>
#include <X11/Xatom.h> #include <X11/Xatom.h>
...@@ -65,6 +66,7 @@ ...@@ -65,6 +66,7 @@
#include <sal/macros.h> #include <sal/macros.h>
#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/uno/Exception.hpp>
#include "svdata.hxx"
#include "svids.hrc" #include "svids.hrc"
#include "impbmp.hxx" #include "impbmp.hxx"
...@@ -889,6 +891,15 @@ X11SalFrame::~X11SalFrame() ...@@ -889,6 +891,15 @@ X11SalFrame::~X11SalFrame()
delete pFreeGraphics_; delete pFreeGraphics_;
} }
// reset all OpenGL contexts using this window
OpenGLContext* pContext = ImplGetSVData()->maGDIData.mpLastContext;
while( pContext )
{
if( pContext->getOpenGLWindow().win == mhWindow )
pContext->reset();
pContext = pContext->mpPrevContext;
}
XDestroyWindow( GetXDisplay(), mhWindow ); XDestroyWindow( GetXDisplay(), mhWindow );
/* /*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment