Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Yoann Lopes authored and Qt by Nokia committed Dec 21, 2011
1 parent 0febfa0 commit 3d8986d
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 39 deletions.
22 changes: 14 additions & 8 deletions src/quick/scenegraph/qsgadaptationlayer.cpp
Expand Up @@ -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) {
Expand All @@ -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;

Expand All @@ -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()
Expand Down
6 changes: 4 additions & 2 deletions src/quick/scenegraph/qsgadaptationlayer_p.h
Expand Up @@ -191,9 +191,10 @@ class Q_QUICK_EXPORT QSGDistanceFieldGlyphCache
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);
Expand All @@ -215,6 +216,7 @@ class Q_QUICK_EXPORT QSGDistanceFieldGlyphCache
QHash<glyph_t, QPainterPath> glyphPaths;
bool doubleGlyphResolution;
QLinkedList<QSGDistanceFieldGlyphNode*> m_registeredNodes;
QHash<glyph_t, quint32> glyphRefCount;

GlyphCacheData(QOpenGLContext *ctx)
: QOpenGLSharedResource(ctx->shareGroup())
Expand Down
36 changes: 12 additions & 24 deletions src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
Expand Up @@ -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);
Expand Down Expand Up @@ -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)
Expand Down
8 changes: 4 additions & 4 deletions src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
Expand Up @@ -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>

Expand All @@ -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;
Expand All @@ -72,7 +73,6 @@ class Q_QUICK_EXPORT QSGDefaultDistanceFieldGlyphCache : public QSGDistanceField
GLuint texture;
GLuint fbo;
QSize size;
QHash<glyph_t, quint32> glyphRefCount;
QSet<glyph_t> unusedGlyphs;
int currX;
int currY;
Expand Down
5 changes: 4 additions & 1 deletion src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
Expand Up @@ -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);
}

Expand Down

0 comments on commit 3d8986d

Please sign in to comment.