Rebased ref, commits from common ancestor: commit f2a3a957110f19f3ddfea943d6afd167f8708292 Author: Michael Meeks <michael.me...@collabora.com> Date: Sat Dec 5 22:11:24 2015 +0000
vcl: bind stencil buffer for clipping vs. textures. Fixes complex (ie. non glScissor) clipping when rendering to textures: virtual-devices and/or (now) off-screen rendering. Also cleanup and document debug variables. Change-Id: Ia8289d02d4cb51161cdde8927ecc7b24c767db13 diff --git a/vcl/README.vars b/vcl/README.vars index 4f62333..bf85485 100644 --- a/vcl/README.vars +++ b/vcl/README.vars @@ -21,6 +21,8 @@ EMF_PLUS_DISABLE - use EMF rendering and ignore EMF+ specifics OpenGL ------ SAL_FORCEGL - force enable OpenGL +SAL_GL_NO_SWAP - disable buffer swapping if set (should show nothing) +SAL_GL_SLEEP_ON_SWAP - sleep for half a second on each swap-buffers. SAL_WITHOUT_WIDGET_CACHE - disable LRU caching of native widget texutres SAL_DISABLE_GLYPH_CACHING - don't render glyphs through OpenGL textures SAL_DISABLE_GL_WATCHDOG - don't start the thread that watches for broken GL drivers diff --git a/vcl/inc/opengl/texture.hxx b/vcl/inc/opengl/texture.hxx index f67b334..e57aa9e 100644 --- a/vcl/inc/opengl/texture.hxx +++ b/vcl/inc/opengl/texture.hxx @@ -37,6 +37,8 @@ public: int mnWidth; int mnHeight; GLenum mnFilter; + GLuint mnOptStencil; + bool mbHasOptStencil; std::unique_ptr<std::vector<int>> mpSlotReferences; int mnFreeSlots; @@ -76,7 +78,8 @@ public: } bool InitializeSlots(int nSlotSize); - int FindFreeSlot(); + int FindFreeSlot(); + GLuint AddStencil(); }; class VCL_DLLPUBLIC OpenGLTexture @@ -110,6 +113,9 @@ public: void Bind(); void Unbind(); void Read( GLenum nFormat, GLenum nType, sal_uInt8* pData ); + GLuint AddStencil(); + bool HasStencil() const; + GLuint StencilId() const; void SaveToFile(const OUString& rFileName); diff --git a/vcl/opengl/framebuffer.cxx b/vcl/opengl/framebuffer.cxx index c009ccb..464662d 100644 --- a/vcl/opengl/framebuffer.cxx +++ b/vcl/opengl/framebuffer.cxx @@ -72,6 +72,16 @@ void OpenGLFramebuffer::AttachTexture( const OpenGLTexture& rTexture ) mnHeight = rTexture.GetHeight(); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mnAttachedTexture, 0); CHECK_GL_ERROR(); + + GLuint nStencil = rTexture.StencilId(); + if( nStencil ) + { + VCL_GL_INFO( "Attaching stencil " << nStencil << " to framebuffer " << (int)mnId ); + glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, + GL_RENDERBUFFER, nStencil ); + CHECK_GL_ERROR(); + } + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); CHECK_GL_ERROR(); if (status != GL_FRAMEBUFFER_COMPLETE) @@ -87,6 +97,11 @@ void OpenGLFramebuffer::DetachTexture() mnAttachedTexture = 0; glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0 ); CHECK_GL_ERROR(); + + // FIXME: we could make this conditional on having a stencil ? + glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, + GL_RENDERBUFFER, 0 ); + CHECK_GL_ERROR(); } } diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx index 3266dea..05994dd 100644 --- a/vcl/opengl/gdiimpl.cxx +++ b/vcl/opengl/gdiimpl.cxx @@ -277,6 +277,20 @@ void OpenGLSalGraphicsImpl::freeResources() void OpenGLSalGraphicsImpl::ImplSetClipBit( const vcl::Region& rClip, GLuint nMask ) { glEnable( GL_STENCIL_TEST ); + + VCL_GL_INFO( "Adding complex clip / stencil" ); + GLuint nStencil = maOffscreenTex.StencilId(); + if( nStencil == 0 ) + { + nStencil = maOffscreenTex.AddStencil(); + glFramebufferRenderbuffer( + GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, + GL_RENDERBUFFER, nStencil ); + CHECK_GL_ERROR(); + } + // else - we associated the stencil in + // AcquireFrameBuffer / AttachTexture + CHECK_GL_ERROR(); glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE ); CHECK_GL_ERROR(); @@ -311,7 +325,7 @@ void OpenGLSalGraphicsImpl::ImplInitClipRegion() if( maClipRegion != mpContext->maClipRegion ) { mpContext->maClipRegion = maClipRegion; - if( maClipRegion.IsRectangle() ) + if( mbUseScissor ) { Rectangle aRect( maClipRegion.GetBoundRect() ); glScissor( aRect.Left(), GetHeight() - aRect.Bottom() - 1, aRect.GetWidth() + 1, aRect.GetHeight() + 1 ); @@ -476,7 +490,11 @@ bool OpenGLSalGraphicsImpl::CheckOffscreenTexture() if( bClearTexture ) { glDrawBuffer( GL_COLOR_ATTACHMENT0 ); +#if OSL_DEBUG_LEVEL > 0 // lets have some red debugging background. GLfloat clearColor[4] = { 1.0, 0, 0, 0 }; +#else + GLfloat clearColor[4] = { 1.0, 1.0, 1.0, 0 }; +#endif glClearBufferfv( GL_COLOR, 0, clearColor ); // FIXME: use glClearTexImage if we have it ? } @@ -2056,19 +2074,15 @@ void OpenGLSalGraphicsImpl::doFlush() pProgram->ApplyMatrix(GetWidth(), GetHeight(), 0.0); pProgram->SetVertices( &aVertices[0] ); - if (!getenv("NO_COPY")) - glDrawArrays( GL_TRIANGLE_FAN, 0, nPoints ); + glDrawArrays( GL_TRIANGLE_FAN, 0, nPoints ); pProgram->Clean(); glBindTexture( GL_TEXTURE_2D, 0 ); - if (!getenv("NO_SWAP")) - { + static bool bNoSwap = getenv("SAL_GL_NO_SWAP"); + if (!bNoSwap) mpWindowContext->swapBuffers(); - if (!getenv("NO_SLEEP")) - usleep(500 * 1000); - } } VCL_GL_INFO( "flushAndSwap - end." ); diff --git a/vcl/opengl/texture.cxx b/vcl/opengl/texture.cxx index b540e96..bf4aa1d 100644 --- a/vcl/opengl/texture.cxx +++ b/vcl/opengl/texture.cxx @@ -35,6 +35,7 @@ ImplOpenGLTexture::ImplOpenGLTexture( int nWidth, int nHeight, bool bAllocate ) mnWidth( nWidth ), mnHeight( nHeight ), mnFilter( GL_NEAREST ), + mnOptStencil( 0 ), mnFreeSlots(-1) { glGenTextures( 1, &mnTexture ); @@ -67,6 +68,7 @@ ImplOpenGLTexture::ImplOpenGLTexture( int nX, int nY, int nWidth, int nHeight ) mnWidth( nWidth ), mnHeight( nHeight ), mnFilter( GL_NEAREST ), + mnOptStencil( 0 ), mnFreeSlots(-1) { // FIXME We need the window height here @@ -99,6 +101,7 @@ ImplOpenGLTexture::ImplOpenGLTexture( int nWidth, int nHeight, int nFormat, int mnWidth( nWidth ), mnHeight( nHeight ), mnFilter( GL_NEAREST ), + mnOptStencil( 0 ), mnFreeSlots(-1) { if( !mnTexture ) @@ -126,6 +129,21 @@ ImplOpenGLTexture::ImplOpenGLTexture( int nWidth, int nHeight, int nFormat, int VCL_GL_INFO( "OpenGLTexture " << mnTexture << " " << nWidth << "x" << nHeight << " from data" ); } +GLuint ImplOpenGLTexture::AddStencil() +{ + assert( mnOptStencil == 0 ); + + glGenRenderbuffers( 1, &mnOptStencil ); + glBindRenderbuffer( GL_RENDERBUFFER, mnOptStencil ); + CHECK_GL_ERROR(); + VCL_GL_INFO( "Allocate stencil " << mnWidth << " x " << mnHeight ); + glRenderbufferStorage( GL_RENDERBUFFER, GL_STENCIL_INDEX, + mnWidth, mnHeight ); + CHECK_GL_ERROR(); + + return mnOptStencil; +} + ImplOpenGLTexture::~ImplOpenGLTexture() { VCL_GL_INFO( "~OpenGLTexture " << mnTexture ); @@ -136,9 +154,11 @@ ImplOpenGLTexture::~ImplOpenGLTexture() // Check we have been correctly un-bound from all framebuffers. ImplSVData* pSVData = ImplGetSVData(); rtl::Reference<OpenGLContext> pContext = pSVData->maGDIData.mpLastContext; - if (pContext.is()) + if( pContext.is() ) pContext->UnbindTextureFromFramebuffers( mnTexture ); + if( mnOptStencil != 0 ) + glDeleteRenderbuffers( 1, &mnOptStencil ); glDeleteTextures( 1, &mnTexture ); } } @@ -279,6 +299,24 @@ int OpenGLTexture::GetHeight() const return maRect.GetHeight(); } +bool OpenGLTexture::HasStencil() const +{ + return mpImpl && mpImpl->mnOptStencil != 0; +} + +GLuint OpenGLTexture::StencilId() const +{ + return mpImpl ? mpImpl->mnOptStencil : 0; +} + +GLuint OpenGLTexture::AddStencil() +{ + if (mpImpl) + return mpImpl->AddStencil(); + else + return 0; +} + void OpenGLTexture::GetCoord( GLfloat* pCoord, const SalTwoRect& rPosAry, bool bInverted ) const { VCL_GL_INFO( "Getting coord " << Id() << " [" << maRect.Left() << "," << maRect.Top() << "] " << GetWidth() << "x" << GetHeight() ); diff --git a/vcl/source/opengl/OpenGLContext.cxx b/vcl/source/opengl/OpenGLContext.cxx index fb50f90..ed1347d 100644 --- a/vcl/source/opengl/OpenGLContext.cxx +++ b/vcl/source/opengl/OpenGLContext.cxx @@ -18,6 +18,8 @@ #include <vcl/bmpacc.hxx> #include <vcl/graph.hxx> +#include <osl/thread.hxx> + #if defined(MACOSX) #include <premac.h> #include "OpenGLWrapper.hxx" @@ -1486,6 +1488,14 @@ void OpenGLContext::swapBuffers() #elif defined( UNX ) glXSwapBuffers(m_aGLWin.dpy, m_aGLWin.win); #endif + + static bool bSleep = getenv("SAL_GL_SLEEP_ON_SWAP"); + if (bSleep) + { + // half a second. + TimeValue aSleep( 0, 500*1000*1000 ); + osl::Thread::wait( aSleep ); + } } void OpenGLContext::sync() _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits