diff options
Diffstat (limited to 'vcl/source/opengl/OpenGLContext.cxx')
-rw-r--r-- | vcl/source/opengl/OpenGLContext.cxx | 124 |
1 files changed, 112 insertions, 12 deletions
diff --git a/vcl/source/opengl/OpenGLContext.cxx b/vcl/source/opengl/OpenGLContext.cxx index caf3d3022293..3eb7d25462dd 100644 --- a/vcl/source/opengl/OpenGLContext.cxx +++ b/vcl/source/opengl/OpenGLContext.cxx @@ -29,6 +29,9 @@ #include "svdata.hxx" +#include <opengl/framebuffer.hxx> +#include <opengl/texture.hxx> + using namespace com::sun::star; // TODO use rtl::Static instead of 'static' @@ -53,6 +56,9 @@ OpenGLContext::OpenGLContext(): mbRequestLegacyContext(false), mbUseDoubleBufferedRendering(true), mbRequestVirtualDevice(false), + mpCurrentFramebuffer(NULL), + mpFirstFramebuffer(NULL), + mpLastFramebuffer(NULL), mnPainting(0), mpPrevContext(NULL), mpNextContext(NULL) @@ -74,15 +80,6 @@ OpenGLContext::OpenGLContext(): OpenGLContext::~OpenGLContext() { -#if defined( WNT ) - if (m_aGLWin.hRC) - { - vShareList.erase(std::remove(vShareList.begin(), vShareList.end(), m_aGLWin.hRC)); - - wglMakeCurrent( m_aGLWin.hDC, 0 ); - wglDeleteContext( m_aGLWin.hRC ); - ReleaseDC( m_aGLWin.hWnd, m_aGLWin.hDC ); - } ImplSVData* pSVData = ImplGetSVData(); if( mpPrevContext ) mpPrevContext->mpNextContext = mpNextContext; @@ -93,6 +90,15 @@ OpenGLContext::~OpenGLContext() else pSVData->maGDIData.mpLastContext = mpPrevContext; +#if defined( WNT ) + if (m_aGLWin.hRC) + { + vShareList.erase(std::remove(vShareList.begin(), vShareList.end(), m_aGLWin.hRC)); + + 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 ) @@ -579,6 +585,7 @@ void initOpenGLFunctionPointers() glXGetVisualFromFBConfig = (XVisualInfo*(*)(Display *dpy, GLXFBConfig config))glXGetProcAddressARB((GLubyte*)"glXGetVisualFromFBConfig"); // try to find a visual for the current set of attributes glXGetFBConfigAttrib = (int(*)(Display *dpy, GLXFBConfig config, int attribute, int* value))glXGetProcAddressARB((GLubyte*)"glXGetFBConfigAttrib"); glXCreateContextAttribsARB = (GLXContext(*) (Display*, GLXFBConfig, GLXContext, Bool, const int*)) glXGetProcAddressARB((const GLubyte *) "glXCreateContextAttribsARB");; + glXCreatePixmap = (GLXPixmap(*) (Display*, GLXFBConfig, Pixmap, const int*)) glXGetProcAddressARB((const GLubyte *) "glXCreatePixmap");; } Visual* getVisual(Display* dpy, Window win) @@ -663,6 +670,8 @@ bool OpenGLContext::init(Display* dpy, Pixmap pix, unsigned int width, unsigned if (!dpy) return false; + initOpenGLFunctionPointers(); + SAL_INFO("vcl.opengl", "init with pixmap"); m_aGLWin.dpy = dpy; m_aGLWin.Width = width; @@ -681,8 +690,6 @@ bool OpenGLContext::init(Display* dpy, Pixmap pix, unsigned int width, unsigned mbPixmap = true; - initOpenGLFunctionPointers(); - return ImplInit(); } @@ -1203,13 +1210,32 @@ 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) { - SAL_INFO("vcl.opengl", "OpenGLContext::makeCurrent(): Avoid setting the same context"); + ; // 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 + { + 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; + + mpPrevContext = pSVData->maGDIData.mpLastContext; + mpNextContext = NULL; + pSVData->maGDIData.mpLastContext->mpNextContext = this; + pSVData->maGDIData.mpLastContext = this; + } + } #endif } @@ -1282,4 +1308,78 @@ NSOpenGLView* OpenGLContext::getOpenGLView() } #endif +bool OpenGLContext::AcquireFramebuffer( OpenGLFramebuffer* pFramebuffer ) +{ + if( pFramebuffer != mpCurrentFramebuffer ) + { + // release the attached texture so it's available from the other contexts + //if( mpCurrentFramebuffer ) + // mpCurrentFramebuffer->DetachTexture(); + + if( pFramebuffer ) + pFramebuffer->Bind(); + else + mpCurrentFramebuffer->Unbind(); + mpCurrentFramebuffer = pFramebuffer; + } + + return true; +} + +bool OpenGLContext::AcquireDefaultFramebuffer() +{ + return AcquireFramebuffer( NULL ); +} + +OpenGLFramebuffer* OpenGLContext::AcquireFramebuffer( const OpenGLTexture& rTexture ) +{ + OpenGLFramebuffer* pFramebuffer = NULL; + OpenGLFramebuffer* pFreeFramebuffer = NULL; + + // check if there is already a framebuffer attached to that texture + pFramebuffer = mpLastFramebuffer; + while( pFramebuffer ) + { + if( pFramebuffer->IsAttached( rTexture ) ) + break; + if( !pFreeFramebuffer && pFramebuffer->IsFree() ) + pFreeFramebuffer = pFramebuffer; + pFramebuffer = pFramebuffer->mpPrevFramebuffer; + } + + // else use the first free framebuffer + if( !pFramebuffer && pFreeFramebuffer ) + pFramebuffer = pFreeFramebuffer; + + // if there isn't any free one, create a new one + if( !pFramebuffer ) + { + pFramebuffer = new OpenGLFramebuffer(); + if( mpLastFramebuffer ) + { + pFramebuffer->mpPrevFramebuffer = mpLastFramebuffer; + mpLastFramebuffer->mpNextFramebuffer = pFramebuffer; + mpLastFramebuffer = pFramebuffer; + } + else + { + mpFirstFramebuffer = pFramebuffer; + mpLastFramebuffer = pFramebuffer; + } + } + + AcquireFramebuffer( pFramebuffer ); + if( pFramebuffer->IsFree() ) + pFramebuffer->AttachTexture( rTexture ); + glViewport( 0, 0, rTexture.GetWidth(), rTexture.GetHeight() ); + + return pFramebuffer; +} + +void OpenGLContext::ReleaseFramebuffer( OpenGLFramebuffer* pFramebuffer ) +{ + if( pFramebuffer ) + pFramebuffer->DetachTexture(); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |