From 3d8986d7475ef6fdd04ea1286d840d2b570133a0 Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Thu, 15 Dec 2011 14:17:33 +0100 Subject: [PATCH] Reference count glyphs in QSGDistanceFieldGlyphCache. 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 --- src/quick/scenegraph/qsgadaptationlayer.cpp | 22 ++++++++----- src/quick/scenegraph/qsgadaptationlayer_p.h | 6 ++-- .../qsgdefaultdistancefieldglyphcache.cpp | 36 ++++++++-------------- .../qsgdefaultdistancefieldglyphcache_p.h | 8 ++--- src/quick/scenegraph/qsgdistancefieldglyphnode.cpp | 5 ++- 5 files changed, 38 insertions(+), 39 deletions(-) diff --git a/src/quick/scenegraph/qsgadaptationlayer.cpp b/src/quick/scenegraph/qsgadaptationlayer.cpp index 57c0990..73ac81f 100644 --- a/src/quick/scenegraph/qsgadaptationlayer.cpp +++ b/src/quick/scenegraph/qsgadaptationlayer.cpp @@ -132,6 +132,7 @@ const QSGDistanceFieldGlyphCache::Texture *QSGDistanceFieldGlyphCache::glyphText void QSGDistanceFieldGlyphCache::populate(const QVector &glyphs) { + QSet referencedGlyphs; QSet newGlyphs; int count = glyphs.count(); for (int i = 0; i < count; ++i) { @@ -141,6 +142,9 @@ void QSGDistanceFieldGlyphCache::populate(const QVector &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 &glyphs) if (newGlyphs.isEmpty()) return; - QVector glyphsVec; - QSet::const_iterator it = newGlyphs.constBegin(); - while (it != newGlyphs.constEnd()) { - glyphsVec.append(*it); - ++it; - } - requestGlyphs(glyphsVec); + referenceGlyphs(referencedGlyphs); + requestGlyphs(newGlyphs); } void QSGDistanceFieldGlyphCache::release(const QVector &glyphs) { - releaseGlyphs(glyphs); + QSet 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() diff --git a/src/quick/scenegraph/qsgadaptationlayer_p.h b/src/quick/scenegraph/qsgadaptationlayer_p.h index 0c777ef..c4851c3 100644 --- a/src/quick/scenegraph/qsgadaptationlayer_p.h +++ b/src/quick/scenegraph/qsgadaptationlayer_p.h @@ -191,9 +191,10 @@ protected: QPointF position; }; - virtual void requestGlyphs(const QVector &glyphs) = 0; + virtual void requestGlyphs(const QSet &glyphs) = 0; virtual void storeGlyphs(const QHash &glyphs) = 0; - virtual void releaseGlyphs(const QVector &glyphs) = 0; + virtual void referenceGlyphs(const QSet &glyphs) = 0; + virtual void releaseGlyphs(const QSet &glyphs) = 0; void setGlyphsPosition(const QList &glyphs); void setGlyphsTexture(const QVector &glyphs, const Texture &tex); @@ -215,6 +216,7 @@ private: QHash glyphPaths; bool doubleGlyphResolution; QLinkedList m_registeredNodes; + QHash glyphRefCount; GlyphCacheData(QOpenGLContext *ctx) : QOpenGLSharedResource(ctx->shareGroup()) diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp index 4f69ad8..57a9a87 100644 --- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp +++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp @@ -65,31 +65,19 @@ QSGDefaultDistanceFieldGlyphCache::QSGDefaultDistanceFieldGlyphCache(QSGDistance m_textureData = textureData(c); } -void QSGDefaultDistanceFieldGlyphCache::requestGlyphs(const QVector &glyphs) +void QSGDefaultDistanceFieldGlyphCache::requestGlyphs(const QSet &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 glyphPositions; QVector 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::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 setGlyphsTexture(glyphTextures, t); } -void QSGDefaultDistanceFieldGlyphCache::releaseGlyphs(const QVector &glyphs) +void QSGDefaultDistanceFieldGlyphCache::referenceGlyphs(const QSet &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 &glyphs) +{ + m_textureData->unusedGlyphs += glyphs; } void QSGDefaultDistanceFieldGlyphCache::createTexture(int width, int height) diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h index b52ec45..06f9283 100644 --- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h +++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h @@ -42,8 +42,8 @@ #ifndef QSGDEFAULTDISTANCEFIELDGLYPHCACHE_H #define QSGDEFAULTDISTANCEFIELDGLYPHCACHE_H +#include "qsgadaptationlayer_p.h" #include -#include #include #include @@ -54,9 +54,10 @@ class Q_QUICK_EXPORT QSGDefaultDistanceFieldGlyphCache : public QSGDistanceField public: QSGDefaultDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font); - void requestGlyphs(const QVector &glyphs); + void requestGlyphs(const QSet &glyphs); void storeGlyphs(const QHash &glyphs); - void releaseGlyphs(const QVector &glyphs); + void referenceGlyphs(const QSet &glyphs); + void releaseGlyphs(const QSet &glyphs); bool cacheIsFull() const { return m_textureData->currY >= maxTextureSize(); } bool useWorkaroundBrokenFBOReadback() const; @@ -72,7 +73,6 @@ private: GLuint texture; GLuint fbo; QSize size; - QHash glyphRefCount; QSet unusedGlyphs; int currX; int currY; diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp index fe5f16a..f192573 100644 --- a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp +++ b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp @@ -71,7 +71,10 @@ QSGDistanceFieldGlyphNode::~QSGDistanceFieldGlyphNode() delete m_material; if (m_glyph_cache) { - m_glyph_cache->release(m_glyphs.glyphIndexes()); + QVector 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); } -- 2.7.4