summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/vcl/opengl/OpenGLContext.hxx2
-rw-r--r--vcl/opengl/salbmp.cxx2
-rw-r--r--vcl/source/opengl/OpenGLContext.cxx183
-rw-r--r--vcl/unx/generic/window/salframe.cxx11
4 files changed, 137 insertions, 61 deletions
diff --git a/include/vcl/opengl/OpenGLContext.hxx b/include/vcl/opengl/OpenGLContext.hxx
index a78972cf6a5f..21f45d207d6f 100644
--- a/include/vcl/opengl/OpenGLContext.hxx
+++ b/include/vcl/opengl/OpenGLContext.hxx
@@ -204,6 +204,7 @@ public:
#elif defined( _WIN32 )
bool init( HDC hDC, HWND hWnd );
#endif
+ void reset();
// use these methods right after setting a context to make sure drawing happens
// in the right FBO (default one is for onscreen painting)
@@ -218,6 +219,7 @@ public:
OpenGLProgram* GetProgram( const OUString& rVertexShader, const OUString& rFragmentShader );
OpenGLProgram* UseProgram( const OUString& rVertexShader, const OUString& rFragmentShader );
+ bool isCurrent();
void makeCurrent();
void resetCurrent();
void swapBuffers();
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 );
/*