diff options
author | Louis-Francis Ratté-Boulianne <lfrb@collabora.com> | 2014-11-22 07:58:38 -0500 |
---|---|---|
committer | Jan Holesovsky <kendy@collabora.com> | 2014-12-02 15:47:21 +0100 |
commit | 8b0954e2619ccd82a8ccb1426734bcab2068f89c (patch) | |
tree | a2386f01c82a249eb61342eee10fc19ca7a9ef96 /vcl/opengl | |
parent | 260a0b53b758daa79aa6a87d07537841821d25ff (diff) |
vcl: Always use the same OpenGL context when drawing in a window
Change-Id: Ief0e947149c133aaa8e81973e088c4df6432bfdc
Diffstat (limited to 'vcl/opengl')
-rw-r--r-- | vcl/opengl/gdiimpl.cxx | 142 | ||||
-rw-r--r-- | vcl/opengl/win/gdiimpl.cxx | 30 | ||||
-rw-r--r-- | vcl/opengl/x11/gdiimpl.cxx | 56 |
3 files changed, 173 insertions, 55 deletions
diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx index 6432fde53bca..3ecbac38252a 100644 --- a/vcl/opengl/gdiimpl.cxx +++ b/vcl/opengl/gdiimpl.cxx @@ -31,6 +31,7 @@ #include <vcl/opengl/OpenGLHelper.hxx> #include "salgdi.hxx" +#include "svdata.hxx" #include "opengl/salbmp.hxx" #include <glm/glm.hpp> @@ -63,8 +64,7 @@ 1.0f ) OpenGLSalGraphicsImpl::OpenGLSalGraphicsImpl() - : mpFrame(NULL) - , mnPainting(0) + : mpContext(0) , mbUseScissor(false) , mbUseStencil(false) , mbOffscreen(false) @@ -109,11 +109,106 @@ OpenGLSalGraphicsImpl::OpenGLSalGraphicsImpl() OpenGLSalGraphicsImpl::~OpenGLSalGraphicsImpl() { + ReleaseContext(); +} + +bool OpenGLSalGraphicsImpl::AcquireContext( bool bOffscreen ) +{ + ImplSVData* pSVData = ImplGetSVData(); + + if( mpContext ) + mpContext->DeRef(); + + if( bOffscreen ) + { + mpContext = CreatePixmapContext(); + return (mpContext != NULL); + } + + OpenGLContext* pContext = pSVData->maGDIData.mpLastContext; + while( pContext ) + { + // check if this context can be used by this SalGraphicsImpl instance + if( CompareWinContext( pContext ) ) + break; + pContext = pContext->mpPrevContext; + } + + if( pContext ) + pContext->AddRef(); + else + pContext = CreateWinContext(); + + mpContext = pContext; + return (mpContext != NULL); +} + +bool OpenGLSalGraphicsImpl::ReleaseContext() +{ + if( mpContext ) + mpContext->DeRef(); + mpContext = NULL; + return true; +} + +void OpenGLSalGraphicsImpl::Init() +{ + const bool bOffscreen = IsOffscreen(); + + // check if we can simply re-use the same context + if( mpContext ) + { + if( bOffscreen != mbOffscreen || ( !mbOffscreen && CompareWinContext( mpContext ) ) ) + ReleaseContext(); + } + + if( !mpContext && !AcquireContext( bOffscreen ) ) + { + SAL_WARN( "vcl.opengl", "Couldn't acquire context for SalGraphics" ); + return; + } + + mpContext->makeCurrent(); + + if( mbOffscreen == bOffscreen ) + { + // Nothing more to do for onscreen case + if( !mbOffscreen ) + return; + + // Already enabled and same size + if( maOffscreenTex.GetWidth() == GetWidth() && + maOffscreenTex.GetHeight() == GetHeight() ) + return; + } + else + { + mbOffscreen = bOffscreen; + if( bOffscreen ) + glGenFramebuffers( 1, &mnFramebufferId ); + else + glDeleteFramebuffers( 1, &mnFramebufferId ); + } + + // Create/update attached offscreen texture + if( mbOffscreen ) + { + glBindFramebuffer( GL_FRAMEBUFFER, mnFramebufferId ); + maOffscreenTex = OpenGLTexture( GetWidth(), GetHeight() ); + glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, maOffscreenTex.Id(), 0 ); + GLenum nStatus = glCheckFramebufferStatus( GL_FRAMEBUFFER ); + if( nStatus != GL_FRAMEBUFFER_COMPLETE ) + SAL_WARN( "vcl.opengl", "Incomplete framebuffer " << nStatus ); + glBindFramebuffer( GL_FRAMEBUFFER, 0 ); + CHECK_GL_ERROR(); + } } void OpenGLSalGraphicsImpl::PreDraw() { - maContext.makeCurrent(); + assert( mpContext && mpContext->isInitialized() ); + + mpContext->makeCurrent(); // TODO: lfrb: make sure the render target has the right size if( mbOffscreen ) CheckOffscreenTexture(); @@ -273,46 +368,17 @@ void OpenGLSalGraphicsImpl::SetROPFillColor( SalROPColor /*nROPColor*/ ) { } -// enable/disbale offscreen rendering -void OpenGLSalGraphicsImpl::SetOffscreen( bool bOffscreen ) -{ - if( bOffscreen == mbOffscreen ) - { - // Already disabled - if( !mbOffscreen ) - return; - - // Already enabled and same size - if( maOffscreenTex.GetWidth() == GetWidth() && - maOffscreenTex.GetHeight() == GetHeight() ) - return; - } - else - { - mbOffscreen = bOffscreen; - if( bOffscreen ) - glGenFramebuffers( 1, &mnFramebufferId ); - else - glDeleteFramebuffers( 1, &mnFramebufferId ); - } - - if( mbOffscreen ) - { - glBindFramebuffer( GL_FRAMEBUFFER, mnFramebufferId ); - maOffscreenTex = OpenGLTexture( GetWidth(), GetHeight() ); - glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, maOffscreenTex.Id(), 0 ); - glBindFramebuffer( GL_FRAMEBUFFER, 0 ); - } - - CHECK_GL_ERROR(); -} - bool OpenGLSalGraphicsImpl::CheckOffscreenTexture() { glBindFramebuffer( GL_FRAMEBUFFER, mnFramebufferId ); if( maOffscreenTex.IsUnique() ) + { + GLenum nStatus = glCheckFramebufferStatus( GL_FRAMEBUFFER ); + if( nStatus != GL_FRAMEBUFFER_COMPLETE ) + SAL_WARN( "vcl.opengl", "Incomplete framebuffer " << nStatus ); return true; + } SalTwoRect aPosAry; aPosAry.mnSrcX = aPosAry.mnDestX = 0; @@ -1808,7 +1874,7 @@ void OpenGLSalGraphicsImpl::endPaint() SAL_INFO( "vcl.opengl", "END PAINT " << this ); if( mnPainting == 0 ) { - maContext.makeCurrent(); + mpContext->makeCurrent(); glFlush(); } } diff --git a/vcl/opengl/win/gdiimpl.cxx b/vcl/opengl/win/gdiimpl.cxx index 18e0da860e6b..08159278f576 100644 --- a/vcl/opengl/win/gdiimpl.cxx +++ b/vcl/opengl/win/gdiimpl.cxx @@ -68,4 +68,34 @@ GLfloat WinOpenGLSalGraphicsImpl::GetHeight() const return 1; } +bool WinOpenGLSalGraphicsImpl::IsOffscreen() const +{ + WinSalFrame* pFrame = GetWindowPtr( mrParent.gethWnd() ); + return ( pFrame == NULL ); +} + +OpenGLContext* WinOpenGLSalGraphicsImpl::CreateWinContext() +{ + OpenGLContext* pContext = new OpenGLContext(); + pContext->requestSingleBufferedRendering(); + pContext->init( mrParent.mhLocalDC, mrParent.mhWnd ); + return pContext; +} + +bool WinOpenGLSalGraphicsImpl::CompareWinContext( OpenGLContext* pContext ) +{ + if( !pContext || !pContext->isInitialized() ) + return false; + return ( pContext->getOpenGLWindow().hWnd == mrParent.mhWnd ); +} + +OpenGLContext* WinOpenGLSalGraphicsImpl::CreatePixmapContext() +{ + OpenGLContext* pContext = new OpenGLContext(); + pContext->requestVirtualDevice(); + pContext->requestSingleBufferedRendering(); + pContext->init( mrParent.mhLocalDC, mrParent.mhWnd ); + return pContext; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/opengl/x11/gdiimpl.cxx b/vcl/opengl/x11/gdiimpl.cxx index afaea924601c..0a8bf681484e 100644 --- a/vcl/opengl/x11/gdiimpl.cxx +++ b/vcl/opengl/x11/gdiimpl.cxx @@ -59,31 +59,53 @@ GLfloat X11OpenGLSalGraphicsImpl::GetHeight() const return 1; } -void X11OpenGLSalGraphicsImpl::Init() +bool X11OpenGLSalGraphicsImpl::IsOffscreen() const { X11WindowProvider *pProvider = dynamic_cast<X11WindowProvider*>(mrParent.m_pFrame); - - // Called after eg. a vdev re-size where we need to update the underlying pixmap - maContext.resetToReInitialize(); - if (pProvider) - { - Window aWin = pProvider->GetX11Window(); - maContext.init( mrParent.GetXDisplay(), aWin, mrParent.m_nXScreen.getXScreen()); - SetOffscreen( false ); - } + if( pProvider ) + return false; else if( mrParent.m_pVDev ) - { - maContext.init( mrParent.GetXDisplay(), mrParent.m_pVDev->GetDrawable(), - mrParent.m_pVDev->GetWidth(), mrParent.m_pVDev->GetHeight(), - mrParent.m_nXScreen.getXScreen() ); - SetOffscreen( true ); - } + return true; else { SAL_WARN( "vcl.opengl", "what happened here?" ); + return true; } } +OpenGLContext* X11OpenGLSalGraphicsImpl::CreateWinContext() +{ + X11WindowProvider *pProvider = dynamic_cast<X11WindowProvider*>(mrParent.m_pFrame); + + if( !pProvider ) + return NULL; + Window aWin = pProvider->GetX11Window(); + OpenGLContext* pContext = new OpenGLContext(); + pContext->init( mrParent.GetXDisplay(), aWin, + mrParent.m_nXScreen.getXScreen() ); + return pContext; +} + +bool X11OpenGLSalGraphicsImpl::CompareWinContext( OpenGLContext* pContext ) +{ + X11WindowProvider *pProvider = dynamic_cast<X11WindowProvider*>(mrParent.m_pFrame); + + if( !pProvider || !pContext->isInitialized() ) + return false; + return ( pContext->getOpenGLWindow().win == pProvider->GetX11Window() ); +} + +OpenGLContext* X11OpenGLSalGraphicsImpl::CreatePixmapContext() +{ + if( mrParent.m_pVDev == NULL ) + return NULL; + OpenGLContext* pContext = new OpenGLContext(); + pContext->init( mrParent.GetXDisplay(), mrParent.m_pVDev->GetDrawable(), + mrParent.m_pVDev->GetWidth(), mrParent.m_pVDev->GetHeight(), + mrParent.m_nXScreen.getXScreen() ); + return pContext; +} + void X11OpenGLSalGraphicsImpl::copyBits( const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics ) { OpenGLSalGraphicsImpl *pImpl = pSrcGraphics ? static_cast< OpenGLSalGraphicsImpl* >(pSrcGraphics->GetImpl()) : static_cast< OpenGLSalGraphicsImpl *>(mrParent.GetImpl()); @@ -104,7 +126,7 @@ bool X11OpenGLSalGraphicsImpl::FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, return false; // make sure everything is synced up before reading back - maContext.makeCurrent(); + mpContext->makeCurrent(); glXWaitX(); // TODO: lfrb: What if offscreen? |