[Libreoffice-commits] core.git: Branch 'libreoffice-5-1' - vcl/inc vcl/opengl vcl/win

Tomaž Vajngerl tomaz.vajngerl at collabora.co.uk
Mon Apr 18 10:04:41 UTC 2016


 vcl/inc/opengl/PackedTextureAtlas.hxx |    6 +++
 vcl/opengl/PackedTextureAtlas.cxx     |   44 ++++++++++++++++++++++----
 vcl/win/source/gdi/winlayout.cxx      |   57 +++++++++++++++++++++++++++++++---
 3 files changed, 96 insertions(+), 11 deletions(-)

New commits:
commit f691a50a78c8f4f157fbb432efba059d723d1111
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Mon Apr 11 18:23:18 2016 +0900

    tdf#94682 limit the number of textures for the glyph texture atlas
    
    Previously the number of textures in a packed texture atlas was
    not limited. After some time the number of the textures could
    grow quite a lot, however the first textures could contain very
    little glyphs that are valid. In this commit we add a new method
    ReduceTextureNumber which when called, reduces the number of
    textures that are tracked by the texutre atlas to the specified
    input number, and returnes the texture IDs that were removed so
    the caller can now clean-up any invalid (OpenGLTexutre) objects.
    
    Change-Id: I7790e8dddb4586167f860e0ecc81bda1f4dae21a
    Reviewed-on: https://gerrit.libreoffice.org/24071
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Michael Meeks <michael.meeks at collabora.com>

diff --git a/vcl/inc/opengl/PackedTextureAtlas.hxx b/vcl/inc/opengl/PackedTextureAtlas.hxx
index 17501f3..4d9015f 100644
--- a/vcl/inc/opengl/PackedTextureAtlas.hxx
+++ b/vcl/inc/opengl/PackedTextureAtlas.hxx
@@ -35,10 +35,16 @@ class VCL_PLUGIN_PUBLIC PackedTextureAtlasManager
     void CreateNewTexture();
 
 public:
+
+    /**
+     * nTextureWidth and nTextureHeight are the dimensions of the common texture(s)
+     * nTextureLimit is the maximum limit of that a texture atlas can have (0 or less - unlimited)
+     */
     PackedTextureAtlasManager(int nTextureWidth, int nTextureHeight);
     ~PackedTextureAtlasManager();
     OpenGLTexture InsertBuffer(int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData);
     OpenGLTexture Reserve(int nWidth, int nHeight);
+    std::vector<GLuint> ReduceTextureNumber(int nMaxNumberOfTextures);
 };
 
 #endif // INCLUDED_VCL_INC_OPENGL_PACKEDTEXTUREATLAS_HXX
diff --git a/vcl/opengl/PackedTextureAtlas.cxx b/vcl/opengl/PackedTextureAtlas.cxx
index 60fa1e9..0231cbd 100644
--- a/vcl/opengl/PackedTextureAtlas.cxx
+++ b/vcl/opengl/PackedTextureAtlas.cxx
@@ -24,12 +24,21 @@ struct Node
     std::unique_ptr<Node> mRightNode;
     bool mOccupied;
 
+    Node(int nWidth, int nHeight);
+
     Node(Rectangle& aRectangle);
 
     bool isLeaf();
     Node* insert(int nWidth, int nHeight, int nPadding);
 };
 
+Node::Node(int nWidth, int nHeight)
+    : mRectangle(Rectangle(Point(), Size(nWidth, nHeight)))
+    , mLeftNode()
+    , mRightNode()
+    , mOccupied(false)
+{}
+
 Node::Node(Rectangle& aRectangle)
     : mRectangle(aRectangle)
     , mLeftNode()
@@ -101,8 +110,15 @@ Node* Node::insert(int nWidth, int nHeight, int nPadding)
 
 struct PackedTexture
 {
-    std::unique_ptr<Node> mpRootNode;
     ImplOpenGLTexture* mpTexture;
+    std::unique_ptr<Node> mpRootNode;
+    int mnDeallocatedArea;
+
+    PackedTexture(int nWidth, int nHeight)
+        : mpTexture(new ImplOpenGLTexture(nWidth, nHeight, true))
+        , mpRootNode(new Node(nWidth, nHeight))
+        , mnDeallocatedArea(0)
+    {}
 };
 
 PackedTextureAtlasManager::PackedTextureAtlasManager(int nTextureWidth, int nTextureHeight)
