vcl: Use the current OpenGL context for VirtualDevice and Bitmap if possible

Conflicts:
	include/vcl/opengl/OpenGLContext.hxx
	vcl/inc/openglgdiimpl.hxx
	vcl/opengl/gdiimpl.cxx
	vcl/opengl/x11/gdiimpl.cxx
	vcl/source/opengl/OpenGLContext.cxx

Change-Id: I17f6ce66fb8b5bc027d35b4016ae56c24ee0a738
This commit is contained in:
Louis-Francis Ratté-Boulianne
2014-11-26 09:22:25 -05:00
committed by Markus Mohrhard
parent 83c97b2a1c
commit d6b51a87b4
25 changed files with 613 additions and 278 deletions

View File

@@ -65,10 +65,10 @@
OpenGLSalGraphicsImpl::OpenGLSalGraphicsImpl()
: mpContext(0)
, mpFramebuffer(NULL)
, mbUseScissor(false)
, mbUseStencil(false)
, mbOffscreen(false)
, mnFramebufferId(0)
, mnLineColor(SALCOLOR_NONE)
, mnFillColor(SALCOLOR_NONE)
, mnSolidProgram(0)
@@ -111,27 +111,30 @@ OpenGLSalGraphicsImpl::~OpenGLSalGraphicsImpl()
{
}
bool OpenGLSalGraphicsImpl::AcquireContext( bool bOffscreen )
OpenGLContext* OpenGLSalGraphicsImpl::GetOpenGLContext()
{
if( !mpContext )
AcquireContext();
return mpContext.get();
}
bool OpenGLSalGraphicsImpl::AcquireContext( )
{
ImplSVData* pSVData = ImplGetSVData();
if( bOffscreen )
{
mpContext.reset(CreatePixmapContext());
return (mpContext.get() != NULL);
}
mpContext.reset();
OpenGLContext* pContext = pSVData->maGDIData.mpLastContext;
while( pContext )
{
// check if this context can be used by this SalGraphicsImpl instance
if( CompareWinContext( pContext ) )
if( UseContext( pContext ) )
break;
pContext = pContext->mpPrevContext;
}
if (!pContext)
pContext =CreateWinContext();
pContext = mbOffscreen ? CreatePixmapContext() : CreateWinContext();
mpContext.reset(pContext);
return (mpContext != nullptr);
@@ -145,68 +148,41 @@ bool OpenGLSalGraphicsImpl::ReleaseContext()
void OpenGLSalGraphicsImpl::Init()
{
const bool bOffscreen = IsOffscreen();
mbOffscreen = IsOffscreen();
// check if we can simply re-use the same context
if( mpContext )
{
if( bOffscreen != mbOffscreen || ( !mbOffscreen && CompareWinContext( mpContext.get() ) ) )
if( !UseContext( mpContext.get() ) )
ReleaseContext();
}
if( !mpContext && !AcquireContext( bOffscreen ) )
// reset the offscreen texture
if( !mbOffscreen ||
maOffscreenTex.GetWidth() != GetWidth() ||
maOffscreenTex.GetHeight() != GetHeight() )
{
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();
maOffscreenTex = OpenGLTexture();
}
}
void OpenGLSalGraphicsImpl::PreDraw()
{
assert( mpContext && mpContext->isInitialized() );
if( !mpContext && !AcquireContext() )
{
SAL_WARN( "vcl.opengl", "Couldn't acquire context" );
return;
}
mpContext->makeCurrent();
// TODO: lfrb: make sure the render target has the right size
if( mbOffscreen )
CheckOffscreenTexture();
else
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
CHECK_GL_ERROR();
if( !mbOffscreen )
mpContext->AcquireDefaultFramebuffer();
else
CheckOffscreenTexture();
CHECK_GL_ERROR();
glViewport( 0, 0, GetWidth(), GetHeight() );
ImplInitClipRegion();
@@ -215,15 +191,16 @@ void OpenGLSalGraphicsImpl::PreDraw()
void OpenGLSalGraphicsImpl::PostDraw()
{
if( mbOffscreen )
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
else if( mpContext->mnPainting == 0 )
if( !mbOffscreen && mpContext->mnPainting == 0 )
glFlush();
if( mbUseScissor )
glDisable( GL_SCISSOR_TEST );
if( mbUseStencil )
glDisable( GL_STENCIL_TEST );
mpContext->ReleaseFramebuffer( mpFramebuffer );
mpFramebuffer = NULL;
CHECK_GL_ERROR();
}
@@ -279,6 +256,8 @@ void OpenGLSalGraphicsImpl::ImplInitClipRegion()
glStencilFunc( GL_EQUAL, 1, 0x1 );
glEnable( GL_STENCIL_TEST );
}
CHECK_GL_ERROR();
}
bool OpenGLSalGraphicsImpl::setClipRegion( const vcl::Region& rClip )
@@ -371,26 +350,25 @@ void OpenGLSalGraphicsImpl::SetROPFillColor( SalROPColor /*nROPColor*/ )
bool OpenGLSalGraphicsImpl::CheckOffscreenTexture()
{
glBindFramebuffer( GL_FRAMEBUFFER, mnFramebufferId );
if( !maOffscreenTex )
maOffscreenTex = OpenGLTexture( GetWidth(), GetHeight() );
if( maOffscreenTex.IsUnique() )
if( !maOffscreenTex.IsUnique() )
{
GLenum nStatus = glCheckFramebufferStatus( GL_FRAMEBUFFER );
if( nStatus != GL_FRAMEBUFFER_COMPLETE )
SAL_WARN( "vcl.opengl", "Incomplete framebuffer " << nStatus );
return true;
GLfloat fWidth = GetWidth();
GLfloat fHeight = GetHeight();
SalTwoRect aPosAry(0, 0, fWidth, fHeight, 0,0, fWidth, fHeight);
// TODO: lfrb: User GL_ARB_copy_image?
OpenGLTexture aNewTex = OpenGLTexture( GetWidth(), GetHeight() );
mpFramebuffer = mpContext->AcquireFramebuffer( aNewTex );
DrawTexture( maOffscreenTex, aPosAry );
maOffscreenTex = aNewTex;
}
else
{
mpFramebuffer = mpContext->AcquireFramebuffer( maOffscreenTex );
}
GLfloat fWidth = GetWidth();
GLfloat fHeight = GetHeight();
SalTwoRect aPosAry(0, 0, fWidth, fHeight, 0,0, fWidth, fHeight);
// TODO: improve performance: lfrb: User GL_ARB_copy_image?
OpenGLTexture aNewTex = OpenGLTexture( GetWidth(), GetHeight() );
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, aNewTex.Id(), 0 );
glViewport( 0, 0, GetWidth(), GetHeight() );
DrawTexture( maOffscreenTex, aPosAry );
maOffscreenTex = aNewTex;
CHECK_GL_ERROR();
return true;
@@ -1895,13 +1873,17 @@ bool OpenGLSalGraphicsImpl::drawGradient(const tools::PolyPolygon& rPolyPoly,
void OpenGLSalGraphicsImpl::beginPaint()
{
SAL_INFO( "vcl.opengl", "BEGIN PAINT " << this );
if( !mpContext && !AcquireContext() )
return;
mpContext->mnPainting++;
}
void OpenGLSalGraphicsImpl::endPaint()
{
SAL_INFO( "vcl.opengl", "END PAINT " << this );
if( !mpContext && !AcquireContext() )
return;
mpContext->mnPainting--;
assert( mpContext->mnPainting >= 0 );
if( mpContext->mnPainting == 0 && !mbOffscreen )