[Libreoffice-commits] core.git: 3 commits - vcl/inc vcl/Library_vcl.mk vcl/opengl vcl/Package_opengl.mk

Tomaž Vajngerl tomaz.vajngerl at collabora.co.uk
Mon Aug 24 03:09:18 PDT 2015


 vcl/Library_vcl.mk                             |    1 
 vcl/Package_opengl.mk                          |    1 
 vcl/inc/opengl/FixedTextureAtlas.hxx           |   39 +++++++
 vcl/inc/opengl/program.hxx                     |    2 
 vcl/inc/opengl/texture.hxx                     |   47 ++++++++-
 vcl/opengl/FixedTextureAtlas.cxx               |   71 ++++++++++++++
 vcl/opengl/areaScaleFastFragmentShader.glsl    |    3 
 vcl/opengl/areaScaleFragmentShader.glsl        |    1 
 vcl/opengl/blendedTextureFragmentShader.glsl   |    8 +
 vcl/opengl/blendedTextureVertexShader.glsl     |    3 
 vcl/opengl/diffTextureFragmentShader.glsl      |    6 -
 vcl/opengl/gdiimpl.cxx                         |   37 ++++++-
 vcl/opengl/maskedTextureFragmentShader.glsl    |    6 -
 vcl/opengl/maskedTextureVertexShader.glsl      |   24 ++++
 vcl/opengl/program.cxx                         |    6 +
 vcl/opengl/texture.cxx                         |  123 ++++++++++++++++++++-----
 vcl/opengl/transformedTextureVertexShader.glsl |    3 
 17 files changed, 344 insertions(+), 37 deletions(-)

New commits:
commit bdce4e29191aa5bd029efa242e094aba45c44869
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Mon Aug 24 15:00:26 2015 +0900

    opengl: push mask coords to the shaders along the image coords
    
    If using the same texture to store the image and mask data (for
    example when using texture atlas) the mask and image (RGB) coords
    aren't the same anymore. With this commit we always define the mask
    coords separately.
    
    Change-Id: Ie33f87a6e9ab398972c6a3d5938e5f1364c82d36