@@ -116,18 +132,17 @@ PackedTextureAtlasManager::~PackedTextureAtlasManager()
     for (std::unique_ptr<PackedTexture>& pPackedTexture : maPackedTextures)
     {
         // Free texture early in VCL shutdown while we have a context.
-        pPackedTexture->mpTexture->Dispose();
-        pPackedTexture->mpTexture->DecreaseRefCount(0);
+        delete pPackedTexture->mpTexture;
     }
 }
 
 void PackedTextureAtlasManager::CreateNewTexture()
 {
-    std::unique_ptr<PackedTexture> pPackedTexture(new PackedTexture);
-    pPackedTexture->mpTexture = new ImplOpenGLTexture(mnTextureWidth, mnTextureHeight, true);
-    Rectangle aInitialRect(Point(0, 0), Size(mnTextureWidth, mnTextureHeight));
-    pPackedTexture->mpRootNode.reset(new Node(aInitialRect));
+    std::unique_ptr<PackedTexture> pPackedTexture(new PackedTexture(mnTextureWidth, mnTextureHeight));
+    GLuint nTextureID = pPackedTexture->mpTexture->mnTexture;
     maPackedTextures.push_back(std::move(pPackedTexture));
+    VCL_GL_INFO("PackedTextureAtlas::CreateNewTexture adding texture: " << nTextureID <<
+                " atlases: " << maPackedTextures.size());
 }
 
 OpenGLTexture PackedTextureAtlasManager::Reserve(int nWidth, int nHeight)
@@ -161,4 +176,19 @@ OpenGLTexture PackedTextureAtlasManager::InsertBuffer(int nWidth, int nHeight, i
     return aTexture;
 }
 
+std::vector<GLuint> PackedTextureAtlasManager::ReduceTextureNumber(int nMaxNumberOfTextures)
+{
+    std::vector<GLuint> aTextureIDs;
+    while (int(maPackedTextures.size()) > nMaxNumberOfTextures)
+    {
+        // Remove oldest created texture
+        GLuint nTextureID = maPackedTextures[0]->mpTexture->mnTexture;
+        aTextureIDs.push_back(nTextureID);
+        maPackedTextures.erase(maPackedTextures.begin());
+        VCL_GL_INFO("PackedTextureAtlas::ReduceTextureNumber removing texture: " << nTextureID <<
+                    " atlases: " << maPackedTextures.size());
+    }
+    return aTextureIDs;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/win/source/gdi/winlayout.cxx b/vcl/win/source/gdi/winlayout.cxx
index 49aa0c4..f5b3a6b 100644
--- a/vcl/win/source/gdi/winlayout.cxx
+++ b/vcl/win/source/gdi/winlayout.cxx
@@ -48,6 +48,7 @@
 #include <winver.h>
 
 #include <unordered_map>
+#include <unordered_set>
 
 typedef std::unordered_map<int,int> IntMap;
 
@@ -97,19 +98,66 @@ struct OpenGLGlyphDrawElement
     }
 };
 
+class GlyphCache;
+
+struct GlobalGlyphCache
+{
+    GlobalGlyphCache()
+        : maPackedTextureAtlas(2048, 2048)
+    {}
+
+    PackedTextureAtlasManager maPackedTextureAtlas;
+    std::unordered_set<GlyphCache*> maGlyphCaches;
+};
+
 class GlyphCache
 {
 private:
-    static PackedTextureAtlasManager sPackedTextureAtlas;
+    static std::unique_ptr<GlobalGlyphCache> gGlobalGlyphCache;
     std::unordered_map<int, OpenGLGlyphDrawElement> maOpenGLTextureCache;
 
 public:
     GlyphCache()
-    {}
+    {
+        gGlobalGlyphCache.get()->maGlyphCaches.insert(this);
+    }
+
+    ~GlyphCache()
+    {
+        gGlobalGlyphCache.get()->maGlyphCaches.erase(this);
+    }
 
     void ReserveTextureSpace(OpenGLGlyphDrawElement& rElement, int nWidth, int nHeight)
     {
-        rElement.maTexture = sPackedTextureAtlas.Reserve(nWidth, nHeight);
+        GlobalGlyphCache* pGlobalGlyphCache = gGlobalGlyphCache.get();
+        rElement.maTexture = pGlobalGlyphCache->maPackedTextureAtlas.Reserve(nWidth, nHeight);
+        std::vector<GLuint> aTextureIDs = pGlobalGlyphCache->maPackedTextureAtlas.ReduceTextureNumber(8);
+        if (!aTextureIDs.empty())
+        {
+            for (auto& pGlyphCache: pGlobalGlyphCache->maGlyphCaches)
+            {
+                pGlyphCache->RemoveTextures(aTextureIDs);
+            }
+        }
+    }
+
+    void RemoveTextures(std::vector<GLuint>& rTextureIDs)
+    {
+        auto it = maOpenGLTextureCache.begin();
+
+        while (it != maOpenGLTextureCache.end())
+        {
+            GLuint nTextureID = it->second.maTexture.Id();
+
+            if (std::find(rTextureIDs.begin(), rTextureIDs.end(), nTextureID) != rTextureIDs.end())
+            {
+                it = maOpenGLTextureCache.erase(it);
+            }
+            else
+            {
+                it++;
+            }
+        }
     }
 
     void PutDrawElementInCache(const OpenGLGlyphDrawElement& rElement, int nGlyphIndex)
@@ -130,7 +178,8 @@ public:
     }
 };
 
-PackedTextureAtlasManager GlyphCache::sPackedTextureAtlas(2048, 2048);
+// static initialization
+std::unique_ptr<GlobalGlyphCache> GlyphCache::gGlobalGlyphCache(new GlobalGlyphCache);
 
 // win32 specific physical font instance
 class ImplWinFontEntry : public ImplFontEntry


More information about the Libreoffice-commits mailing list