[Libreoffice-commits] core.git: Branch 'private/mmeeks/opengl-backbuffer2' - vcl/inc vcl/opengl vcl/README.vars vcl/source

Michael Meeks michael.meeks at collabora.com
Wed Dec 9 06:09:43 PST 2015


Rebased ref, commits from common ancestor:
commit f2a3a957110f19f3ddfea943d6afd167f8708292
Author: Michael Meeks <michael.meeks at 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()


More information about the Libreoffice-commits mailing list