diff --git a/vcl/Package_opengl.mk b/vcl/Package_opengl.mk
index 0a54ad6..2628dcd 100644
--- a/vcl/Package_opengl.mk
+++ b/vcl/Package_opengl.mk
@@ -19,6 +19,7 @@ $(eval $(call gb_Package_add_files,vcl_opengl_shader,$(LIBO_ETC_FOLDER)/opengl,\
 	convolutionFragmentShader.glsl \
 	linearGradientFragmentShader.glsl \
 	maskFragmentShader.glsl \
+	maskedTextureVertexShader.glsl \
 	maskedTextureFragmentShader.glsl \
 	radialGradientFragmentShader.glsl \
 	replaceColorFragmentShader.glsl \
diff --git a/vcl/inc/opengl/program.hxx b/vcl/inc/opengl/program.hxx
index 5ca9aff..7ac1936 100644
--- a/vcl/inc/opengl/program.hxx
+++ b/vcl/inc/opengl/program.hxx
@@ -36,6 +36,7 @@ private:
     GLuint          mnPositionAttrib;
     GLuint          mnTexCoordAttrib;
     GLuint          mnAlphaCoordAttrib;
+    GLuint          mnMaskCoordAttrib;
     TextureList     maTextures;
     bool            mbBlending;
 
@@ -51,6 +52,7 @@ public:
     void SetVertices( const GLvoid* pData );
     void SetTextureCoord( const GLvoid* pData );
     void SetAlphaCoord( const GLvoid* pData );
+    void SetMaskCoord(const GLvoid* pData);
 
     void SetUniform1f( const OString& rName, GLfloat v1 );
     void SetUniform2f( const OString& rName, GLfloat v1, GLfloat v2 );
diff --git a/vcl/opengl/areaScaleFastFragmentShader.glsl b/vcl/opengl/areaScaleFastFragmentShader.glsl
index 10ce9f5..f74397b 100644
--- a/vcl/opengl/areaScaleFastFragmentShader.glsl
+++ b/vcl/opengl/areaScaleFastFragmentShader.glsl
@@ -21,6 +21,7 @@ varying vec2 tex_coord;
 // This mode makes the scaling work like maskedTextureFragmentShader.glsl
 // (instead of like plain textureVertexShader.glsl).
 #ifdef MASKED
+varying vec2 mask_coord;
 uniform sampler2D mask;
 #endif
 
@@ -41,7 +42,7 @@ void main(void)
 #else
             vec4 texel;
             texel = texture2D( sampler, tex_coord.st + offset );
-            texel.a = 1.0 - texture2D( mask, tex_coord.st + offset ).r;
+            texel.a = 1.0 - texture2D( mask, mask_coord.st + offset ).r;
             sum += texel;
 #endif
             offset.x += xstep;
diff --git a/vcl/opengl/areaScaleFragmentShader.glsl b/vcl/opengl/areaScaleFragmentShader.glsl
index d72184c..b95b869 100644
--- a/vcl/opengl/areaScaleFragmentShader.glsl
+++ b/vcl/opengl/areaScaleFragmentShader.glsl
@@ -30,6 +30,7 @@ varying vec2 tex_coord;
 // This mode makes the scaling work like maskedTextureFragmentShader.glsl
 // (instead of like plain textureVertexShader.glsl).
 #ifdef MASKED
+varying vec2 mask_coord;
 uniform sampler2D mask;
 #endif
 
diff --git a/vcl/opengl/blendedTextureFragmentShader.glsl b/vcl/opengl/blendedTextureFragmentShader.glsl
index 318023c..eabb652 100644
--- a/vcl/opengl/blendedTextureFragmentShader.glsl
+++ b/vcl/opengl/blendedTextureFragmentShader.glsl
@@ -9,14 +9,18 @@
 
 varying vec2 tex_coord;
 varying vec2 alpha_coord;
+varying vec2 mask_coord;
+
 uniform sampler2D sampler;
 uniform sampler2D mask;
 uniform sampler2D alpha;
 
-void main() {
+void main()
+{
     vec4 texel0, texel1, texel2;
+
     texel0 = texture2D(sampler, tex_coord);
-    texel1 = texture2D(mask, tex_coord);
+    texel1 = texture2D(mask, mask_coord);
     texel2 = texture2D(alpha, alpha_coord);
     gl_FragColor = texel0;
 
diff --git a/vcl/opengl/blendedTextureVertexShader.glsl b/vcl/opengl/blendedTextureVertexShader.glsl
index 3a9b827..64bae78 100644
--- a/vcl/opengl/blendedTextureVertexShader.glsl
+++ b/vcl/opengl/blendedTextureVertexShader.glsl
@@ -10,14 +10,17 @@
 attribute vec4 position;
 attribute vec2 tex_coord_in;
 attribute vec2 alpha_coord_in;
+attribute vec2 mask_coord_in;
 varying vec2 tex_coord;
 varying vec2 alpha_coord;
+varying vec2 mask_coord;
 uniform mat4 mvp;
 
 void main() {
    gl_Position = mvp * position;
    tex_coord = tex_coord_in;
    alpha_coord = alpha_coord_in;
+   mask_coord = mask_coord_in;
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/opengl/diffTextureFragmentShader.glsl b/vcl/opengl/diffTextureFragmentShader.glsl
index c0a982d..af9a1dc 100644
--- a/vcl/opengl/diffTextureFragmentShader.glsl
+++ b/vcl/opengl/diffTextureFragmentShader.glsl
@@ -9,14 +9,16 @@
 
 /*precision mediump float;*/
 varying vec2 tex_coord;
+varying vec2 mask_coord;
 uniform sampler2D texture; /* white background */
 uniform sampler2D mask;    /* black background */
 
-void main() {
+void main()
+{
     float alpha;
     vec4 texel0, texel1;
     texel0 = texture2D(texture, tex_coord);
-    texel1 = texture2D(mask, tex_coord);
+    texel1 = texture2D(mask, mask_coord);
     alpha = 1.0 - abs(texel0.r - texel1.r);
     if(alpha > 0.0)
         gl_FragColor = texel1 / alpha;
diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index 6a8c588..5e2785c 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -959,6 +959,9 @@ void OpenGLSalGraphicsImpl::DrawTransformedTexture(
                 "#define MASKED" ) )
             return;
         mpProgram->SetTexture( "mask", rMask );
+        GLfloat aMaskCoord[8];
+        rMask.GetWholeCoord(aMaskCoord);
+        mpProgram->SetMaskCoord(aMaskCoord);
         rMask.SetFilter( GL_LINEAR );
         mpProgram->SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
     }
@@ -1027,25 +1030,39 @@ void OpenGLSalGraphicsImpl::DrawTextureDiff( OpenGLTexture& rTexture, OpenGLText
 {
     OpenGLZone aZone;
 
-    if( !UseProgram( "textureVertexShader", "diffTextureFragmentShader" ) )
+    if( !UseProgram( "maskedTextureVertexShader", "diffTextureFragmentShader" ) )
         return;
     mpProgram->SetTexture( "texture", rTexture );
     mpProgram->SetTexture( "mask", rMask );
     mpProgram->SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
+
+    GLfloat aMaskCoord[8];
+    rMask.GetCoord(aMaskCoord, rPosAry, bInverted);
+    mpProgram->SetMaskCoord(aMaskCoord);
+
     DrawTextureRect( rTexture, rPosAry, bInverted );
     mpProgram->Clean();
 }
 
-void OpenGLSalGraphicsImpl::DrawTextureWithMask( OpenGLTexture& rTexture, OpenGLTexture& rMask, const SalTwoRect& pPosAry )
+void OpenGLSalGraphicsImpl::DrawTextureWithMask( OpenGLTexture& rTexture, OpenGLTexture& rMask, const SalTwoRect& rPosAry )
 {
     OpenGLZone aZone;
 
-    if( !UseProgram( "textureVertexShader", "maskedTextureFragmentShader" ) )
+    if( !UseProgram( "maskedTextureVertexShader", "maskedTextureFragmentShader" ) )
         return;
     mpProgram->SetTexture( "sampler", rTexture );
     mpProgram->SetTexture( "mask", rMask );
     mpProgram->SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
-    DrawTextureRect( rTexture, pPosAry );
+
+    GLfloat aTexCoord[8];
+    rTexture.GetCoord(aTexCoord, rPosAry);
+    mpProgram->SetTextureCoord(aTexCoord);
+
+    GLfloat aMaskCoord[8];
+    rMask.GetCoord(aMaskCoord, rPosAry);
+    mpProgram->SetMaskCoord(aMaskCoord);
+
+    DrawRect(rPosAry.mnDestX, rPosAry.mnDestY, rPosAry.mnDestWidth, rPosAry.mnDestHeight);
     mpProgram->Clean();
 }
 
@@ -1053,14 +1070,20 @@ void OpenGLSalGraphicsImpl::DrawBlendedTexture( OpenGLTexture& rTexture, OpenGLT
 {
     OpenGLZone aZone;
 
-    GLfloat aTexCoord[8];
     if( !UseProgram( "blendedTextureVertexShader", "blendedTextureFragmentShader" ) )
         return;
     mpProgram->SetTexture( "sampler", rTexture );
     mpProgram->SetTexture( "mask", rMask );
     mpProgram->SetTexture( "alpha", rAlpha );
-    rAlpha.GetCoord( aTexCoord, rPosAry );
-    mpProgram->SetAlphaCoord( aTexCoord );
+
+    GLfloat aAlphaCoord[8];
+    rAlpha.GetCoord(aAlphaCoord, rPosAry);
+    mpProgram->SetAlphaCoord(aAlphaCoord);
+
+    GLfloat aMaskCoord[8];
+    rMask.GetCoord(aMaskCoord, rPosAry);
+    mpProgram->SetMaskCoord(aMaskCoord);
+
     mpProgram->SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
     DrawTextureRect( rTexture, rPosAry );
     mpProgram->Clean();
diff --git a/vcl/opengl/maskedTextureFragmentShader.glsl b/vcl/opengl/maskedTextureFragmentShader.glsl
index 4d79ae9..75ce4ae 100644
--- a/vcl/opengl/maskedTextureFragmentShader.glsl
+++ b/vcl/opengl/maskedTextureFragmentShader.glsl
@@ -9,13 +9,15 @@
 
 /*precision mediump float;*/
 varying vec2 tex_coord;
+varying vec2 mask_coord;
 uniform sampler2D sampler;
 uniform sampler2D mask;
 
-void main() {
+void main()
+{
     vec4 texel0, texel1;
     texel0 = texture2D(sampler, tex_coord);
-    texel1 = texture2D(mask, tex_coord);
+    texel1 = texture2D(mask, mask_coord);
     gl_FragColor = texel0;
     gl_FragColor.a = 1.0 - texel1.r;
 }
diff --git a/vcl/opengl/maskedTextureVertexShader.glsl b/vcl/opengl/maskedTextureVertexShader.glsl
new file mode 100644
index 0000000..ab225a8
--- /dev/null
+++ b/vcl/opengl/maskedTextureVertexShader.glsl
@@ -0,0 +1,24 @@
+/* -*- 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/.
+ */
+
+attribute vec4 position;
+attribute vec2 tex_coord_in;
+attribute vec2 mask_coord_in;
+varying vec2 tex_coord;
+varying vec2 mask_coord;
+uniform mat4 mvp;
+
+void main()
+{
+   gl_Position = mvp * position;
+   tex_coord = tex_coord_in;
+   mask_coord = mask_coord_in;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/opengl/program.cxx b/vcl/opengl/program.cxx
index 3bfa6c2..ede0548 100644
--- a/vcl/opengl/program.cxx
+++ b/vcl/opengl/program.cxx
@@ -21,6 +21,7 @@ OpenGLProgram::OpenGLProgram() :
     mnPositionAttrib( SAL_MAX_UINT32 ),
     mnTexCoordAttrib( SAL_MAX_UINT32 ),
     mnAlphaCoordAttrib( SAL_MAX_UINT32 ),
+    mnMaskCoordAttrib( SAL_MAX_UINT32 ),
     mbBlending( false )
 {
 }
@@ -112,6 +113,11 @@ void OpenGLProgram::SetAlphaCoord( const GLvoid* pData )
     SetVertexAttrib( mnAlphaCoordAttrib, "alpha_coord_in", pData );
 }
 
+void OpenGLProgram::SetMaskCoord(const GLvoid* pData)
+{
+    SetVertexAttrib(mnMaskCoordAttrib, "mask_coord_in", pData);
+}
+
 GLuint OpenGLProgram::GetUniformLocation( const OString& rName )
 {
     auto it = maUniformLocations.find( rName );
diff --git a/vcl/opengl/transformedTextureVertexShader.glsl b/vcl/opengl/transformedTextureVertexShader.glsl
index 3a64fd0..6f8d5f3 100644
--- a/vcl/opengl/transformedTextureVertexShader.glsl
+++ b/vcl/opengl/transformedTextureVertexShader.glsl
@@ -9,15 +9,18 @@
 
 attribute vec4 position;
 attribute vec2 tex_coord_in;
+attribute vec2 mask_coord_in;
 uniform vec2 viewport;
 uniform mat4 transform;
 uniform mat4 mvp;
 varying vec2 tex_coord;
+varying vec2 mask_coord;
 
 void main() {
     vec4 pos = mvp * transform * position;
     gl_Position = pos;
     tex_coord = tex_coord_in;
+    mask_coord = mask_coord_in;
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit b26ba85d04e81f48622dfdbb71d9d80b54dacc40
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Wed Aug 19 11:51:15 2015 +0900

    Fixed (fixed size) texture atlas for "caching" OpenGL texures
    
    Change-Id: I7fe90c0a0033b4d9a341a4f0b8356d7f7133e93e

diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 2e6f8b0..306178c 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -132,6 +132,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
 	vcl/opengl/framebuffer \
 	vcl/opengl/program \
 	vcl/opengl/texture \
+	vcl/opengl/FixedTextureAtlas \
     vcl/source/opengl/OpenGLContext \
     vcl/source/opengl/OpenGLHelper \
     vcl/source/window/cairo_cairo \
diff --git a/vcl/inc/opengl/FixedTextureAtlas.hxx b/vcl/inc/opengl/FixedTextureAtlas.hxx
new file mode 100644
index 0000000..c4f5d60
--- /dev/null
+++ b/vcl/inc/opengl/FixedTextureAtlas.hxx
@@ -0,0 +1,39 @@
+/* -*- 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_FIXED_TEXTURE_ATLAS_H
+#define INCLUDED_VCL_INC_OPENGL_FIXED_TEXTURE_ATLAS_H
+
+#include "opengl/texture.hxx"
+
+
+class VCL_PLUGIN_PUBLIC FixedTextureAtlasManager
+{
+    std::vector<std::unique_ptr<ImplOpenGLTexture>> mpTextures;
+
+    int mWidthFactor;
+    int mHeightFactor;
+    int mSubTextureSize;
+
+    void CreateNewTexture();
+
+public:
+    FixedTextureAtlasManager(int nWidthFactor, int nHeightFactor, int nTextureSize);
+    OpenGLTexture InsertBuffer(int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData);
+
+    int GetSubtextureSize()
+    {
+        return mSubTextureSize;
+    }
+};
+
+#endif // INCLUDED_VCL_INC_OPENGL_FIXED_TEXTURE_ATLAS_H
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/opengl/texture.hxx b/vcl/inc/opengl/texture.hxx
index b6839764..51f7040 100644
--- a/vcl/inc/opengl/texture.hxx
+++ b/vcl/inc/opengl/texture.hxx
@@ -26,6 +26,8 @@
 #include <rtl/ustring.hxx>
 #include <tools/gen.hxx>
 
+#include <memory>
+
 class ImplOpenGLTexture
 {
 public:
@@ -35,10 +37,45 @@ public:
     int    mnHeight;
     GLenum mnFilter;
 
+    std::unique_ptr<std::vector<int>> mpSlotReferences;
+    int mnFreeSlots;
+
     ImplOpenGLTexture( int nWidth, int nHeight, bool bAllocate );
     ImplOpenGLTexture( int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData );
     ImplOpenGLTexture( int nX, int nY, int nWidth, int nHeight );
     ~ImplOpenGLTexture();
+
+    bool InsertBuffer(int nX, int nY, int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData);
+
+    void IncreaseRefCount(int nSlotNumber)
+    {
+        mnRefCount++;
+        if (mpSlotReferences && nSlotNumber >= 0)
+        {
+            if (mpSlotReferences->at(nSlotNumber) == 0)
+                mnFreeSlots--;
+            mpSlotReferences->at(nSlotNumber)++;
+        }
+    }
+
+    void DecreaseRefCount(int nSlotNumber)
+    {
+        mnRefCount--;
+        if (mpSlotReferences && nSlotNumber >= 0)
+        {
+            mpSlotReferences->at(nSlotNumber)--;
+            if (mpSlotReferences->at(nSlotNumber) == 0)
+                mnFreeSlots++;
+        }
+    }
+
+    bool ExistRefs()
+    {
+        return mnRefCount > 0;
+    }
+
+    bool InitializeSlots(int nSlotSize);
+    int FindFreeSlot();
 };
 
 class VCL_PLUGIN_PUBLIC OpenGLTexture
@@ -46,12 +83,14 @@ class VCL_PLUGIN_PUBLIC OpenGLTexture
 private:
     // if the rect size doesn't match the mpImpl one, this instance
     // is a sub-area from the real OpenGL texture
-    Rectangle          maRect;
-
+    Rectangle maRect;
     ImplOpenGLTexture* mpImpl;
+    int mnSlotNumber;
 
 public:
                     OpenGLTexture();
+                    OpenGLTexture(ImplOpenGLTexture* pImpl, Rectangle aRectangle, int nSlotNumber = 0);
+
                     OpenGLTexture( int nWidth, int nHeight, bool bAllocate = true );
                     OpenGLTexture( int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData );
                     OpenGLTexture( int nX, int nY, int nWidth, int nHeight );
diff --git a/vcl/opengl/FixedTextureAtlas.cxx b/vcl/opengl/FixedTextureAtlas.cxx
new file mode 100644
index 0000000..c8ca508
--- /dev/null
+++ b/vcl/opengl/FixedTextureAtlas.cxx
@@ -0,0 +1,71 @@
+/* -*- 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/.
+ *
+ */
+
+#include <sal/config.h>
+#include <vcl/opengl/OpenGLContext.hxx>
+#include <vcl/opengl/OpenGLHelper.hxx>
+
+#include "opengl/framebuffer.hxx"
+#include "opengl/texture.hxx"
+
+#include "opengl/FixedTextureAtlas.hxx"
+
+FixedTextureAtlasManager::FixedTextureAtlasManager(int nWidthFactor, int nHeightFactor, int nSubTextureSize)
+    : mWidthFactor(nWidthFactor)
+    , mHeightFactor(nHeightFactor)
+    , mSubTextureSize(nSubTextureSize)
+{
+}
+
+void FixedTextureAtlasManager::CreateNewTexture()
+{
+    int nTextureWidth = mWidthFactor  * mSubTextureSize;
+    int nTextureHeight = mHeightFactor * mSubTextureSize;
+    mpTextures.push_back(std::move(std::unique_ptr<ImplOpenGLTexture>(new ImplOpenGLTexture(nTextureWidth, nTextureHeight, true))));
+    mpTextures.back()->InitializeSlots(mWidthFactor * mHeightFactor);
+}
+
+OpenGLTexture FixedTextureAtlasManager::InsertBuffer(int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData)
+{
+    ImplOpenGLTexture* pTexture = nullptr;
+
+    for (size_t i = 0; i < mpTextures.size(); i++)
+    {
+        if (mpTextures[i]->mnFreeSlots > 0)
+        {
+            pTexture = mpTextures[i].get();
+        }
+    }
+
+    if (!pTexture)
+    {
+        CreateNewTexture();
+        pTexture = mpTextures.back().get();
+    }
+
+    int nSlot = pTexture->FindFreeSlot();
+
+    // Calculate coordinates in texture
+    int nX = (nSlot % mWidthFactor) * mSubTextureSize;
+    int nY = (nSlot / mWidthFactor) * mSubTextureSize;
+
+    Rectangle aRectangle(Point(nX, nY), Size(nWidth, nHeight));
+
+    // If available, copy the image data to the texture
+    if (pData)
+    {
+        if (!pTexture->InsertBuffer(nX, nY, nWidth, nHeight, nFormat, nType, pData))
+            return OpenGLTexture();
+    }
+
+    return OpenGLTexture(pTexture, aRectangle, nSlot);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/opengl/texture.cxx b/vcl/opengl/texture.cxx
index a527ceb..cbb8b07 100644
--- a/vcl/opengl/texture.cxx
+++ b/vcl/opengl/texture.cxx
@@ -34,7 +34,8 @@ ImplOpenGLTexture::ImplOpenGLTexture( int nWidth, int nHeight, bool bAllocate )
     mnRefCount( 1 ),
     mnWidth( nWidth ),
     mnHeight( nHeight ),
-    mnFilter( GL_NEAREST )
+    mnFilter( GL_NEAREST ),
+    mnFreeSlots(-1)
 {
     glGenTextures( 1, &mnTexture );
     glBindTexture( GL_TEXTURE_2D, mnTexture );
@@ -57,7 +58,8 @@ ImplOpenGLTexture::ImplOpenGLTexture( int nX, int nY, int nWidth, int nHeight )
     mnTexture( 0 ),
     mnWidth( nWidth ),
     mnHeight( nHeight ),
-    mnFilter( GL_NEAREST )
+    mnFilter( GL_NEAREST ),
+    mnFreeSlots(-1)
 {
     // FIXME We need the window height here
     // nY = GetHeight() - nHeight - nY;
@@ -83,7 +85,8 @@ ImplOpenGLTexture::ImplOpenGLTexture( int nWidth, int nHeight, int nFormat, int
     mnTexture( 0 ),
     mnWidth( nWidth ),
     mnHeight( nHeight ),
-    mnFilter( GL_NEAREST )
+    mnFilter( GL_NEAREST ),
+    mnFreeSlots(-1)
 {
     if( !mnTexture )
         glGenTextures( 1, &mnTexture );
@@ -108,12 +111,64 @@ ImplOpenGLTexture::~ImplOpenGLTexture()
         glDeleteTextures( 1, &mnTexture );
 }
 
+bool ImplOpenGLTexture::InsertBuffer(int nX, int nY, int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData)
+{
+    if (!pData || mnTexture == 0)
+        return false;
+    glBindTexture(GL_TEXTURE_2D, mnTexture);
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+    glTexSubImage2D(GL_TEXTURE_2D, 0, nX, mnHeight - nY - nHeight, nWidth, nHeight, nFormat, nType, pData);
+    glBindTexture(GL_TEXTURE_2D, 0);
+
+    SAL_INFO( "vcl.opengl", "OpenGLTexture " << mnTexture << " Insert buff. to " << nX << " " << nY
+                                             << " size " << nWidth << "x" << nHeight << " from data" );
+    CHECK_GL_ERROR();
+
+    return true;
+}
+
+bool ImplOpenGLTexture::InitializeSlots(int nSlotSize)
+{
+    if (mpSlotReferences)
+        return false;
+
+    mpSlotReferences.reset(new std::vector<int>(nSlotSize, 0));
+    mnFreeSlots = nSlotSize;
+
+    return true;
+}
+
+int ImplOpenGLTexture::FindFreeSlot()
+{
+    if (mnFreeSlots > 0 && mpSlotReferences)
+    {
+        for (size_t i = 0; i < mpSlotReferences->size(); i++)
+        {
+            if (mpSlotReferences->at(i) <= 0)
+            {
+                return i;
+            }
+        }
+    }
+    return -1;
+}
+
 OpenGLTexture::OpenGLTexture() :
     maRect( 0, 0, 0, 0 ),
-    mpImpl( NULL )
+    mpImpl(NULL),
+    mnSlotNumber(-1)
 {
 }
 
+OpenGLTexture::OpenGLTexture(ImplOpenGLTexture* pImpl, Rectangle aRectangle, int nSlotNumber)
+    : maRect(aRectangle)
+    , mpImpl(pImpl)
+    , mnSlotNumber(nSlotNumber)
+{
+    if (mpImpl)
+        mpImpl->IncreaseRefCount(nSlotNumber);
+}
+
 OpenGLTexture::OpenGLTexture( int nWidth, int nHeight, bool bAllocate ) :
     maRect( Point( 0, 0 ), Size( nWidth, nHeight ) )
 {
@@ -136,8 +191,10 @@ OpenGLTexture::OpenGLTexture( const OpenGLTexture& rTexture )
 {
     maRect = rTexture.maRect;
     mpImpl = rTexture.mpImpl;
-    if( mpImpl )
-        mpImpl->mnRefCount++;
+    mnSlotNumber = rTexture.mnSlotNumber;
+
+    if (mpImpl)
+        mpImpl->IncreaseRefCount(mnSlotNumber);
 }
 
 OpenGLTexture::OpenGLTexture( const OpenGLTexture& rTexture,
@@ -146,19 +203,19 @@ OpenGLTexture::OpenGLTexture( const OpenGLTexture& rTexture,
     maRect = Rectangle( Point( rTexture.maRect.Left() + nX, rTexture.maRect.Top() + nY ),
                         Size( nWidth, nHeight ) );
     mpImpl = rTexture.mpImpl;
-    if( mpImpl )
-        mpImpl->mnRefCount++;
+    mnSlotNumber = rTexture.mnSlotNumber;
+    if (mpImpl)
+        mpImpl->IncreaseRefCount(mnSlotNumber);
     SAL_INFO( "vcl.opengl", "Copying texture " << Id() << " [" << maRect.Left() << "," << maRect.Top() << "] " << GetWidth() << "x" << GetHeight() );
 }
 
 OpenGLTexture::~OpenGLTexture()
 {
-    if( mpImpl )
+    if (mpImpl)
     {
-        if( mpImpl->mnRefCount == 1 )
+        mpImpl->DecreaseRefCount(mnSlotNumber);
+        if (!mpImpl->ExistRefs())
             delete mpImpl;
-        else
-            mpImpl->mnRefCount--;
     }
 }
 
@@ -325,25 +382,30 @@ OpenGLTexture::operator bool() const
 
 OpenGLTexture&  OpenGLTexture::operator=( const OpenGLTexture& rTexture )
 {
-    if( rTexture.mpImpl )
-        rTexture.mpImpl->mnRefCount++;
-    if( mpImpl )
+    if (rTexture.mpImpl)
+    {
+        rTexture.mpImpl->IncreaseRefCount(rTexture.mnSlotNumber);
+    }
+
+    if (mpImpl)
     {
-        if( mpImpl->mnRefCount == 1 )
+        mpImpl->DecreaseRefCount(mnSlotNumber);
+        if (!mpImpl->ExistRefs())
             delete mpImpl;
-        else
-            mpImpl->mnRefCount--;
     }
 
     maRect = rTexture.maRect;
     mpImpl = rTexture.mpImpl;
+    mnSlotNumber = rTexture.mnSlotNumber;
 
     return *this;
 }
 
 bool OpenGLTexture::operator==( const OpenGLTexture& rTexture ) const
 {
-    return (mpImpl == rTexture.mpImpl && maRect == rTexture.maRect );
+    return (mpImpl == rTexture.mpImpl
+         && maRect == rTexture.maRect
+         && mnSlotNumber == rTexture.mnSlotNumber);
 }
 
 bool OpenGLTexture::operator!=( const OpenGLTexture& rTexture ) const
commit 652e3d2dbdd2d6f43953da3ae37cfc98d350328d
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Mon Aug 10 08:52:14 2015 +0900

    save texture to file as a PNG image
    
    Change-Id: I5605b80f95d89599efe58cf65e1ce3f3581d401f

diff --git a/vcl/inc/opengl/texture.hxx b/vcl/inc/opengl/texture.hxx
index 554a02d..b6839764 100644
--- a/vcl/inc/opengl/texture.hxx
+++ b/vcl/inc/opengl/texture.hxx
@@ -23,7 +23,7 @@
 #include <GL/glew.h>
 #include <vcl/dllapi.h>
 #include <vcl/salgtype.hxx>
-
+#include <rtl/ustring.hxx>
 #include <tools/gen.hxx>
 
 class ImplOpenGLTexture
@@ -71,6 +71,8 @@ public:
     void            Unbind();
     void            Read( GLenum nFormat, GLenum nType, sal_uInt8* pData );
 
+    void            SaveToFile(const OUString& rFileName);
+
     GLenum          GetFilter() const;
     void            SetFilter( GLenum nFilter );
 
diff --git a/vcl/opengl/texture.cxx b/vcl/opengl/texture.cxx
index 2aa99a7..a527ceb 100644
--- a/vcl/opengl/texture.cxx
+++ b/vcl/opengl/texture.cxx
@@ -23,7 +23,8 @@
 
 #include "svdata.hxx"
 
-#include "vcl/salbtype.hxx"
+#include <vcl/salbtype.hxx>
+#include <vcl/pngwrite.hxx>
 
 #include "opengl/framebuffer.hxx"
 #include "opengl/texture.hxx"
@@ -262,6 +263,26 @@ void OpenGLTexture::Unbind()
     CHECK_GL_ERROR();
 }
 
+void OpenGLTexture::SaveToFile(const OUString& rFileName)
+{
+    std::vector<sal_uInt8> pBuffer(GetWidth() * GetHeight() * 4);
+    Read(GL_BGRA, GL_UNSIGNED_BYTE, pBuffer.data());
+    BitmapEx aBitmap = OpenGLHelper::ConvertBGRABufferToBitmapEx(pBuffer.data(), GetWidth(), GetHeight());
+    try
+    {
+        vcl::PNGWriter aWriter(aBitmap);
+        SvFileStream sOutput(rFileName, StreamMode::WRITE);
+        aWriter.Write(sOutput);
+        sOutput.Close();
+    }
+    catch (...)
+    {
+        SAL_WARN("vcl.opengl", "Error writing png to " << rFileName);
+    }
+
+    CHECK_GL_ERROR();
+}
+
 void OpenGLTexture::Read( GLenum nFormat, GLenum nType, sal_uInt8* pData )
 {
     if( mpImpl == NULL )


More information about the Libreoffice-commits mailing list