summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorLouis-Francis Ratté-Boulianne <lfrb@collabora.com>2014-12-04 22:25:56 -0500
committerMarkus Mohrhard <markus.mohrhard@googlemail.com>2014-12-15 22:47:07 +0100
commitff55a35975e677b74d3b7632bbfc39b8633d6b0a (patch)
tree92e1a3271c523bee78fb66211afc61635a728bc1 /vcl
parenta6ba404dcaaf1e284f52e2a1e1b988274d35d7f9 (diff)
vcl: Re-use a framebuffer of the same size when possible
Conflicts: include/vcl/opengl/OpenGLContext.hxx Change-Id: Id9c7932976ce9d9282776c20d93d9cca4d290056
Diffstat (limited to 'vcl')
-rw-r--r--vcl/inc/opengl/framebuffer.hxx4
-rw-r--r--vcl/opengl/framebuffer.cxx4
-rw-r--r--vcl/opengl/gdiimpl.cxx12
-rw-r--r--vcl/source/opengl/OpenGLContext.cxx88
4 files changed, 89 insertions, 19 deletions
diff --git a/vcl/inc/opengl/framebuffer.hxx b/vcl/inc/opengl/framebuffer.hxx
index 4ccc1c5728ea..e9c9065f1edc 100644
--- a/vcl/inc/opengl/framebuffer.hxx
+++ b/vcl/inc/opengl/framebuffer.hxx
@@ -20,12 +20,16 @@ class VCL_PLUGIN_PUBLIC OpenGLFramebuffer
private:
GLuint mnId;
OpenGLTexture maAttachedTexture;
+ int mnWidth;
+ int mnHeight;
public:
OpenGLFramebuffer();
virtual ~OpenGLFramebuffer();
GLuint Id() const { return mnId; };
+ int GetWidth() const { return mnWidth; };
+ int GetHeight() const { return mnHeight; };
void Bind();
void Unbind();
diff --git a/vcl/opengl/framebuffer.cxx b/vcl/opengl/framebuffer.cxx
index 29f9a781130a..e760b53f614d 100644
--- a/vcl/opengl/framebuffer.cxx
+++ b/vcl/opengl/framebuffer.cxx
@@ -15,6 +15,8 @@
OpenGLFramebuffer::OpenGLFramebuffer() :
mnId( 0 ),
+ mnWidth( 0 ),
+ mnHeight( 0 ),
mpPrevFramebuffer( NULL ),
mpNextFramebuffer( NULL )
{
@@ -55,6 +57,8 @@ void OpenGLFramebuffer::AttachTexture( const OpenGLTexture& rTexture )
{
SAL_INFO( "vcl.opengl", "Attaching texture " << rTexture.Id() << " to framebuffer " << (int)mnId );
maAttachedTexture = rTexture;
+ mnWidth = rTexture.GetWidth();
+ mnHeight = rTexture.GetHeight();
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
maAttachedTexture.Id(), 0 );
CHECK_GL_ERROR();
diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index dcc4d85780b2..0e14fada7418 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -121,6 +121,8 @@ void OpenGLSalGraphicsImpl::Init()
maOffscreenTex.GetWidth() != GetWidth() ||
maOffscreenTex.GetHeight() != GetHeight() )
{
+ if( mpContext ) // valid context
+ mpContext->ReleaseFramebuffer( maOffscreenTex );
maOffscreenTex = OpenGLTexture();
}
}
@@ -162,15 +164,18 @@ void OpenGLSalGraphicsImpl::PostDraw()
mpProgram = NULL;
}
- mpContext->ReleaseFramebuffer( mpFramebuffer );
- mpFramebuffer = NULL;
-
CHECK_GL_ERROR();
}
void OpenGLSalGraphicsImpl::freeResources()
{
// TODO Delete shaders, programs and textures if not shared
+ if( mbOffscreen && mpContext && mpContext->isInitialized() )
+ {
+ mpContext->makeCurrent();
+ mpContext->ReleaseFramebuffer( maOffscreenTex );
+ }
+ ReleaseContext();
}
void OpenGLSalGraphicsImpl::ImplSetClipBit( const vcl::Region& rClip, GLuint nMask )
@@ -1584,6 +1589,7 @@ void OpenGLSalGraphicsImpl::endPaint()
if( mpContext->mnPainting == 0 && !mbOffscreen )
{
mpContext->makeCurrent();
+ mpContext->AcquireDefaultFramebuffer();
glFlush();
}
}
diff --git a/vcl/source/opengl/OpenGLContext.cxx b/vcl/source/opengl/OpenGLContext.cxx
index f662f2fc95d3..578cc02e84f1 100644
--- a/vcl/source/opengl/OpenGLContext.cxx
+++ b/vcl/source/opengl/OpenGLContext.cxx
@@ -35,6 +35,8 @@
using namespace com::sun::star;
+#define MAX_FRAMEBUFFER_COUNT 30
+
// TODO use rtl::Static instead of 'static'
#if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID
static std::vector<GLXContext> g_vShareList;
@@ -57,6 +59,7 @@ OpenGLContext::OpenGLContext():
mbRequestLegacyContext(false),
mbUseDoubleBufferedRendering(true),
mbRequestVirtualDevice(false),
+ mnFramebufferCount(0),
mpCurrentFramebuffer(NULL),
mpFirstFramebuffer(NULL),
mpLastFramebuffer(NULL),
@@ -1275,6 +1278,18 @@ bool OpenGLContext::isCurrent()
glXGetCurrentDrawable() == nDrawable);
#endif
}
+
+void OpenGLContext::clearCurrent()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // release all framebuffers from the old context so we can re-attach the
+ // texture in the new context
+ OpenGLContext* pCurrentCtx = pSVData->maGDIData.mpLastContext;
+ if( pCurrentCtx && pCurrentCtx->isCurrent() )
+ pCurrentCtx->ReleaseFramebuffers();
+}
+
void OpenGLContext::makeCurrent()
{
ImplSVData* pSVData = ImplGetSVData();
@@ -1282,6 +1297,8 @@ void OpenGLContext::makeCurrent()
if (isCurrent())
return;
+ clearCurrent();
+
#if defined( WNT )
if (!wglMakeCurrent(m_aGLWin.hDC, m_aGLWin.hRC))
{
@@ -1322,6 +1339,8 @@ void OpenGLContext::makeCurrent()
void OpenGLContext::resetCurrent()
{
+ clearCurrent();
+
#if defined( WNT )
wglMakeCurrent( m_aGLWin.hDC, 0 );
#elif defined( MACOSX )
@@ -1389,14 +1408,10 @@ NSOpenGLView* OpenGLContext::getOpenGLView()
}
#endif
-bool OpenGLContext::AcquireFramebuffer( OpenGLFramebuffer* pFramebuffer )
+bool OpenGLContext::BindFramebuffer( 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
@@ -1409,13 +1424,14 @@ bool OpenGLContext::AcquireFramebuffer( OpenGLFramebuffer* pFramebuffer )
bool OpenGLContext::AcquireDefaultFramebuffer()
{
- return AcquireFramebuffer( NULL );
+ return BindFramebuffer( NULL );
}
OpenGLFramebuffer* OpenGLContext::AcquireFramebuffer( const OpenGLTexture& rTexture )
{
OpenGLFramebuffer* pFramebuffer = NULL;
- OpenGLFramebuffer* pFreeFramebuffer = NULL;
+ OpenGLFramebuffer* pFreeFbo = NULL;
+ OpenGLFramebuffer* pSameSizeFbo = NULL;
// check if there is already a framebuffer attached to that texture
pFramebuffer = mpLastFramebuffer;
@@ -1423,18 +1439,27 @@ OpenGLFramebuffer* OpenGLContext::AcquireFramebuffer( const OpenGLTexture& rText
{
if( pFramebuffer->IsAttached( rTexture ) )
break;
- if( !pFreeFramebuffer && pFramebuffer->IsFree() )
- pFreeFramebuffer = pFramebuffer;
+ if( !pFreeFbo && pFramebuffer->IsFree() )
+ pFreeFbo = pFramebuffer;
+ if( !pSameSizeFbo &&
+ pFramebuffer->GetWidth() == rTexture.GetWidth() &&
+ pFramebuffer->GetHeight() == rTexture.GetHeight() )
+ pSameSizeFbo = pFramebuffer;
pFramebuffer = pFramebuffer->mpPrevFramebuffer;
}
+ // else use any framebuffer having the same size
+ if( !pFramebuffer && pSameSizeFbo )
+ pFramebuffer = pSameSizeFbo;
+
// else use the first free framebuffer
- if( !pFramebuffer && pFreeFramebuffer )
- pFramebuffer = pFreeFramebuffer;
+ if( !pFramebuffer && pFreeFbo )
+ pFramebuffer = pFreeFbo;
- // if there isn't any free one, create a new one
- if( !pFramebuffer )
+ // if there isn't any free one, create a new one if the limit isn't reached
+ if( !pFramebuffer && mnFramebufferCount < MAX_FRAMEBUFFER_COUNT )
{
+ mnFramebufferCount++;
pFramebuffer = new OpenGLFramebuffer();
if( mpLastFramebuffer )
{
@@ -1449,9 +1474,14 @@ OpenGLFramebuffer* OpenGLContext::AcquireFramebuffer( const OpenGLTexture& rText
}
}
- AcquireFramebuffer( pFramebuffer );
- if( pFramebuffer->IsFree() )
- pFramebuffer->AttachTexture( rTexture );
+ // last try, use any framebuffer
+ // TODO order the list of framebuffers as a LRU
+ if( !pFramebuffer )
+ pFramebuffer = mpFirstFramebuffer;
+
+ assert( pFramebuffer );
+ BindFramebuffer( pFramebuffer );
+ pFramebuffer->AttachTexture( rTexture );
glViewport( 0, 0, rTexture.GetWidth(), rTexture.GetHeight() );
return pFramebuffer;
@@ -1463,6 +1493,32 @@ void OpenGLContext::ReleaseFramebuffer( OpenGLFramebuffer* pFramebuffer )
pFramebuffer->DetachTexture();
}
+void OpenGLContext::ReleaseFramebuffer( const OpenGLTexture& rTexture )
+{
+ OpenGLFramebuffer* pFramebuffer = mpLastFramebuffer;
+
+ while( pFramebuffer )
+ {
+ if( pFramebuffer->IsAttached( rTexture ) )
+ {
+ BindFramebuffer( pFramebuffer );
+ pFramebuffer->DetachTexture();
+ }
+ pFramebuffer = pFramebuffer->mpPrevFramebuffer;
+ }
+}
+
+void OpenGLContext::ReleaseFramebuffers()
+{
+ OpenGLFramebuffer* pFramebuffer = mpLastFramebuffer;
+ while( pFramebuffer )
+ {
+ BindFramebuffer( pFramebuffer );
+ pFramebuffer->DetachTexture();
+ pFramebuffer = pFramebuffer->mpPrevFramebuffer;
+ }
+}
+
OpenGLProgram* OpenGLContext::GetProgram( const OUString& rVertexShader, const OUString& rFragmentShader )
{
boost::unordered_map<ProgramKey, OpenGLProgram*>::iterator it;