[Libreoffice-commits] core.git: Branch 'feature/fixes20' - 3 commits - include/vcl vcl/inc vcl/opengl vcl/source

Tomaž Vajngerl tomaz.vajngerl at collabora.co.uk
Thu Apr 28 12:23:59 UTC 2016


 include/vcl/opengl/OpenGLContext.hxx |    8 ++
 vcl/inc/opengl/RenderState.hxx       |  122 +++++++++++++++++++++++++++++++++++
 vcl/inc/opengl/TextureState.hxx      |   76 +++++++++++++++++++++
 vcl/opengl/gdiimpl.cxx               |   84 +++++++++++-------------
 vcl/opengl/program.cxx               |   26 +++----
 vcl/opengl/salbmp.cxx                |   14 +++-
 vcl/opengl/scale.cxx                 |    3 
 vcl/opengl/texture.cxx               |   60 ++++++++---------
 vcl/opengl/x11/gdiimpl.cxx           |    5 -
 vcl/source/opengl/OpenGLContext.cxx  |    3 
 10 files changed, 308 insertions(+), 93 deletions(-)

New commits:
commit 2a1a72da11961a0cad6a72938dcd2bb52af6c78f
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Thu Apr 28 20:01:28 2016 +0900

    opengl: track the state of stencil test
    
    Change-Id: Id3e15e91316df740f04a42ed8c95b77d83240b5a

diff --git a/vcl/inc/opengl/RenderState.hxx b/vcl/inc/opengl/RenderState.hxx
index 7b3db7be..b1b0b18 100644
--- a/vcl/inc/opengl/RenderState.hxx
+++ b/vcl/inc/opengl/RenderState.hxx
@@ -69,10 +69,44 @@ public:
     }
 };
 
+class StencilState
+{
+    bool mbTest;
+public:
+
+    StencilState()
+        : mbTest(false)
+    {
+        glDisable(GL_STENCIL_TEST);
+        CHECK_GL_ERROR();
+    }
+
+    void enable()
+    {
+        if (!mbTest)
+        {
+            glEnable(GL_STENCIL_TEST);
+            CHECK_GL_ERROR();
+            mbTest = true;
+        }
+    }
+
+    void disable()
+    {
+        if (mbTest)
+        {
+            glDisable(GL_STENCIL_TEST);
+            CHECK_GL_ERROR();
+            mbTest = false;
+        }
+    }
+};
+
 class RenderState
 {
     TextureState maTexture;
     ScissorState maScissor;
+    StencilState maStencil;
 
 public:
     RenderState()
@@ -80,6 +114,7 @@ public:
 
     TextureState& texture() { return maTexture; }
     ScissorState& scissor() { return maScissor; }
+    StencilState& stencil() { return maStencil; }
 };
 
 #endif // INCLUDED_VCL_INC_OPENGL_RENDER_STATE_H
diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index 6f54ad0..3eb72d4 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -232,11 +232,6 @@ void OpenGLSalGraphicsImpl::PostDraw()
         CHECK_GL_ERROR();
     }
 
-    if( mbUseStencil )
-    {
-        glDisable( GL_STENCIL_TEST );
-        CHECK_GL_ERROR();
-    }
     if( mpProgram )
     {
         mpProgram->Clean();
@@ -269,6 +264,7 @@ void OpenGLSalGraphicsImpl::freeResources()
         mpContext->makeCurrent();
         FlushDeferredDrawing();
         mpContext->state()->scissor().disable();
+        mpContext->state()->stencil().disable();
         mpContext->ReleaseFramebuffer( maOffscreenTex );
     }
     ReleaseContext();
@@ -276,7 +272,7 @@ void OpenGLSalGraphicsImpl::freeResources()
 
 void OpenGLSalGraphicsImpl::ImplSetClipBit( const vcl::Region& rClip, GLuint nMask )
 {
-    glEnable( GL_STENCIL_TEST );
+    mpContext->state()->stencil().enable();
 
     VCL_GL_INFO( "Adding complex clip / stencil" );
     GLuint nStencil = maOffscreenTex.StencilId();
@@ -315,8 +311,8 @@ void OpenGLSalGraphicsImpl::ImplSetClipBit( const vcl::Region& rClip, GLuint nMa
     CHECK_GL_ERROR();
     glStencilMask( 0x00 );
     CHECK_GL_ERROR();
-    glDisable( GL_STENCIL_TEST );
-    CHECK_GL_ERROR();
+
+    mpContext->state()->stencil().disable();
 }
 
 void OpenGLSalGraphicsImpl::ImplInitClipRegion()
@@ -346,8 +342,11 @@ void OpenGLSalGraphicsImpl::ImplInitClipRegion()
     {
         glStencilFunc( GL_EQUAL, 1, 0x1 );
         CHECK_GL_ERROR();
-        glEnable( GL_STENCIL_TEST );
-        CHECK_GL_ERROR();
+        mpContext->state()->stencil().enable();
+    }
+    else
+    {
+        mpContext->state()->stencil().disable();
     }
 }
 
