Reference count glyphs in QSGDistanceFieldGlyphCache.
authorYoann Lopes <yoann.lopes@nokia.com>
Thu, 15 Dec 2011 13:17:33 +0000 (14:17 +0100)
committerQt by Nokia <qt-info@nokia.com>
Wed, 21 Dec 2011 11:16:25 +0000 (12:16 +0100)
This was previously done only in the default cache implementation. It
has been moved to the base class.
releaseGlyphs() is called when a glyph is not referenced anymore by any
node.
Added a virtual function referenceGlyphs() that is called everytime glyphs
are being used in a node. This function is called just before
requestGlyphs().

Change-Id: If90f86c328c18ae2a5977847a6adf50b99ea1241
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>
src/quick/scenegraph/qsgadaptationlayer.cpp
src/quick/scenegraph/qsgadaptationlayer_p.h
src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
src/quick/scenegraph/qsgdistancefieldglyphnode.cpp

index 57c0990..73ac81f 100644 (file)
@@ -132,6 +132,7 @@ const QSGDistanceFieldGlyphCache::Texture *QSGDistanceFieldGlyphCache::glyphText
 
 void QSGDistanceFieldGlyphCache::populate(const QVector<glyph_t> &glyphs)
 {
+    QSet<glyph_t> referencedGlyphs;
     QSet<glyph_t> newGlyphs;
     int count = glyphs.count();
     for (int i = 0; i < count; ++i) {
@@ -141,6 +142,9 @@ void QSGDistanceFieldGlyphCache::populate(const QVector<glyph_t> &glyphs)
             continue;
         }
 
+        ++m_cacheData->glyphRefCount[glyphIndex];
+        referencedGlyphs.insert(glyphIndex);
+
         if (m_cacheData->texCoords.contains(glyphIndex) || newGlyphs.contains(glyphIndex))
             continue;
 
@@ -160,18 +164,20 @@ void QSGDistanceFieldGlyphCache::populate(const QVector<glyph_t> &glyphs)
     if (newGlyphs.isEmpty())
         return;
 
-    QVector<glyph_t> glyphsVec;
-    QSet<glyph_t>::const_iterator it = newGlyphs.constBegin();
-    while (it != newGlyphs.constEnd()) {
-        glyphsVec.append(*it);
-        ++it;
-    }
-    requestGlyphs(glyphsVec);
+    referenceGlyphs(referencedGlyphs);
+    requestGlyphs(newGlyphs);
 }
 
 void QSGDistanceFieldGlyphCache::release(const QVector<glyph_t> &glyphs)
 {
-    releaseGlyphs(glyphs);
+    QSet<glyph_t> unusedGlyphs;
+    int count = glyphs.count();
+    for (int i = 0; i < count; ++i) {
+        glyph_t glyphIndex = glyphs.at(i);
+        if (--m_cacheData->glyphRefCount[glyphIndex] == 0 && !glyphTexCoord(glyphIndex).isNull())
+            unusedGlyphs.insert(glyphIndex);
+    }
+    releaseGlyphs(unusedGlyphs);
 }
 
 void QSGDistanceFieldGlyphCache::update()
index 0c777ef..c4851c3 100644 (file)
@@ -191,9 +191,10 @@ protected:
         QPointF position;
     };
 
-    virtual void requestGlyphs(const QVector<glyph_t> &glyphs) = 0;
+    virtual void requestGlyphs(const QSet<glyph_t> &glyphs) = 0;
     virtual void storeGlyphs(const QHash<glyph_t, QImage> &glyphs) = 0;
-    virtual void releaseGlyphs(const QVector<glyph_t> &glyphs) = 0;
+    virtual void referenceGlyphs(const QSet<glyph_t> &glyphs) = 0;
+    virtual void releaseGlyphs(const QSet<glyph_t> &glyphs) = 0;
 
     void setGlyphsPosition(const QList<GlyphPosition> &glyphs);
     void setGlyphsTexture(const QVector<glyph_t> &glyphs, const Texture &tex);
@@ -215,6 +216,7 @@ private:
         QHash<glyph_t, QPainterPath> glyphPaths;
         bool doubleGlyphResolution;
         QLinkedList<QSGDistanceFieldGlyphNode*> m_registeredNodes;
+        QHash<glyph_t, quint32> glyphRefCount;
 
         GlyphCacheData(QOpenGLContext *ctx)
             : QOpenGLSharedResource(ctx->shareGroup())
index 4f69ad8..57a9a87 100644 (file)
@@ -65,31 +65,19 @@ QSGDefaultDistanceFieldGlyphCache::QSGDefaultDistanceFieldGlyphCache(QSGDistance
     m_textureData = textureData(c);
 }
 
