diff options
author | Yoann Lopes <yoann.lopes@nokia.com> | 2011-12-15 14:17:33 +0100 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2011-12-21 12:16:25 +0100 |
commit | 3d8986d7475ef6fdd04ea1286d840d2b570133a0 (patch) | |
tree | 66cec7e44c432c904b0e33dec4ce34ef622c7b67 | |
parent | 0febfa03b62a4449c42ad1e675777b7b099ebaa3 (diff) |
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 <eskil.abrahamsen-blomfeldt@nokia.com>
5 files changed, 38 insertions, 39 deletions
diff --git a/src/quick/scenegraph/qsgadaptationlayer.cpp b/src/quick/scenegraph/qsgadaptationlayer.cpp index 57c0990f1d..73ac81fd5b 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<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() diff --git a/src/quick/scenegraph/qsgadaptationlayer_p.h b/src/quick/scenegraph/qsgadaptationlayer_p.h index 0c777ef639..c4851c326b 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<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()) diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp index 4f69ad8c44..57a9a8741c 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<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) diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h index b52ec45107..06f9283bcc 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 <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; diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp index fe5f16a0a2..f192573624 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<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); } |