@@ -1501,11 +1500,7 @@ void OpenGLSalGraphicsImpl::DrawTransformedTexture(
             // so if we do not disable the scissor test, the texture produced
             // by the first downscaling is clipped to the current window size.
             mpContext->state()->scissor().disable();
-            CHECK_GL_ERROR();
-
-            // Maybe it can give problems too.
-            glDisable(GL_STENCIL_TEST);
-            CHECK_GL_ERROR();
+            mpContext->state()->stencil().disable();
 
             // the square root of the whole inverted scale ratio
             double ixscalesqrt = std::floor(std::sqrt(ixscale));
@@ -1529,10 +1524,7 @@ void OpenGLSalGraphicsImpl::DrawTransformedTexture(
                 mpContext->state()->scissor().enable();
 
             if (mbUseStencil)
-            {
-                glEnable(GL_STENCIL_TEST);
-                CHECK_GL_ERROR();
-            }
+                mpContext->state()->stencil().enable();
         }
     }
 
@@ -2488,6 +2480,7 @@ void OpenGLSalGraphicsImpl::flush()
     FlushDeferredDrawing();
 
     mpContext->state()->scissor().disable();
+    mpContext->state()->stencil().disable();
 
     if( IsOffscreen() )
         return;
@@ -2506,6 +2499,7 @@ void OpenGLSalGraphicsImpl::doFlush()
     FlushDeferredDrawing();
 
     mpContext->state()->scissor().disable();
+    mpContext->state()->stencil().disable();
 
     if( IsOffscreen() )
         return;
@@ -2551,6 +2545,7 @@ void OpenGLSalGraphicsImpl::doFlush()
     CHECK_GL_ERROR();
 
     mpWindowContext->state()->scissor().disable();