-void QSGDefaultDistanceFieldGlyphCache::requestGlyphs(const QVector<glyph_t> &glyphs)
+void QSGDefaultDistanceFieldGlyphCache::requestGlyphs(const QSet<glyph_t> &glyphs)
 {
-    int count = glyphs.count();
-
-    // Avoid useless and costly glyph re-generation
-    if (cacheIsFull() && !m_textureData->unusedGlyphs.isEmpty()) {
-        for (int i = 0; i < count; ++i) {
-            glyph_t glyphIndex = glyphs.at(i);
-            if (containsGlyph(glyphIndex) && m_textureData->unusedGlyphs.contains(glyphIndex))
-                m_textureData->unusedGlyphs.remove(glyphIndex);
-        }
-    }
-
     QList<GlyphPosition> glyphPositions;
     QVector<glyph_t> glyphsToRender;
 
-    for (int i = 0; i < count; ++i) {
-        glyph_t glyphIndex = glyphs.at(i);
-
-        if (++m_textureData->glyphRefCount[glyphIndex] == 1)
-            m_textureData->unusedGlyphs.remove(glyphIndex);
+    for (QSet<glyph_t>::const_iterator it = glyphs.constBegin(); it != glyphs.constEnd() ; ++it) {
+        glyph_t glyphIndex = *it;
 
         if (cacheIsFull() && m_textureData->unusedGlyphs.isEmpty())
             continue;
 
+        m_textureData->unusedGlyphs.remove(glyphIndex);
+
         GlyphPosition p;
         p.glyph = glyphIndex;
         p.position = QPointF(m_textureData->currX, m_textureData->currY);
@@ -162,14 +150,14 @@ void QSGDefaultDistanceFieldGlyphCache::storeGlyphs(const QHash<glyph_t, QImage>
     setGlyphsTexture(glyphTextures, t);
 }
 
-void QSGDefaultDistanceFieldGlyphCache::releaseGlyphs(const QVector<glyph_t> &glyphs)
+void QSGDefaultDistanceFieldGlyphCache::referenceGlyphs(const QSet<glyph_t> &glyphs)
 {
-    int count = glyphs.count();
-    for (int i = 0; i < count; ++i) {
-        glyph_t glyphIndex = glyphs.at(i);
-        if (--m_textureData->glyphRefCount[glyphIndex] == 0 && !glyphTexCoord(glyphIndex).isNull())
-            m_textureData->unusedGlyphs.insert(glyphIndex);
-    }
+    m_textureData->unusedGlyphs -= glyphs;
+}
+
+void QSGDefaultDistanceFieldGlyphCache::releaseGlyphs(const QSet<glyph_t> &glyphs)
+{
+    m_textureData->unusedGlyphs += glyphs;
 }
 
 void QSGDefaultDistanceFieldGlyphCache::createTexture(int width, int height)
index b52ec45..06f9283 100644 (file)
@@ -42,8 +42,8 @@
 #ifndef QSGDEFAULTDISTANCEFIELDGLYPHCACHE_H
 #define QSGDEFAULTDISTANCEFIELDGLYPHCACHE_H
 
+#include "qsgadaptationlayer_p.h"
 #include <QtGui/qopenglfunctions.h>
-#include <private/qsgadaptationlayer_p.h>
 #include <qopenglshaderprogram.h>
 #include <QtGui/private/qopenglengineshadersource_p.h>
 
@@ -54,9 +54,10 @@ class Q_QUICK_EXPORT QSGDefaultDistanceFieldGlyphCache : public QSGDistanceField
 public:
     QSGDefaultDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font);
 
-    void requestGlyphs(const QVector<glyph_t> &glyphs);
+    void requestGlyphs(const QSet<glyph_t> &glyphs);
     void storeGlyphs(const QHash<glyph_t, QImage> &glyphs);
-    void releaseGlyphs(const QVector<glyph_t> &glyphs);
+    void referenceGlyphs(const QSet<glyph_t> &glyphs);
+    void releaseGlyphs(const QSet<glyph_t> &glyphs);
 
     bool cacheIsFull() const { return m_textureData->currY >= maxTextureSize(); }
     bool useWorkaroundBrokenFBOReadback() const;
@@ -72,7 +73,6 @@ private:
         GLuint texture;
         GLuint fbo;
         QSize size;
-        QHash<glyph_t, quint32> glyphRefCount;
         QSet<glyph_t> unusedGlyphs;
         int currX;
         int currY;
index fe5f16a..f192573 100644 (file)
@@ -71,7 +71,10 @@ QSGDistanceFieldGlyphNode::~QSGDistanceFieldGlyphNode()
     delete m_material;
 
     if (m_glyph_cache) {
-        m_glyph_cache->release(m_glyphs.glyphIndexes());
+        QVector<quint32> glyphIndexes;
+        for (int i = 0; i < m_allGlyphs.count(); ++i)
+            glyphIndexes.append(m_allGlyphs.at(i).glyphIndex);
+        m_glyph_cache->release(glyphIndexes);
         m_glyph_cache->unregisterGlyphNode(this);
     }