summaryrefslogtreecommitdiff
path: root/vcl/opengl
diff options
context:
space:
mode:
authorLouis-Francis Ratté-Boulianne <lfrb@collabora.com>2014-11-22 07:58:38 -0500
committerJan Holesovsky <kendy@collabora.com>2014-12-02 15:47:21 +0100
commit8b0954e2619ccd82a8ccb1426734bcab2068f89c (patch)
treea2386f01c82a249eb61342eee10fc19ca7a9ef96 /vcl/opengl
parent260a0b53b758daa79aa6a87d07537841821d25ff (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.cxx142
-rw-r--r--vcl/opengl/win/gdiimpl.cxx30
-rw-r--r--vcl/opengl/x11/gdiimpl.cxx56
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?