[Libreoffice-commits] core.git: Branch 'feature/opengl-vcl2' - 5 commits - include/vcl vcl/inc vcl/opengl vcl/source vcl/unx
Louis-Francis Ratté-Boulianne
lfrb at collabora.com
Thu Dec 4 19:28:48 PST 2014
include/vcl/opengl/OpenGLContext.hxx | 7
vcl/inc/cairotextrender.hxx | 1
vcl/inc/opengl/framebuffer.hxx | 8
vcl/inc/openglgdiimpl.hxx | 2
vcl/opengl/framebuffer.cxx | 26 +-
vcl/opengl/gdiimpl.cxx | 36 ++-
vcl/opengl/salbmp.cxx | 2
vcl/source/opengl/OpenGLContext.cxx | 255 ++++++++++++++++-------
vcl/unx/generic/gdi/cairotextrender.cxx | 4
vcl/unx/generic/gdi/openglx11cairotextrender.cxx | 48 +++-
vcl/unx/generic/gdi/openglx11cairotextrender.hxx | 1
vcl/unx/generic/gdi/x11cairotextrender.cxx | 6
vcl/unx/generic/gdi/x11cairotextrender.hxx | 1
vcl/unx/generic/window/salframe.cxx | 11
14 files changed, 299 insertions(+), 109 deletions(-)
New commits:
commit fb2574334c3da0630484de74d22a6f25d21d507a
Author: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
Date: Thu Dec 4 22:27:38 2014 -0500
vcl: Don't keep a reference to the texture in the FBO object
Change-Id: I240d2b44e77d28af3cd5952b6d666a1709c4c54a
diff --git a/vcl/inc/opengl/framebuffer.hxx b/vcl/inc/opengl/framebuffer.hxx
index e9c9065..915008c 100644
--- a/vcl/inc/opengl/framebuffer.hxx
+++ b/vcl/inc/opengl/framebuffer.hxx
@@ -18,10 +18,10 @@
class VCL_PLUGIN_PUBLIC OpenGLFramebuffer
{
private:
- GLuint mnId;
- OpenGLTexture maAttachedTexture;
+ GLuint mnId;
int mnWidth;
int mnHeight;
+ GLuint mnAttachedTexture;
public:
OpenGLFramebuffer();
diff --git a/vcl/opengl/framebuffer.cxx b/vcl/opengl/framebuffer.cxx
index e760b53..c4dfb05 100644
--- a/vcl/opengl/framebuffer.cxx
+++ b/vcl/opengl/framebuffer.cxx
@@ -17,6 +17,7 @@ OpenGLFramebuffer::OpenGLFramebuffer() :
mnId( 0 ),
mnWidth( 0 ),
mnHeight( 0 ),
+ mnAttachedTexture( 0 ),
mpPrevFramebuffer( NULL ),
mpNextFramebuffer( NULL )
{
@@ -45,30 +46,37 @@ void OpenGLFramebuffer::Unbind()
bool OpenGLFramebuffer::IsFree() const
{
- return (!maAttachedTexture);
+ return (!mnAttachedTexture);
}
bool OpenGLFramebuffer::IsAttached( const OpenGLTexture& rTexture ) const
{
- return ( maAttachedTexture == rTexture );
+ return ( mnAttachedTexture == rTexture.Id() );
}
void OpenGLFramebuffer::AttachTexture( const OpenGLTexture& rTexture )
{
+ if( rTexture.Id() == mnAttachedTexture )
+ return;
+
SAL_INFO( "vcl.opengl", "Attaching texture " << rTexture.Id() << " to framebuffer " << (int)mnId );
- maAttachedTexture = rTexture;
+ mnAttachedTexture = rTexture.Id();
mnWidth = rTexture.GetWidth();
mnHeight = rTexture.GetHeight();
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
- maAttachedTexture.Id(), 0 );
+ mnAttachedTexture, 0 );
CHECK_GL_ERROR();
}
void OpenGLFramebuffer::DetachTexture()
{
- maAttachedTexture = OpenGLTexture();
- glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0 );
- CHECK_GL_ERROR();
+ if( mnAttachedTexture != 0 )
+ {
+ CHECK_GL_ERROR();
+ mnAttachedTexture = 0;
+ glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0 );
+ CHECK_GL_ERROR();
+ }
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit f186da3f21c3b6633123be95131f62d6b390491e
Author: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
Date: Thu Dec 4 22:25:56 2014 -0500
vcl: Re-use a framebuffer of the same size when possible
Change-Id: Id9c7932976ce9d9282776c20d93d9cca4d290056
diff --git a/include/vcl/opengl/OpenGLContext.hxx b/include/vcl/opengl/OpenGLContext.hxx
index 84174c1..11d37fa 100644
--- a/include/vcl/opengl/OpenGLContext.hxx
+++ b/include/vcl/opengl/OpenGLContext.hxx
@@ -210,16 +210,19 @@ public:
// use these methods right after setting a context to make sure drawing happens
// in the right FBO (default one is for onscreen painting)
+ bool BindFramebuffer( OpenGLFramebuffer* pFramebuffer );
bool AcquireDefaultFramebuffer();
- bool AcquireFramebuffer( OpenGLFramebuffer* pFramebuffer );
OpenGLFramebuffer* AcquireFramebuffer( const OpenGLTexture& rTexture );
void ReleaseFramebuffer( OpenGLFramebuffer* pFramebuffer );
+ void ReleaseFramebuffer( const OpenGLTexture& rTexture );
+ void ReleaseFramebuffers();
// retrieve a program from the cache or compile/link it
OpenGLProgram* GetProgram( const OUString& rVertexShader, const OUString& rFragmentShader );
OpenGLProgram* UseProgram( const OUString& rVertexShader, const OUString& rFragmentShader );
bool isCurrent();
+ void clearCurrent();
void makeCurrent();
void resetCurrent();
void swapBuffers();
diff --git a/vcl/inc/opengl/framebuffer.hxx b/vcl/inc/opengl/framebuffer.hxx
index 4ccc1c5..e9c9065 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 29f9a78..e760b53 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 1cd61ea..c477f4e 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -119,6 +119,8 @@ void OpenGLSalGraphicsImpl::Init()
maOffscreenTex.GetWidth() != GetWidth() ||
maOffscreenTex.GetHeight() != GetHeight() )
{
+ if( mpContext ) // valid context
+ mpContext->ReleaseFramebuffer( maOffscreenTex );
maOffscreenTex = OpenGLTexture();
}
}
@@ -160,15 +162,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 )
@@ -1442,6 +1447,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 780bbf9..4093b5f 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> vShareList;
@@ -57,6 +59,7 @@ OpenGLContext::OpenGLContext():
mbRequestLegacyContext(false),
mbUseDoubleBufferedRendering(true),
mbRequestVirtualDevice(false),
+ mnFramebufferCount(0),
mpCurrentFramebuffer(NULL),
mpFirstFramebuffer(NULL),
mpLastFramebuffer(NULL),
@@ -1245,6 +1248,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();
@@ -1252,6 +1267,8 @@ void OpenGLContext::makeCurrent()
if (isCurrent())
return;
+ clearCurrent();
+
#if defined( WNT )
if (!wglMakeCurrent(m_aGLWin.hDC, m_aGLWin.hRC))
{
@@ -1292,6 +1309,8 @@ void OpenGLContext::makeCurrent()
void OpenGLContext::resetCurrent()
{
+ clearCurrent();
+
#if defined( WNT )
wglMakeCurrent( m_aGLWin.hDC, 0 );
#elif defined( MACOSX )
@@ -1359,14 +1378,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
@@ -1379,13 +1394,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;
@@ -1393,18 +1409,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 )
{
@@ -1419,9 +1444,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;
@@ -1433,6 +1463,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;
commit d6718423d36e83a13d01f098aaf32fc145cf6a33
Author: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
Date: Thu Dec 4 22:21:50 2014 -0500
vcl: Keep the same context for VirtualDevice to avoid FBO switches
Change-Id: I66496fae902db9df5b8301b00bb779f42adaa7a7
diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index c7423a4..1cd61ea 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -56,8 +56,8 @@ OpenGLSalGraphicsImpl::~OpenGLSalGraphicsImpl()
OpenGLContext* OpenGLSalGraphicsImpl::GetOpenGLContext()
{
- if( !mpContext )
- AcquireContext();
+ if( !AcquireContext() )
+ return NULL;
return mpContext;
}
@@ -71,7 +71,11 @@ bool OpenGLSalGraphicsImpl::AcquireContext( )
ImplSVData* pSVData = ImplGetSVData();
if( mpContext )
+ {
+ if( mpContext->isInitialized() )
+ return true;
mpContext->DeRef();
+ }
OpenGLContext* pContext = pSVData->maGDIData.mpLastContext;
while( pContext )
@@ -121,7 +125,7 @@ void OpenGLSalGraphicsImpl::Init()
void OpenGLSalGraphicsImpl::PreDraw()
{
- if( !mpContext && !AcquireContext() )
+ if( !AcquireContext() )
{
SAL_WARN( "vcl.opengl", "Couldn't acquire context" );
return;
@@ -160,11 +164,6 @@ void OpenGLSalGraphicsImpl::PostDraw()
mpFramebuffer = NULL;
CHECK_GL_ERROR();
-
- // release the context as there is no guarantee the underlying window
- // will still be valid for the next draw operation
- if( mbOffscreen )
- ReleaseContext();
}
void OpenGLSalGraphicsImpl::freeResources()
@@ -1427,7 +1426,7 @@ bool OpenGLSalGraphicsImpl::drawGradient(const tools::PolyPolygon& rPolyPoly,
void OpenGLSalGraphicsImpl::beginPaint()
{
- if( !mpContext && !AcquireContext() )
+ if( !AcquireContext() )
return;
mpContext->mnPainting++;
@@ -1435,7 +1434,7 @@ void OpenGLSalGraphicsImpl::beginPaint()
void OpenGLSalGraphicsImpl::endPaint()
{
- if( !mpContext && !AcquireContext() )
+ if( !AcquireContext() )
return;
mpContext->mnPainting--;
commit 5bf989edbb0bf83190665cc97cafdcdd6cdbe4a9
Author: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
Date: Thu Dec 4 22:17:58 2014 -0500
vcl: Reset context when the backind window is destroyed
Change-Id: Ie2b93de8efe5ea56b0420adf23639c0153103385
diff --git a/include/vcl/opengl/OpenGLContext.hxx b/include/vcl/opengl/OpenGLContext.hxx
index 6546dde..84174c1 100644
--- a/include/vcl/opengl/OpenGLContext.hxx
+++ b/include/vcl/opengl/OpenGLContext.hxx
@@ -203,6 +203,7 @@ public:
#elif defined( _WIN32 )
bool init( HDC hDC, HWND hWnd );
#endif
+ void reset();
void AddRef();
void DeRef();
@@ -218,6 +219,7 @@ public:
OpenGLProgram* GetProgram( const OUString& rVertexShader, const OUString& rFragmentShader );
OpenGLProgram* UseProgram( const OUString& rVertexShader, const OUString& rFragmentShader );
+ bool isCurrent();
void makeCurrent();
void resetCurrent();
void swapBuffers();
diff --git a/vcl/opengl/salbmp.cxx b/vcl/opengl/salbmp.cxx
index 20ef2c4..61d8358 100644
--- a/vcl/opengl/salbmp.cxx
+++ b/vcl/opengl/salbmp.cxx
@@ -471,6 +471,8 @@ void OpenGLSalBitmap::makeCurrent()
// TODO: make sure we can really use the last used context
mpContext = pSVData->maGDIData.mpLastContext;
+ while( mpContext && !mpContext->isInitialized() )
+ mpContext = mpContext->mpPrevContext;
if( !mpContext )
mpContext = GetBitmapContext();
assert(mpContext && "Couldn't get an OpenGL context");
diff --git a/vcl/source/opengl/OpenGLContext.cxx b/vcl/source/opengl/OpenGLContext.cxx
index 5dfdd54..780bbf9 100644
--- a/vcl/source/opengl/OpenGLContext.cxx
+++ b/vcl/source/opengl/OpenGLContext.cxx
@@ -82,6 +82,8 @@ OpenGLContext::OpenGLContext():
OpenGLContext::~OpenGLContext()
{
+ reset();
+
ImplSVData* pSVData = ImplGetSVData();
if( mpPrevContext )
mpPrevContext->mpNextContext = mpNextContext;
@@ -91,36 +93,6 @@ OpenGLContext::~OpenGLContext()
mpNextContext->mpPrevContext = mpPrevContext;
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 )
- // nothing
-#elif defined( UNX )
- if(m_aGLWin.ctx)
- {
- vShareList.erase(std::remove( vShareList.begin(), vShareList.end(), m_aGLWin.ctx ));
-
- glXMakeCurrent(m_aGLWin.dpy, None, NULL);
- if( glGetError() != GL_NO_ERROR )
- {
- SAL_WARN("vcl.opengl", "glError: " << (char *)gluErrorString(glGetError()));
- }
- glXDestroyContext(m_aGLWin.dpy, m_aGLWin.ctx);
-
- if (mbPixmap)
- glXDestroyGLXPixmap(m_aGLWin.dpy, m_aGLWin.glPix);
- }
-#endif
}
void OpenGLContext::AddRef()
@@ -1154,6 +1126,73 @@ void OpenGLContext::initGLWindow(Visual* pVisual)
#endif
+void OpenGLContext::reset()
+{
+ if( !mbInitialized )
+ return;
+
+ // reset the clip region
+ maClipRegion.SetEmpty();
+
+ // destroy all framebuffers
+ if( mpLastFramebuffer )
+ {
+ OpenGLFramebuffer* pFramebuffer = mpLastFramebuffer;
+
+ makeCurrent();
+ while( pFramebuffer )
+ {
+ OpenGLFramebuffer* pPrevFramebuffer = pFramebuffer->mpPrevFramebuffer;
+ delete pFramebuffer;
+ pFramebuffer = pPrevFramebuffer;
+ }
+ mpFirstFramebuffer = NULL;
+ mpLastFramebuffer = NULL;
+ }
+
+ // destroy all programs
+ if( !maPrograms.empty() )
+ {
+ boost::unordered_map<ProgramKey, OpenGLProgram*>::iterator it;
+
+ makeCurrent();
+ it = maPrograms.begin();
+ while( it != maPrograms.end() )
+ {
+ delete it->second;
+ it++;
+ }
+ maPrograms.clear();
+ }
+
+ if( isCurrent() )
+ resetCurrent();
+
+ mbInitialized = false;
+
+ // destroy the context itself
+#if defined( WNT )
+ if (m_aGLWin.hRC)
+ {
+ vShareList.erase(std::remove(vShareList.begin(), vShareList.end(), m_aGLWin.hRC));
+ wglDeleteContext( m_aGLWin.hRC );
+ ReleaseDC( m_aGLWin.hWnd, m_aGLWin.hDC );
+ }
+#elif defined( MACOSX )
+ // nothing
+#elif defined( IOS ) || defined( ANDROID )
+ // nothing
+#elif defined( UNX )
+ if(m_aGLWin.ctx)
+ {
+ vShareList.erase(std::remove( vShareList.begin(), vShareList.end(), m_aGLWin.ctx ));
+ glXDestroyContext(m_aGLWin.dpy, m_aGLWin.ctx);
+ if (mbPixmap)
+ glXDestroyGLXPixmap(m_aGLWin.dpy, m_aGLWin.glPix);
+ }
+#endif
+}
+
#if defined( WNT ) || defined( MACOSX ) || defined( IOS ) || defined( ANDROID )
SystemWindowData OpenGLContext::generateWinData(vcl::Window* /*pParent*/, bool bRequestLegacyContext)
@@ -1191,17 +1230,33 @@ SystemWindowData OpenGLContext::generateWinData(vcl::Window* pParent, bool)
#endif
+bool OpenGLContext::isCurrent()
+{
+#if defined( WNT )
+ return (wglGetCurrentContext() == m_aGLWin.hRC &&
+ wglGetCurrentDC() == m_aGLWin.hDC);
+#elif defined( MACOSX )
+ return false;
+#elif defined( IOS ) || defined( ANDROID )
+ return false;
+#elif defined( UNX )
+ GLXDrawable nDrawable = mbPixmap ? m_aGLWin.glPix : m_aGLWin.win;
+ return (glXGetCurrentContext() == m_aGLWin.ctx &&
+ glXGetCurrentDrawable() == nDrawable);
+#endif
+}
void OpenGLContext::makeCurrent()
{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if (isCurrent())
+ return;
+
#if defined( WNT )
- if (wglGetCurrentContext() == m_aGLWin.hRC &&
- wglGetCurrentDC() == m_aGLWin.hDC)
- {
- SAL_INFO("vcl.opengl", "OpenGLContext::makeCurrent(): Avoid setting the same context");
- }
- else if (!wglMakeCurrent(m_aGLWin.hDC, m_aGLWin.hRC))
+ if (!wglMakeCurrent(m_aGLWin.hDC, m_aGLWin.hRC))
{
SAL_WARN("vcl.opengl", "OpenGLContext::makeCurrent(): wglMakeCurrent failed: " << GetLastError());
+ return;
}
#elif defined( MACOSX )
NSOpenGLView* pView = getOpenGLView();
@@ -1210,33 +1265,29 @@ 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)
+ if (!glXMakeCurrent( m_aGLWin.dpy, nDrawable, m_aGLWin.ctx ))
{
- ; // 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
+ return;
+ }
+#endif
+
+ // move the context at the end of the contexts list
+ static int nSwitch = 0;
+ SAL_INFO("vcl.opengl", "******* CONTEXT SWITCH " << ++nSwitch << " *********");
+ if( mpNextContext )
{
- 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;
+ 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;
- }
+ mpPrevContext = pSVData->maGDIData.mpLastContext;
+ mpNextContext = NULL;
+ pSVData->maGDIData.mpLastContext->mpNextContext = this;
+ pSVData->maGDIData.mpLastContext = this;
}
-#endif
}
void OpenGLContext::resetCurrent()
diff --git a/vcl/unx/generic/window/salframe.cxx b/vcl/unx/generic/window/salframe.cxx
index ee94a19..ff63c7a 100644
--- a/vcl/unx/generic/window/salframe.cxx
+++ b/vcl/unx/generic/window/salframe.cxx
@@ -34,6 +34,7 @@
#include "vcl/printerinfomanager.hxx"
#include "vcl/settings.hxx"
#include "vcl/bmpacc.hxx"
+#include "vcl/opengl/OpenGLContext.hxx"
#include <prex.h>
#include <X11/Xatom.h>
@@ -65,6 +66,7 @@
#include <sal/macros.h>
#include <com/sun/star/uno/Exception.hpp>
+#include "svdata.hxx"
#include "svids.hrc"
#include "impbmp.hxx"
@@ -894,6 +896,15 @@ X11SalFrame::~X11SalFrame()
delete pFreeGraphics_;
}
+ // reset all OpenGL contexts using this window
+ OpenGLContext* pContext = ImplGetSVData()->maGDIData.mpLastContext;
+ while( pContext )
+ {
+ if( pContext->getOpenGLWindow().win == mhWindow )
+ pContext->reset();
+ pContext = pContext->mpPrevContext;
+ }
+
XDestroyWindow( GetXDisplay(), mhWindow );
/*
commit 5d717ae96c08c4a74641422ef99b359b56aa0630
Author: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
Date: Thu Dec 4 11:45:55 2014 -0500
vcl: Limit Cairo surface size to the clipping region to improve performance
Change-Id: I469b34c9f1047a274550229391d3dfb578291df6
diff --git a/vcl/inc/cairotextrender.hxx b/vcl/inc/cairotextrender.hxx
index e5db2ab..2b8a21e 100644
--- a/vcl/inc/cairotextrender.hxx
+++ b/vcl/inc/cairotextrender.hxx
@@ -77,6 +77,7 @@ class CairoTextRender : public TextRenderImpl
protected:
virtual GlyphCache& getPlatformGlyphCache() = 0;
virtual cairo_surface_t* getCairoSurface() = 0;
+ virtual void getSurfaceOffset(double& nDX, double& nDY) = 0;
virtual void drawSurface(cairo_t* cr) = 0;
bool setFont( const FontSelectPattern *pEntry, int nFallbackLevel );
diff --git a/vcl/inc/openglgdiimpl.hxx b/vcl/inc/openglgdiimpl.hxx
index 3a4222e..0011692 100644
--- a/vcl/inc/openglgdiimpl.hxx
+++ b/vcl/inc/openglgdiimpl.hxx
@@ -129,7 +129,9 @@ public:
virtual void freeResources() SAL_OVERRIDE;
+ virtual const vcl::Region& getClipRegion() const;
virtual bool setClipRegion( const vcl::Region& ) SAL_OVERRIDE;
+
//
// get the depth of the device
virtual sal_uInt16 GetBitCount() const SAL_OVERRIDE;
diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index 1fb59a2..c7423a4 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -224,6 +224,11 @@ void OpenGLSalGraphicsImpl::ImplInitClipRegion()
CHECK_GL_ERROR();
}
+const vcl::Region& OpenGLSalGraphicsImpl::getClipRegion() const
+{
+ return maClipRegion;
+}
+
bool OpenGLSalGraphicsImpl::setClipRegion( const vcl::Region& rClip )
{
SAL_INFO( "vcl.opengl", "::setClipRegion " << rClip );
diff --git a/vcl/unx/generic/gdi/cairotextrender.cxx b/vcl/unx/generic/gdi/cairotextrender.cxx
index 5b31b92..589b53a 100644
--- a/vcl/unx/generic/gdi/cairotextrender.cxx
+++ b/vcl/unx/generic/gdi/cairotextrender.cxx
@@ -222,6 +222,10 @@ void CairoTextRender::DrawServerFontLayout( const ServerFontLayout& rLayout )
if (const void *pOptions = Application::GetSettings().GetStyleSettings().GetCairoFontOptions())
cairo_set_font_options(cr, static_cast<const cairo_font_options_t*>(pOptions));
+ double nDX, nDY;
+ getSurfaceOffset(nDX, nDY);
+ cairo_translate(cr, nDX, nDY);
+
clipRegion(cr);
cairo_set_source_rgb(cr,
diff --git a/vcl/unx/generic/gdi/openglx11cairotextrender.cxx b/vcl/unx/generic/gdi/openglx11cairotextrender.cxx
index 38a7213..b49df00 100644
--- a/vcl/unx/generic/gdi/openglx11cairotextrender.cxx
+++ b/vcl/unx/generic/gdi/openglx11cairotextrender.cxx
@@ -25,32 +25,56 @@ cairo_surface_t* OpenGLX11CairoTextRender::getCairoSurface()
// static size_t id = 0;
// OString aFileName = OString("/tmp/libo_logs/text_rendering") + OString::number(id++) + OString(".svg");
// cairo_surface_t* surface = cairo_svg_surface_create(aFileName.getStr(), GetWidth(), GetHeight());
- cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, GetWidth(), GetHeight());
+ cairo_surface_t* surface = NULL;
+ OpenGLSalGraphicsImpl *pImpl = dynamic_cast< OpenGLSalGraphicsImpl* >(mrParent.GetImpl());
+ if( pImpl )
+ {
+ Rectangle aClipRect = pImpl->getClipRegion().GetBoundRect();
+ if( aClipRect.GetWidth() == 0 || aClipRect.GetHeight() == 0 )
+ {
+ aClipRect.setWidth( GetWidth() );
+ aClipRect.setHeight( GetHeight() );
+ }
+ surface = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, aClipRect.GetWidth(), aClipRect.GetHeight() );
+ }
return surface;
}
+void OpenGLX11CairoTextRender::getSurfaceOffset( double& nDX, double& nDY )
+{
+ OpenGLSalGraphicsImpl *pImpl = dynamic_cast< OpenGLSalGraphicsImpl* >(mrParent.GetImpl());
+ if( pImpl )
+ {
+ Rectangle aClipRect = pImpl->getClipRegion().GetBoundRect();
+ nDX = -aClipRect.Left();
+ nDY = -aClipRect.Top();
+ }
+}
+
void OpenGLX11CairoTextRender::drawSurface(cairo_t* cr)
{
- cairo_surface_t* pSurface = cairo_get_target(cr);
+ cairo_surface_t* pSurface = cairo_get_target( cr );
int nWidth = cairo_image_surface_get_width( pSurface );
int nHeight = cairo_image_surface_get_height( pSurface );
cairo_surface_flush( pSurface );
unsigned char *pSrc = cairo_image_surface_get_data( pSurface );
- SalTwoRect aRect;
- aRect.mnSrcX = 0;
- aRect.mnSrcY = 0;
- aRect.mnSrcWidth = nWidth;
- aRect.mnSrcHeight = nHeight;
- aRect.mnDestX = 0;
- aRect.mnDestY = 0;
- aRect.mnDestWidth = nWidth;
- aRect.mnDestHeight = nHeight;
-
// XXX: lfrb: GLES 2.0 doesn't support GL_UNSIGNED_INT_8_8_8_8_REV
OpenGLSalGraphicsImpl *pImpl = dynamic_cast< OpenGLSalGraphicsImpl* >(mrParent.GetImpl());
if( pImpl )
{
+ Rectangle aClipRect = pImpl->getClipRegion().GetBoundRect();
+
+ SalTwoRect aRect;
+ aRect.mnSrcX = 0;
+ aRect.mnSrcY = 0;
+ aRect.mnSrcWidth = nWidth;
+ aRect.mnSrcHeight = nHeight;
+ aRect.mnDestX = aClipRect.Left();
+ aRect.mnDestY = aClipRect.Top();
+ aRect.mnDestWidth = nWidth;
+ aRect.mnDestHeight = nHeight;
+
// Cairo surface data is ARGB with premultiplied alpha and is Y-inverted
OpenGLTexture aTexture( nWidth, nHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, pSrc );
pImpl->PreDraw();
diff --git a/vcl/unx/generic/gdi/openglx11cairotextrender.hxx b/vcl/unx/generic/gdi/openglx11cairotextrender.hxx
index 87ef948..1719496 100644
--- a/vcl/unx/generic/gdi/openglx11cairotextrender.hxx
+++ b/vcl/unx/generic/gdi/openglx11cairotextrender.hxx
@@ -18,6 +18,7 @@ public:
OpenGLX11CairoTextRender(bool bPrinter, X11SalGraphics& rParent);
virtual cairo_surface_t* getCairoSurface() SAL_OVERRIDE;
+ virtual void getSurfaceOffset(double& nDX, double& nDY) SAL_OVERRIDE;
virtual void drawSurface(cairo_t* cr) SAL_OVERRIDE;
};
diff --git a/vcl/unx/generic/gdi/x11cairotextrender.cxx b/vcl/unx/generic/gdi/x11cairotextrender.cxx
index 0449b98..f3aa47d 100644
--- a/vcl/unx/generic/gdi/x11cairotextrender.cxx
+++ b/vcl/unx/generic/gdi/x11cairotextrender.cxx
@@ -77,6 +77,12 @@ cairo_surface_t* X11CairoTextRender::getCairoSurface()
return surface;
}
+void X11CairoTextRender::getSurfaceOffset( double& nDX, double& nDY )
+{
+ nDX = 0;
+ nDY = 0;
+}
+
void X11CairoTextRender::clipRegion(cairo_t* cr)
{
Region pClipRegion = mrParent.mpClipRegion;
diff --git a/vcl/unx/generic/gdi/x11cairotextrender.hxx b/vcl/unx/generic/gdi/x11cairotextrender.hxx
index fb0c130..1449b3a 100644
--- a/vcl/unx/generic/gdi/x11cairotextrender.hxx
+++ b/vcl/unx/generic/gdi/x11cairotextrender.hxx
@@ -41,6 +41,7 @@ public:
virtual GlyphCache& getPlatformGlyphCache() SAL_OVERRIDE;
virtual cairo_surface_t* getCairoSurface() SAL_OVERRIDE;
+ virtual void getSurfaceOffset(double& nDX, double& nDY) SAL_OVERRIDE;
virtual void clipRegion(cairo_t* cr) SAL_OVERRIDE;
virtual void drawSurface(cairo_t* cr) SAL_OVERRIDE;
};
More information about the Libreoffice-commits
mailing list