diff options
author | Louis-Francis Ratté-Boulianne <lfrb@collabora.com> | 2014-12-04 22:17:58 -0500 |
---|---|---|
committer | Markus Mohrhard <markus.mohrhard@collabora.co.uk> | 2014-12-11 07:57:31 +0100 |
commit | 2e512773095216acbac83e6fd71f6d0444263d70 (patch) | |
tree | bf17b3e97d8ee2448869b6bfa7ffce63f1397b72 /vcl | |
parent | f0f5f50243810762e27f1207b3c08b60ed888ee3 (diff) |
vcl: Reset context when the backend window is destroyed
Conflicts:
vcl/source/opengl/OpenGLContext.cxx
Change-Id: Ie2b93de8efe5ea56b0420adf23639c0153103385
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/opengl/salbmp.cxx | 2 | ||||
-rw-r--r-- | vcl/source/opengl/OpenGLContext.cxx | 183 | ||||
-rw-r--r-- | vcl/unx/generic/window/salframe.cxx | 11 |
3 files changed, 135 insertions, 61 deletions
diff --git a/vcl/opengl/salbmp.cxx b/vcl/opengl/salbmp.cxx index 20ef2c434caf..61d8358b22d2 100644 --- a/vcl/opengl/salbmp.cxx +++ b/vcl/opengl/salbmp.cxx @@ -471,6 +471,8 @@ void OpenGLSalBitmap::makeCurrent() // TODO: make sure we can really use the last used context mpContext = pSVData->maGDIData.mpLastContext; + while( mpContext && !mpContext->isInitialized() ) + mpContext = mpContext->mpPrevContext; if( !mpContext ) mpContext = GetBitmapContext(); assert(mpContext && "Couldn't get an OpenGL context"); diff --git a/vcl/source/opengl/OpenGLContext.cxx b/vcl/source/opengl/OpenGLContext.cxx index c068cd89d042..47150256fc05 100644 --- a/vcl/source/opengl/OpenGLContext.cxx +++ b/vcl/source/opengl/OpenGLContext.cxx @@ -84,6 +84,8 @@ OpenGLContext::OpenGLContext(): OpenGLContext::~OpenGLContext() { SAL_INFO("vcl.opengl", "delete context: " << this); + reset(); + ImplSVData* pSVData = ImplGetSVData(); if( mpPrevContext ) mpPrevContext->mpNextContext = mpNextContext; @@ -93,39 +95,6 @@ OpenGLContext::~OpenGLContext() mpNextContext->mpPrevContext = mpPrevContext; else 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() @@ -1162,6 +1131,86 @@ void OpenGLContext::initGLWindow(Visual* pVisual) #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 ) SystemWindowData OpenGLContext::generateWinData(vcl::Window* /*pParent*/, bool bRequestLegacyContext) @@ -1217,17 +1266,33 @@ SystemWindowData OpenGLContext::generateWinData(vcl::Window* pParent, bool) #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() { + ImplSVData* pSVData = ImplGetSVData(); + + if (isCurrent()) + return; + #if defined( WNT ) - if (wglGetCurrentContext() == 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)) + if (!wglMakeCurrent(m_aGLWin.hDC, m_aGLWin.hRC)) { SAL_WARN("vcl.opengl", "OpenGLContext::makeCurrent(): wglMakeCurrent failed: " << GetLastError()); + return; } #elif defined( MACOSX ) NSOpenGLView* pView = getOpenGLView(); @@ -1236,33 +1301,29 @@ void OpenGLContext::makeCurrent() // nothing #elif defined( UNX ) GLXDrawable nDrawable = mbPixmap ? m_aGLWin.glPix : m_aGLWin.win; - static int nSwitch = 0; - if (glXGetCurrentContext() == m_aGLWin.ctx && - glXGetCurrentDrawable() == nDrawable) + if (!glXMakeCurrent( m_aGLWin.dpy, nDrawable, m_aGLWin.ctx )) { - ; // no-op - } - else if (!glXMakeCurrent( m_aGLWin.dpy, nDrawable, m_aGLWin.ctx )) 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 << " *********"); - ImplSVData* pSVData = ImplGetSVData(); - if( mpNextContext ) - { - if( mpPrevContext ) - mpPrevContext->mpNextContext = mpNextContext; - else - pSVData->maGDIData.mpFirstContext = mpNextContext; - mpNextContext->mpPrevContext = mpPrevContext; + if( mpPrevContext ) + mpPrevContext->mpNextContext = mpNextContext; + else + pSVData->maGDIData.mpFirstContext = mpNextContext; + mpNextContext->mpPrevContext = mpPrevContext; - mpPrevContext = pSVData->maGDIData.mpLastContext; - mpNextContext = NULL; - pSVData->maGDIData.mpLastContext->mpNextContext = this; - pSVData->maGDIData.mpLastContext = this; - } + mpPrevContext = pSVData->maGDIData.mpLastContext; + mpNextContext = NULL; + pSVData->maGDIData.mpLastContext->mpNextContext = this; + pSVData->maGDIData.mpLastContext = this; } -#endif } void OpenGLContext::resetCurrent() diff --git a/vcl/unx/generic/window/salframe.cxx b/vcl/unx/generic/window/salframe.cxx index 4d3c244e5f91..5656748b1279 100644 --- a/vcl/unx/generic/window/salframe.cxx +++ b/vcl/unx/generic/window/salframe.cxx @@ -34,6 +34,7 @@ #include "vcl/printerinfomanager.hxx" #include "vcl/settings.hxx" #include "vcl/bmpacc.hxx" +#include "vcl/opengl/OpenGLContext.hxx" #include <prex.h> #include <X11/Xatom.h> @@ -65,6 +66,7 @@ #include <sal/macros.h> #include <com/sun/star/uno/Exception.hpp> +#include "svdata.hxx" #include "svids.hrc" #include "impbmp.hxx" @@ -889,6 +891,15 @@ X11SalFrame::~X11SalFrame() 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 ); /* |