+    mpWindowContext->state()->stencil().disable();
 
 #if OSL_DEBUG_LEVEL > 0 // random background glClear
     glClearColor((float)rand()/RAND_MAX, (float)rand()/RAND_MAX,
diff --git a/vcl/opengl/salbmp.cxx b/vcl/opengl/salbmp.cxx
index 347204a..87fc542 100644
--- a/vcl/opengl/salbmp.cxx
+++ b/vcl/opengl/salbmp.cxx
@@ -539,6 +539,7 @@ bool OpenGLSalBitmap::ReadTexture()
 
     rtl::Reference<OpenGLContext> xContext = OpenGLContext::getVCLContext();
     xContext->state()->scissor().disable();
+    xContext->state()->stencil().disable();
 
     if (mnBits == 8 || mnBits == 16 || mnBits == 24 || mnBits == 32)
     {
@@ -617,6 +618,7 @@ bool OpenGLSalBitmap::calcChecksumGL(OpenGLTexture& rInputTexture, ChecksumType&
 
     rtl::Reference< OpenGLContext > xContext = OpenGLContext::getVCLContext();
     xContext->state()->scissor().disable();
+    xContext->state()->stencil().disable();
 
     static vcl::DeleteOnDeinit<OpenGLTexture> gCRCTableTexture(
         new OpenGLTexture(512, 1, GL_RGBA, GL_UNSIGNED_BYTE,
@@ -886,6 +888,7 @@ bool OpenGLSalBitmap::Replace( const Color& rSearchColor, const Color& rReplaceC
     OpenGLZone aZone;
     rtl::Reference<OpenGLContext> xContext = OpenGLContext::getVCLContext();
     xContext->state()->scissor().disable();
+    xContext->state()->stencil().disable();
 
     OpenGLFramebuffer* pFramebuffer;
     OpenGLProgram* pProgram;
@@ -925,6 +928,7 @@ bool OpenGLSalBitmap::ConvertToGreyscale()
     OpenGLZone aZone;
     rtl::Reference<OpenGLContext> xContext = OpenGLContext::getVCLContext();
     xContext->state()->scissor().disable();
+    xContext->state()->stencil().disable();
 
     OpenGLFramebuffer* pFramebuffer;
     OpenGLProgram* pProgram;
diff --git a/vcl/opengl/scale.cxx b/vcl/opengl/scale.cxx
index 837d614..3a42bdd 100644
--- a/vcl/opengl/scale.cxx
+++ b/vcl/opengl/scale.cxx
@@ -332,6 +332,7 @@ bool OpenGLSalBitmap::ImplScale( const double& rScaleX, const double& rScaleY, B
     OpenGLVCLContextZone aContextZone;
     rtl::Reference<OpenGLContext> xContext = OpenGLContext::getVCLContext();
     xContext->state()->scissor().disable();
+    xContext->state()->stencil().disable();
 
     if (rScaleX <= 1 && rScaleY <= 1)
     {
commit 586dfa1f33ed37cf3e1d0e3f2516e2e4238e0dc6
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Thu Apr 28 19:34:37 2016 +0900

    opengl: track the state of scissor test and the dimensions
    
    For performance reasons we shouldn't set glScissors if it is not
    necessary so we remember to what dimensions we set the glScissor
    and don't set it again if this is not necessary. The same goes for
    enabling/disabling the GL_SCISSOR_TEST.
    
    Change-Id: I5e1383081b4e76bdded04525c780d3a724f9db5c

diff --git a/vcl/inc/opengl/RenderState.hxx b/vcl/inc/opengl/RenderState.hxx
index a184f2e..7b3db7be 100644
--- a/vcl/inc/opengl/RenderState.hxx
+++ b/vcl/inc/opengl/RenderState.hxx
@@ -13,15 +13,73 @@
 
 #include "opengl/TextureState.hxx"
 
+class ScissorState
+{
+    bool mbTest;
+    int mX;
+    int mY;
+    int mWidth;
+    int mHeight;
+
+public:
+
+    ScissorState()
+        : mbTest(false)
+        , mX(0)
+        , mY(0)
+        , mWidth(0)
+        , mHeight(0)
+    {
+        glDisable(GL_SCISSOR_TEST);
+        CHECK_GL_ERROR();
+    }
+
+    void set(int x, int y, int width, int height)
+    {
+        if (x != mX || y != mY || width != mWidth || height != mHeight)
+        {
+            glScissor(x, y, width, height);
+            CHECK_GL_ERROR();
+
+            mX = x;
+            mY = y;
+            mWidth = width;
+            mHeight = height;
+        }
+    }
+
+    void enable()
+    {
+        if (!mbTest)
+        {
+            glEnable(GL_SCISSOR_TEST);
+            CHECK_GL_ERROR();
+            mbTest = true;
+        }
+    }
+
+    void disable()
+    {
+        if (mbTest)
+        {
+            glDisable(GL_SCISSOR_TEST);
+            CHECK_GL_ERROR();
+            mbTest = false;
+        }
+    }
+};
+
 class RenderState
 {
     TextureState maTexture;
+    ScissorState maScissor;
 
 public:
     RenderState()
     {}
 
     TextureState& texture() { return maTexture; }
+    ScissorState& scissor() { return maScissor; }
 };
 
 #endif // INCLUDED_VCL_INC_OPENGL_RENDER_STATE_H
diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index 0c107da..6f54ad0 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -34,6 +34,7 @@
 #include "svdata.hxx"
 #include "opengl/zone.hxx"
 #include "opengl/salbmp.hxx"
+#include "opengl/RenderState.hxx"
 
 #include <vector>
 
@@ -231,11 +232,6 @@ void OpenGLSalGraphicsImpl::PostDraw()
         CHECK_GL_ERROR();
     }
 
-    if( mbUseScissor )
-    {
-        glDisable( GL_SCISSOR_TEST );
-        CHECK_GL_ERROR();
-    }
     if( mbUseStencil )
     {
         glDisable( GL_STENCIL_TEST );
@@ -272,6 +268,7 @@ void OpenGLSalGraphicsImpl::freeResources()
         VCL_GL_INFO( "freeResources" );
         mpContext->makeCurrent();
         FlushDeferredDrawing();
+        mpContext->state()->scissor().disable();
         mpContext->ReleaseFramebuffer( maOffscreenTex );
     }
     ReleaseContext();
@@ -325,27 +322,27 @@ void OpenGLSalGraphicsImpl::ImplSetClipBit( const vcl::Region& rClip, GLuint nMa
 void OpenGLSalGraphicsImpl::ImplInitClipRegion()
 {
     // make sure the context has the right clipping set
-    if( maClipRegion != mpContext->maClipRegion )
+    if (maClipRegion != mpContext->maClipRegion)
     {
         mpContext->maClipRegion = maClipRegion;
-        if( mbUseScissor )
-        {
-            Rectangle aRect( maClipRegion.GetBoundRect() );
-            glScissor( aRect.Left(), GetHeight() - aRect.Bottom() - 1, aRect.GetWidth(), aRect.GetHeight() );
-            CHECK_GL_ERROR();
-        }
-        else if( !maClipRegion.IsEmpty() )
+        if (mbUseStencil)
         {
-            ImplSetClipBit( maClipRegion, 0x01 );
+            ImplSetClipBit(maClipRegion, 0x01);
         }
     }
 
-    if( mbUseScissor )
+    if (mbUseScissor)
     {
-        glEnable( GL_SCISSOR_TEST );
-        CHECK_GL_ERROR();
+        Rectangle aRect(maClipRegion.GetBoundRect());
+        mpContext->state()->scissor().set(aRect.Left(), GetHeight() - aRect.Bottom() - 1, aRect.GetWidth(), aRect.GetHeight());
+        mpContext->state()->scissor().enable();
     }
-    if( mbUseStencil )
+    else
+    {
+        mpContext->state()->scissor().disable();
+    }
+
+    if (mbUseStencil)
     {
         glStencilFunc( GL_EQUAL, 1, 0x1 );
         CHECK_GL_ERROR();
@@ -375,9 +372,9 @@ bool OpenGLSalGraphicsImpl::setClipRegion( const vcl::Region& rClip )
 
     mbUseStencil = false;
     mbUseScissor = false;
-    if( maClipRegion.IsRectangle() )
+    if (maClipRegion.IsRectangle())
         mbUseScissor = true;
-    else if ( !maClipRegion.IsEmpty() )
+    else if (!maClipRegion.IsEmpty())
         mbUseStencil = true;
 
     return true;
@@ -1503,7 +1500,7 @@ void OpenGLSalGraphicsImpl::DrawTransformedTexture(
             // The scissor area is set to the current window size in PreDraw,
             // so if we do not disable the scissor test, the texture produced
             // by the first downscaling is clipped to the current window size.
-            glDisable(GL_SCISSOR_TEST);
+            mpContext->state()->scissor().disable();
             CHECK_GL_ERROR();
 
             // Maybe it can give problems too.
@@ -1529,10 +1526,8 @@ void OpenGLSalGraphicsImpl::DrawTransformedTexture(
 
             // Re-enable scissor and stencil tests if needed.
             if (mbUseScissor)
-            {
-                glEnable(GL_SCISSOR_TEST);
-                CHECK_GL_ERROR();
-            }
+                mpContext->state()->scissor().enable();
+
             if (mbUseStencil)
             {
                 glEnable(GL_STENCIL_TEST);
@@ -2492,6 +2487,8 @@ void OpenGLSalGraphicsImpl::flush()
 {
     FlushDeferredDrawing();
 
+    mpContext->state()->scissor().disable();
+
     if( IsOffscreen() )
         return;
 
@@ -2508,6 +2505,8 @@ void OpenGLSalGraphicsImpl::doFlush()
 {
     FlushDeferredDrawing();
 
+    mpContext->state()->scissor().disable();
+
     if( IsOffscreen() )
         return;
 
@@ -2551,6 +2550,8 @@ void OpenGLSalGraphicsImpl::doFlush()
     glViewport( 0, 0, GetWidth(), GetHeight() );
     CHECK_GL_ERROR();
 
+    mpWindowContext->state()->scissor().disable();
+
 #if OSL_DEBUG_LEVEL > 0 // random background glClear
     glClearColor((float)rand()/RAND_MAX, (float)rand()/RAND_MAX,
                  (float)rand()/RAND_MAX, 1.0);
diff --git a/vcl/opengl/salbmp.cxx b/vcl/opengl/salbmp.cxx
index 18c2ce3..347204a 100644
--- a/vcl/opengl/salbmp.cxx
+++ b/vcl/opengl/salbmp.cxx
@@ -33,7 +33,7 @@
 #include "opengl/zone.hxx"
 #include "opengl/program.hxx"
 #include "opengl/salbmp.hxx"
-
+#include "opengl/RenderState.hxx"
 #include "opengl/FixedTextureAtlas.hxx"
 
 #if OSL_DEBUG_LEVEL > 0
@@ -537,6 +537,9 @@ bool OpenGLSalBitmap::ReadTexture()
 
     OpenGLVCLContextZone aContextZone;
 
+    rtl::Reference<OpenGLContext> xContext = OpenGLContext::getVCLContext();
+    xContext->state()->scissor().disable();
+
     if (mnBits == 8 || mnBits == 16 || mnBits == 24 || mnBits == 32)
     {
         determineTextureFormat(mnBits, nFormat, nType);
@@ -613,6 +616,7 @@ bool OpenGLSalBitmap::calcChecksumGL(OpenGLTexture& rInputTexture, ChecksumType&
     OUString FragShader("areaHashCRC64TFragmentShader");
 
     rtl::Reference< OpenGLContext > xContext = OpenGLContext::getVCLContext();
+    xContext->state()->scissor().disable();
 
     static vcl::DeleteOnDeinit<OpenGLTexture> gCRCTableTexture(
         new OpenGLTexture(512, 1, GL_RGBA, GL_UNSIGNED_BYTE,
@@ -880,7 +884,8 @@ bool OpenGLSalBitmap::Replace( const Color& rSearchColor, const Color& rReplaceC
     VCL_GL_INFO("::Replace");
 
     OpenGLZone aZone;
-    rtl::Reference< OpenGLContext > xContext = OpenGLContext::getVCLContext();
+    rtl::Reference<OpenGLContext> xContext = OpenGLContext::getVCLContext();
+    xContext->state()->scissor().disable();
 
     OpenGLFramebuffer* pFramebuffer;
     OpenGLProgram* pProgram;
@@ -919,6 +924,7 @@ bool OpenGLSalBitmap::ConvertToGreyscale()
 
     OpenGLZone aZone;
     rtl::Reference<OpenGLContext> xContext = OpenGLContext::getVCLContext();
+    xContext->state()->scissor().disable();
 
     OpenGLFramebuffer* pFramebuffer;
     OpenGLProgram* pProgram;
diff --git a/vcl/opengl/scale.cxx b/vcl/opengl/scale.cxx
index d279229..837d614 100644
--- a/vcl/opengl/scale.cxx
+++ b/vcl/opengl/scale.cxx
@@ -27,6 +27,7 @@
 #include "opengl/salbmp.hxx"
 #include "opengl/program.hxx"
 #include "opengl/texture.hxx"
+#include "opengl/RenderState.hxx"
 
 #include <ResampleKernel.hxx>
 
@@ -330,6 +331,7 @@ bool OpenGLSalBitmap::ImplScale( const double& rScaleX, const double& rScaleY, B
     maUserBuffer.reset();
     OpenGLVCLContextZone aContextZone;
     rtl::Reference<OpenGLContext> xContext = OpenGLContext::getVCLContext();
+    xContext->state()->scissor().disable();
 
     if (rScaleX <= 1 && rScaleY <= 1)
     {
commit 7ca76bc7d39ae96acf8373698d143ee9f408b367
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Thu Apr 28 14:55:45 2016 +0900

    opengl: track state of active and bound textures in context
    
    Add TextureState which is responsible to track the state of
    texture binding (and unbinding) and changing the current active
    texture unit. This is necessary because all GL calls reset the
    internal state without checking what the current state actually
    is and this can accumulate to a large amount of overhead.
    
    We also unbound the textures (glBindTexture with 0 as ID) after
    every operation which is also a major unneeded overhead which is
    fixed by this commit.
    
    Change-Id: I770a6a744c0c41850c576b928f027375962088aa

diff --git a/include/vcl/opengl/OpenGLContext.hxx b/include/vcl/opengl/OpenGLContext.hxx
index a565f5b..c632ab5 100644
--- a/include/vcl/opengl/OpenGLContext.hxx
+++ b/include/vcl/opengl/OpenGLContext.hxx
@@ -62,6 +62,7 @@ class OpenGLProgram;
 class OpenGLTexture;
 class SalGraphicsImpl;
 class OpenGLTests;
+class RenderState;
 
 /// Holds the information of our new child window
 struct GLWindow
@@ -169,6 +170,11 @@ public:
     OpenGLProgram*      UseProgram( const OUString& rVertexShader, const OUString& rFragmentShader, const OString& preamble = "" );
     void                UseNoProgram();
 
+    std::unique_ptr<RenderState>& state()
+    {
+        return mpRenderState;
+    }
+
     /// Is this GL context the current context ?
     bool isCurrent();
     /// release bound resources from the current context
@@ -260,6 +266,8 @@ private:
     std::set<SalGraphicsImpl*> maParents;
 #endif
 
+    std::unique_ptr<RenderState> mpRenderState;
+
 public:
     vcl::Region maClipRegion;
     int mnPainting;
diff --git a/vcl/inc/opengl/RenderState.hxx b/vcl/inc/opengl/RenderState.hxx
new file mode 100644
index 0000000..a184f2e
--- /dev/null
+++ b/vcl/inc/opengl/RenderState.hxx
@@ -0,0 +1,29 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#ifndef INCLUDED_VCL_INC_OPENGL_RENDER_STATE_H
+#define INCLUDED_VCL_INC_OPENGL_RENDER_STATE_H
+
+#include "opengl/TextureState.hxx"
+
+class RenderState
+{
+    TextureState maTexture;
+
+public:
+    RenderState()
+    {}
+
+    TextureState& texture() { return maTexture; }
+};
+
+#endif // INCLUDED_VCL_INC_OPENGL_RENDER_STATE_H
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/opengl/TextureState.hxx b/vcl/inc/opengl/TextureState.hxx
new file mode 100644
index 0000000..945b3b4
--- /dev/null
+++ b/vcl/inc/opengl/TextureState.hxx
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#ifndef INCLUDED_VCL_INC_OPENGL_TEXTURE_STATE_H
+#define INCLUDED_VCL_INC_OPENGL_TEXTURE_STATE_H
+
+#include <vcl/opengl/OpenGLHelper.hxx>
+
+class TextureState
+{
+private:
+    GLuint mnCurrentTextureUnit;
+    std::vector<GLuint> maBoundTextures;
+
+public:
+    TextureState()
+        : mnCurrentTextureUnit(0)
+        , maBoundTextures(4, 0)
+    {}
+
+    void generate(GLuint& nTexture)
+    {
+        glGenTextures(1, &nTexture);
+        CHECK_GL_ERROR();
+    }
+
+    void active(GLuint nTextureUnit)
+    {
+        if (mnCurrentTextureUnit != nTextureUnit)
+        {
+            glActiveTexture(GL_TEXTURE0 + nTextureUnit);
+            CHECK_GL_ERROR();
+            mnCurrentTextureUnit = nTextureUnit;
+        }
+
+    }
+
+    void bind(GLuint nTexture)
+    {
+        if (maBoundTextures[mnCurrentTextureUnit] != nTexture)
+        {
+            glBindTexture(GL_TEXTURE_2D, nTexture);
+            CHECK_GL_ERROR();
+            maBoundTextures[mnCurrentTextureUnit] = nTexture;
+        }
+    }
+
+    void unbindAndDelete(GLuint nTexture)
+    {
+        unbind(nTexture);
+        glDeleteTextures(1, &nTexture);
+    }
+
+    void unbind(GLuint nTexture)
+    {
+        for (size_t i = 0; i < maBoundTextures.size(); i++)
+        {
+            if (nTexture == maBoundTextures[i])
+                maBoundTextures[i] = 0;
+        }
+    }
+
+};
+
+
+
+#endif // INCLUDED_VCL_INC_OPENGL_TEXTURE_STATE_H
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/opengl/program.cxx b/vcl/opengl/program.cxx
index 340b10f..eafd0c6 100644
--- a/vcl/opengl/program.cxx
+++ b/vcl/opengl/program.cxx
@@ -7,9 +7,11 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
-#include <opengl/program.hxx>
+#include "opengl/program.hxx"
+#include "opengl/RenderState.hxx"
 
 #include <vcl/opengl/OpenGLHelper.hxx>
+#include <vcl/opengl/OpenGLContext.hxx>
 
 #include <glm/glm.hpp>
 #include <glm/gtc/type_ptr.hpp>
@@ -62,19 +64,11 @@ bool OpenGLProgram::Use()
 bool OpenGLProgram::Clean()
 {
     // unbind all textures
-    if( !maTextures.empty() )
+    for (OpenGLTexture& rTexture : maTextures)
     {
-        int nIndex( maTextures.size() - 1 );
-        TextureList::reverse_iterator it( maTextures.rbegin() );
-        while( it != maTextures.rend() )
-        {
-            glActiveTexture( GL_TEXTURE0 + nIndex-- );
-            CHECK_GL_ERROR();
-            it->Unbind();
-            ++it;
-        }
-        maTextures.clear();
+        rTexture.Unbind();
     }
+    maTextures.clear();
 
     // disable any enabled vertex attrib array
     if( mnEnabledAttribs )
@@ -252,10 +246,12 @@ void OpenGLProgram::SetTexture( const OString& rName, OpenGLTexture& rTexture )
 
     glUniform1i( nUniform, nIndex );
     CHECK_GL_ERROR();
-    glActiveTexture( GL_TEXTURE0 + nIndex );
-    CHECK_GL_ERROR();
+
+    std::unique_ptr<RenderState>& rState = OpenGLContext::getVCLContext()->state();
+    rState->texture().active(nIndex);
+
     rTexture.Bind();
-    maTextures.push_back( rTexture );
+    maTextures.push_back(rTexture);
 }
 
 void OpenGLProgram::SetTransform(
diff --git a/vcl/opengl/texture.cxx b/vcl/opengl/texture.cxx
index 61b6514..9f5f9a2 100644
--- a/vcl/opengl/texture.cxx
+++ b/vcl/opengl/texture.cxx
@@ -29,6 +29,8 @@
 #include "opengl/framebuffer.hxx"
 #include "opengl/texture.hxx"
 #include "opengl/zone.hxx"
+#include "opengl/RenderState.hxx"
+
 namespace
 {
 
@@ -48,10 +50,11 @@ ImplOpenGLTexture::ImplOpenGLTexture( int nWidth, int nHeight, bool bAllocate )
 {
     OpenGLVCLContextZone aContextZone;
 
-    glGenTextures( 1, &mnTexture );
-    CHECK_GL_ERROR();
-    glBindTexture( GL_TEXTURE_2D, mnTexture );
-    CHECK_GL_ERROR();
+    auto& rState = OpenGLContext::getVCLContext()->state();
+    rState->texture().generate(mnTexture);
+    rState->texture().active(0);
+    rState->texture().bind(mnTexture);
+
     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
     CHECK_GL_ERROR();
     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
@@ -65,8 +68,6 @@ ImplOpenGLTexture::ImplOpenGLTexture( int nWidth, int nHeight, bool bAllocate )
         glTexImage2D( GL_TEXTURE_2D, 0, constInternalFormat, nWidth, nHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr );
         CHECK_GL_ERROR();
     }
-    glBindTexture( GL_TEXTURE_2D, 0 );
-    CHECK_GL_ERROR();
 
     VCL_GL_INFO( "OpenGLTexture " << mnTexture << " " << nWidth << "x" << nHeight << " allocate" );
 }
@@ -86,10 +87,11 @@ ImplOpenGLTexture::ImplOpenGLTexture( int nX, int nY, int nWidth, int nHeight )
     // FIXME We need the window height here
     // nY = GetHeight() - nHeight - nY;
 
-    glGenTextures( 1, &mnTexture );
-    CHECK_GL_ERROR();
-    glBindTexture( GL_TEXTURE_2D, mnTexture );
-    CHECK_GL_ERROR();
+    auto& rState = OpenGLContext::getVCLContext()->state();
+    rState->texture().generate(mnTexture);
+    rState->texture().active(0);
+    rState->texture().bind(mnTexture);
+
     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
     CHECK_GL_ERROR();
     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
@@ -100,8 +102,6 @@ ImplOpenGLTexture::ImplOpenGLTexture( int nX, int nY, int nWidth, int nHeight )
     CHECK_GL_ERROR();
     glCopyTexImage2D( GL_TEXTURE_2D, 0, constInternalFormat, nX, nY, nWidth, nHeight, 0 );
     CHECK_GL_ERROR();
-    glBindTexture( GL_TEXTURE_2D, 0 );
-    CHECK_GL_ERROR();
 
     VCL_GL_INFO( "OpenGLTexture " << mnTexture << " " << nWidth << "x" << nHeight << " from x" << nX << ", y" << nY );
 }
@@ -118,10 +118,11 @@ ImplOpenGLTexture::ImplOpenGLTexture( int nWidth, int nHeight, int nFormat, int
 {
     OpenGLVCLContextZone aContextZone;
 
-    glGenTextures( 1, &mnTexture );
-    CHECK_GL_ERROR();
-    glBindTexture( GL_TEXTURE_2D, mnTexture );
-    CHECK_GL_ERROR();
+    auto& rState = OpenGLContext::getVCLContext()->state();
+    rState->texture().generate(mnTexture);
+    rState->texture().active(0);
+    rState->texture().bind(mnTexture);
+
     glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
     CHECK_GL_ERROR();
     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
@@ -134,8 +135,6 @@ ImplOpenGLTexture::ImplOpenGLTexture( int nWidth, int nHeight, int nFormat, int
     CHECK_GL_ERROR();
     glTexImage2D( GL_TEXTURE_2D, 0, constInternalFormat, mnWidth, mnHeight, 0, nFormat, nType, pData );
     CHECK_GL_ERROR();
-    glBindTexture( GL_TEXTURE_2D, 0 );
-    CHECK_GL_ERROR();
 
     VCL_GL_INFO( "OpenGLTexture " << mnTexture << " " << nWidth << "x" << nHeight << " from data" );
 }
@@ -187,8 +186,8 @@ void ImplOpenGLTexture::Dispose()
                 glDeleteRenderbuffers( 1, &mnOptStencil );
                 mnOptStencil = 0;
             }
-            glDeleteTextures( 1, &mnTexture );
-
+            auto& rState = pContext->state();
+            rState->texture().unbindAndDelete(mnTexture);
             mnTexture = 0;
         }
         else
@@ -203,14 +202,15 @@ bool ImplOpenGLTexture::InsertBuffer(int nX, int nY, int nWidth, int nHeight, in
 {
     if (!pData || mnTexture == 0)
         return false;
-    glBindTexture(GL_TEXTURE_2D, mnTexture);
-    CHECK_GL_ERROR();
+
+    rtl::Reference<OpenGLContext> xContext = OpenGLContext::getVCLContext();
+    xContext->state()->texture().active(0);
+    xContext->state()->texture().bind(mnTexture);
+
     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
     CHECK_GL_ERROR();
     glTexSubImage2D(GL_TEXTURE_2D, 0, nX, mnHeight - nY - nHeight, nWidth, nHeight, nFormat, nType, pData);
     CHECK_GL_ERROR();
-    glBindTexture(GL_TEXTURE_2D, 0);
-    CHECK_GL_ERROR();
 
     VCL_GL_INFO( "OpenGLTexture " << mnTexture << " Insert buff. to " << nX << " " << nY
                                              << " size " << nWidth << "x" << nHeight << " from data" );
@@ -507,10 +507,10 @@ void OpenGLTexture::SetFilter( GLenum nFilter )
 
 void OpenGLTexture::Bind()
 {
-    if( mpImpl )
+    if (mpImpl)
     {
-        glBindTexture( GL_TEXTURE_2D, mpImpl->mnTexture );
-        CHECK_GL_ERROR();
+        std::unique_ptr<RenderState>& rState = OpenGLContext::getVCLContext()->state();
+        rState->texture().bind(mpImpl->mnTexture);
     }
     else
         VCL_GL_INFO( "OpenGLTexture::Binding invalid texture" );
@@ -520,10 +520,10 @@ void OpenGLTexture::Bind()
 
 void OpenGLTexture::Unbind()
 {
-    if( mpImpl )
+    if (mpImpl)
     {
-        glBindTexture( GL_TEXTURE_2D, 0 );
-        CHECK_GL_ERROR();
+        std::unique_ptr<RenderState>& rState = OpenGLContext::getVCLContext()->state();
+        rState->texture().unbind(mpImpl->mnTexture);
     }
 }
 
diff --git a/vcl/opengl/x11/gdiimpl.cxx b/vcl/opengl/x11/gdiimpl.cxx
index fc49e25..61dba9b 100644
--- a/vcl/opengl/x11/gdiimpl.cxx
+++ b/vcl/opengl/x11/gdiimpl.cxx
@@ -22,6 +22,7 @@
 #include <opengl/texture.hxx>
 #include <opengl/x11/gdiimpl.hxx>
 #include <opengl/x11/salvd.hxx>
+#include "opengl/RenderState.hxx"
 
 #include <vcl/opengl/OpenGLContext.hxx>
 #include <vcl/opengl/OpenGLHelper.hxx>
@@ -144,8 +145,8 @@ bool X11OpenGLSalGraphicsImpl::RenderPixmap(X11Pixmap* pPixmap, X11Pixmap* pMask
 
     rCombo.mpTexture.reset(new OpenGLTexture(pPixmap->GetWidth(), pPixmap->GetHeight(), false));
 
-    glActiveTexture( GL_TEXTURE0 );
-    CHECK_GL_ERROR();
+    mpContext->state()->texture().active(0);
+
     rCombo.mpTexture->Bind();
     glXBindTexImageEXT( pDisplay, pGlxPixmap, GLX_FRONT_LEFT_EXT, nullptr );
     rCombo.mpTexture->Unbind();
diff --git a/vcl/source/opengl/OpenGLContext.cxx b/vcl/source/opengl/OpenGLContext.cxx
index a009476..69e185e 100644
--- a/vcl/source/opengl/OpenGLContext.cxx
+++ b/vcl/source/opengl/OpenGLContext.cxx
@@ -40,6 +40,8 @@
 #include <opengl/texture.hxx>
 #include <opengl/zone.hxx>
 
+#include "opengl/RenderState.hxx"
+
 using namespace com::sun::star;
 
 #define MAX_FRAMEBUFFER_COUNT 30
@@ -73,6 +75,7 @@ OpenGLContext::OpenGLContext():
     mpFirstFramebuffer(nullptr),
     mpLastFramebuffer(nullptr),
     mpCurrentProgram(nullptr),
+    mpRenderState(new RenderState),
     mnPainting(0),
     mpPrevContext(nullptr),
     mpNextContext(nullptr)


More information about the Libreoffice-commits mailing list