[Libreoffice-commits] core.git: include/vcl vcl/inc vcl/opengl vcl/source

Tomaž Vajngerl tomaz.vajngerl at collabora.co.uk
Sat Apr 30 03:07:13 UTC 2016


 include/vcl/opengl/OpenGLContext.hxx |    8 +++
 vcl/inc/opengl/RenderState.hxx       |   29 +++++++++++++
 vcl/inc/opengl/TextureState.hxx      |   76 +++++++++++++++++++++++++++++++++++
 vcl/opengl/program.cxx               |   26 +++++------
 vcl/opengl/texture.cxx               |   60 +++++++++++++--------------
 vcl/opengl/x11/gdiimpl.cxx           |    5 +-
 vcl/source/opengl/OpenGLContext.cxx  |    3 +
 7 files changed, 160 insertions(+), 47 deletions(-)

New commits:
commit ba0a5708803d899de4c40cfe2c1697ae83b4827a
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
    Reviewed-on: https://gerrit.libreoffice.org/24503
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>

diff --git a/include/vcl/opengl/OpenGLContext.hxx b/include/vcl/opengl/OpenGLContext.hxx
index 44b8d67..723a994 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
@@ -166,6 +167,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
@@ -249,6 +255,8 @@ private:
     ProgramCollection maPrograms;
     OpenGLProgram* mpCurrentProgram;
 
+    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 c8b0583..c4f5c0e 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 232b2cd..e9fca75 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
 {
 
@@ -47,10 +49,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 );
@@ -64,8 +67,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" );
 }
@@ -84,10 +85,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 );
@@ -98,8 +100,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 );
 }
@@ -115,10 +115,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 );
@@ -131,8 +132,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" );
@@ -492,10 +492,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" );
@@ -505,10 +505,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 2b1e6be..b5881fe 100644
--- a/vcl/source/opengl/OpenGLContext.cxx
+++ b/vcl/source/opengl/OpenGLContext.cxx
@@ -41,6 +41,8 @@
 #include <opengl/texture.hxx>
 #include <opengl/zone.hxx>
 
+#include "opengl/RenderState.hxx"
+
 using namespace com::sun::star;
 
 #define MAX_FRAMEBUFFER_COUNT 30
@@ -74,6 +76,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