aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/scenegraph
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/scenegraph')
-rw-r--r--src/quick/scenegraph/coreapi/qsgrendernode.cpp34
-rw-r--r--src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp86
-rw-r--r--src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h59
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode.cpp67
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode_p.h5
-rw-r--r--src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp19
-rw-r--r--src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h12
7 files changed, 170 insertions, 112 deletions
diff --git a/src/quick/scenegraph/coreapi/qsgrendernode.cpp b/src/quick/scenegraph/coreapi/qsgrendernode.cpp
index ee9fd9fbbb..8012af9cfc 100644
--- a/src/quick/scenegraph/coreapi/qsgrendernode.cpp
+++ b/src/quick/scenegraph/coreapi/qsgrendernode.cpp
@@ -63,14 +63,14 @@ void QSGRenderNode::setInheritedOpacity(qreal opacity)
This function should return a mask where each bit represents OpenGL states changed by
the \l render() function:
\list
- \o DepthState - depth write mask, depth test enabled, depth comparison function
- \o StencilState - stencil write masks, stencil test enabled, stencil operations,
+ \li DepthState - depth write mask, depth test enabled, depth comparison function
+ \li StencilState - stencil write masks, stencil test enabled, stencil operations,
stencil comparison functions
- \o ScissorState - scissor enabled, scissor test enabled
- \o ColorState - clear color, color write mask
- \o BlendState - blend enabled, blend function
- \o CullState - front face, cull face enabled
- \o ViewportState - viewport
+ \li ScissorState - scissor enabled, scissor test enabled
+ \li ColorState - clear color, color write mask
+ \li BlendState - blend enabled, blend function
+ \li CullState - front face, cull face enabled
+ \li ViewportState - viewport
\endlist
The function is called by the renderer so it can reset the OpenGL states after rendering this
@@ -96,17 +96,17 @@ void QSGRenderNode::setInheritedOpacity(qreal opacity)
The following states are set before this function is called:
\list
- \o glDepthMask(false)
- \o glDisable(GL_DEPTH_TEST)
- \o glStencilMask(0)
- \o glEnable(GL_STENCIL_TEST)/glDisable(GL_STENCIL_TEST) depending on clip
- \o glStencilFunc(GL_EQUAL, state.stencilValue, 0xff) depending on clip
- \o glEnable(GL_SCISSOR_TEST)/glDisable(GL_SCISSOR_TEST) depending on clip
- \o glScissor(state.scissorRect.x(), state.scissorRect.y(),
+ \li glDepthMask(false)
+ \li glDisable(GL_DEPTH_TEST)
+ \li glStencilMask(0)
+ \li glEnable(GL_STENCIL_TEST)/glDisable(GL_STENCIL_TEST) depending on clip
+ \li glStencilFunc(GL_EQUAL, state.stencilValue, 0xff) depending on clip
+ \li glEnable(GL_SCISSOR_TEST)/glDisable(GL_SCISSOR_TEST) depending on clip
+ \li glScissor(state.scissorRect.x(), state.scissorRect.y(),
state.scissorRect.width(), state.scissorRect.height()) depending on clip
- \o glEnable(GL_BLEND)
- \o glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)
- \o glDisable(GL_CULL_FACE)
+ \li glEnable(GL_BLEND)
+ \li glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)
+ \li glDisable(GL_CULL_FACE)
\endlist
States that are not listed above, but are included in \l StateFlags, can have arbitrary
diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
index 05d076ec1e..5864f35060 100644
--- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
+++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
@@ -62,6 +62,7 @@ QSGDefaultDistanceFieldGlyphCache::DistanceFieldTextureData *QSGDefaultDistanceF
QSGDefaultDistanceFieldGlyphCache::QSGDefaultDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font)
: QSGDistanceFieldGlyphCache(man, c, font)
, m_maxTextureSize(0)
+ , m_maxTextureCount(3)
{
m_textureData = textureData(c);
}
@@ -77,25 +78,32 @@ void QSGDefaultDistanceFieldGlyphCache::requestGlyphs(const QSet<glyph_t> &glyph
if (cacheIsFull() && m_textureData->unusedGlyphs.isEmpty())
continue;
+ if (textureIsFull(m_textureData->currentTexture) && m_textureData->textures.count() < m_maxTextureCount)
+ m_textureData->currentTexture = m_textureData->addTexture();
+
m_textureData->unusedGlyphs.remove(glyphIndex);
+ DistanceFieldTextureData::TextureInfo *tex = m_textureData->currentTexture;
+
GlyphPosition p;
p.glyph = glyphIndex;
- p.position = QPointF(m_textureData->currX, m_textureData->currY);
+ p.position = QPointF(tex->currX, tex->currY);
if (!cacheIsFull()) {
- m_textureData->currX += QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution());
- if (m_textureData->currX >= maxTextureSize()) {
- m_textureData->currX = 0;
- m_textureData->currY += QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution());
+ tex->currX += QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution());
+ if (tex->currX >= maxTextureSize()) {
+ tex->currX = 0;
+ tex->currY += QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution());
}
} else {
// Recycle glyphs
if (!m_textureData->unusedGlyphs.isEmpty()) {
glyph_t unusedGlyph = *m_textureData->unusedGlyphs.constBegin();
TexCoord unusedCoord = glyphTexCoord(unusedGlyph);
+ tex = m_textureData->glyphsTexture.value(unusedGlyph);
p.position = QPointF(unusedCoord.x, unusedCoord.y);
m_textureData->unusedGlyphs.remove(unusedGlyph);
+ m_textureData->glyphsTexture.remove(unusedGlyph);
removeGlyph(unusedGlyph);
}
}
@@ -103,6 +111,7 @@ void QSGDefaultDistanceFieldGlyphCache::requestGlyphs(const QSet<glyph_t> &glyph
if (p.position.y() < maxTextureSize()) {
glyphPositions.append(p);
glyphsToRender.append(glyphIndex);
+ m_textureData->glyphsTexture.insert(glyphIndex, tex);
}
}
@@ -114,41 +123,46 @@ void QSGDefaultDistanceFieldGlyphCache::storeGlyphs(const QHash<glyph_t, QImage>
{
int requiredWidth = maxTextureSize();
int rows = 128 / (requiredWidth / QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution())); // Enough rows to fill the latin1 set by default..
- int requiredHeight = qMin(maxTextureSize(),
- qMax(m_textureData->currY + QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution()),
- QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution()) * rows));
-
- resizeTexture((requiredWidth), (requiredHeight));
- glBindTexture(GL_TEXTURE_2D, m_textureData->texture);
- QVector<glyph_t> glyphTextures;
+ QHash<DistanceFieldTextureData::TextureInfo *, QVector<glyph_t> > glyphTextures;
QHash<glyph_t, QImage>::const_iterator it;
for (it = glyphs.constBegin(); it != glyphs.constEnd(); ++it) {
glyph_t glyphIndex = it.key();
TexCoord c = glyphTexCoord(glyphIndex);
+ DistanceFieldTextureData::TextureInfo *texInfo = m_textureData->glyphsTexture.value(glyphIndex);
- glyphTextures.append(glyphIndex);
+ int requiredHeight = qMin(maxTextureSize(),
+ qMax(texInfo->currY + QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution()),
+ QT_DISTANCEFIELD_TILESIZE(doubleGlyphResolution()) * rows));
+
+ resizeTexture(texInfo, requiredWidth, requiredHeight);
+ glBindTexture(GL_TEXTURE_2D, texInfo->texture);
+
+ glyphTextures[texInfo].append(glyphIndex);
QImage glyph = it.value();
if (useWorkaroundBrokenFBOReadback()) {
uchar *inBits = glyph.scanLine(0);
- uchar *outBits = m_textureData->image.scanLine(int(c.y)) + int(c.x);
+ uchar *outBits = texInfo->image.scanLine(int(c.y)) + int(c.x);
for (int y = 0; y < glyph.height(); ++y) {
qMemCopy(outBits, inBits, glyph.width());
inBits += glyph.bytesPerLine();
- outBits += m_textureData->image.bytesPerLine();
+ outBits += texInfo->image.bytesPerLine();
}
}
glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, glyph.width(), glyph.height(), GL_ALPHA, GL_UNSIGNED_BYTE, glyph.constBits());
}
- Texture t;
- t.textureId = m_textureData->texture;
- t.size = m_textureData->size;
- setGlyphsTexture(glyphTextures, t);
+ QHash<DistanceFieldTextureData::TextureInfo *, QVector<glyph_t> >::const_iterator i;
+ for (i = glyphTextures.constBegin(); i != glyphTextures.constEnd(); ++i) {
+ Texture t;
+ t.textureId = i.key()->texture;
+ t.size = i.key()->size;
+ setGlyphsTexture(i.value(), t);
+ }
}
void QSGDefaultDistanceFieldGlyphCache::referenceGlyphs(const QSet<glyph_t> &glyphs)
@@ -161,15 +175,15 @@ void QSGDefaultDistanceFieldGlyphCache::releaseGlyphs(const QSet<glyph_t> &glyph
m_textureData->unusedGlyphs += glyphs;
}
-void QSGDefaultDistanceFieldGlyphCache::createTexture(int width, int height)
+void QSGDefaultDistanceFieldGlyphCache::createTexture(DistanceFieldTextureData::TextureInfo *texInfo, int width, int height)
{
- if (useWorkaroundBrokenFBOReadback() && m_textureData->image.isNull())
- m_textureData->image = QImage(width, height, QImage::Format_Indexed8);
+ if (useWorkaroundBrokenFBOReadback() && texInfo->image.isNull())
+ texInfo->image = QImage(width, height, QImage::Format_Indexed8);
while (glGetError() != GL_NO_ERROR) { }
- glGenTextures(1, &m_textureData->texture);
- glBindTexture(GL_TEXTURE_2D, m_textureData->texture);
+ glGenTextures(1, &texInfo->texture);
+ glBindTexture(GL_TEXTURE_2D, texInfo->texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@@ -177,35 +191,35 @@ void QSGDefaultDistanceFieldGlyphCache::createTexture(int width, int height)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- m_textureData->size = QSize(width, height);
+ texInfo->size = QSize(width, height);
GLuint error = glGetError();
if (error != GL_NO_ERROR) {
glBindTexture(GL_TEXTURE_2D, 0);
- glDeleteTextures(1, &m_textureData->texture);
- m_textureData->texture = 0;
+ glDeleteTextures(1, &texInfo->texture);
+ texInfo->texture = 0;
}
}
-void QSGDefaultDistanceFieldGlyphCache::resizeTexture(int width, int height)
+void QSGDefaultDistanceFieldGlyphCache::resizeTexture(DistanceFieldTextureData::TextureInfo *texInfo, int width, int height)
{
- int oldWidth = m_textureData->size.width();
- int oldHeight = m_textureData->size.height();
+ int oldWidth = texInfo->size.width();
+ int oldHeight = texInfo->size.height();
if (width == oldWidth && height == oldHeight)
return;
- GLuint oldTexture = m_textureData->texture;
- createTexture(width, height);
+ GLuint oldTexture = texInfo->texture;
+ createTexture(texInfo, width, height);
if (!oldTexture)
return;
- updateTexture(oldTexture, m_textureData->texture, m_textureData->size);
+ updateTexture(oldTexture, texInfo->texture, texInfo->size);
if (useWorkaroundBrokenFBOReadback()) {
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, oldWidth, oldHeight, GL_ALPHA, GL_UNSIGNED_BYTE, m_textureData->image.constBits());
- m_textureData->image = m_textureData->image.copy(0, 0, width, height);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, oldWidth, oldHeight, GL_ALPHA, GL_UNSIGNED_BYTE, texInfo->image.constBits());
+ texInfo->image = texInfo->image.copy(0, 0, width, height);
glDeleteTextures(1, &oldTexture);
return;
}
@@ -267,7 +281,7 @@ void QSGDefaultDistanceFieldGlyphCache::resizeTexture(int width, int height)
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- glBindTexture(GL_TEXTURE_2D, m_textureData->texture);
+ glBindTexture(GL_TEXTURE_2D, texInfo->texture);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight);
diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
index 76e4a64e60..12bbcce060 100644
--- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
+++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
@@ -59,37 +59,55 @@ public:
void referenceGlyphs(const QSet<glyph_t> &glyphs);
void releaseGlyphs(const QSet<glyph_t> &glyphs);
- bool cacheIsFull() const { return m_textureData->currY >= maxTextureSize(); }
+ bool cacheIsFull() const {
+ return m_textureData->textures.count() == m_maxTextureCount
+ && textureIsFull(m_textureData->currentTexture);
+ }
bool useWorkaroundBrokenFBOReadback() const;
int maxTextureSize() const;
-private:
- void createTexture(int width, int height);
- void resizeTexture(int width, int height);
+ void setMaxTextureCount(int max) { m_maxTextureCount = max; }
+ int maxTextureCount() const { return m_maxTextureCount; }
+private:
mutable int m_maxTextureSize;
+ int m_maxTextureCount;
struct DistanceFieldTextureData : public QOpenGLSharedResource {
- GLuint texture;
+ struct TextureInfo {
+ GLuint texture;
+ QSize size;
+ int currX;
+ int currY;
+ QImage image;
+
+ TextureInfo() : texture(0), currX(0), currY(0)
+ { }
+ };
+
+ TextureInfo *currentTexture;
+ QList<TextureInfo> textures;
+ QHash<glyph_t, TextureInfo *> glyphsTexture;
GLuint fbo;
- QSize size;
QSet<glyph_t> unusedGlyphs;
- int currX;
- int currY;
- QImage image;
QOpenGLShaderProgram *blitProgram;
GLfloat blitVertexCoordinateArray[8];
GLfloat blitTextureCoordinateArray[8];
+ TextureInfo *addTexture()
+ {
+ textures.append(TextureInfo());
+ return &textures.last();
+ }
+
DistanceFieldTextureData(QOpenGLContext *ctx)
: QOpenGLSharedResource(ctx->shareGroup())
- , texture(0)
, fbo(0)
- , currX(0)
- , currY(0)
, blitProgram(0)
{
+ currentTexture = addTexture();
+
blitVertexCoordinateArray[0] = -1.0f;
blitVertexCoordinateArray[1] = -1.0f;
blitVertexCoordinateArray[2] = 1.0f;
@@ -111,19 +129,26 @@ private:
void invalidateResource()
{
- texture = 0;
+ glyphsTexture.clear();
+ textures.clear();
fbo = 0;
- size = QSize();
delete blitProgram;
blitProgram = 0;
+
+ currentTexture = addTexture();
}
void freeResource(QOpenGLContext *ctx)
{
- glDeleteTextures(1, &texture);
+ glyphsTexture.clear();
+ for (int i = 0; i < textures.count(); ++i)
+ glDeleteTextures(1, &textures[i].texture);
+ textures.clear();
ctx->functions()->glDeleteFramebuffers(1, &fbo);
delete blitProgram;
blitProgram = 0;
+
+ currentTexture = addTexture();
}
void createBlitProgram()
@@ -155,6 +180,10 @@ private:
}
};
+ void createTexture(DistanceFieldTextureData::TextureInfo * texInfo, int width, int height);
+ void resizeTexture(DistanceFieldTextureData::TextureInfo * texInfo, int width, int height);
+ bool textureIsFull (const DistanceFieldTextureData::TextureInfo *tex) const { return tex->currY >= maxTextureSize(); }
+
DistanceFieldTextureData *textureData(QOpenGLContext *c);
DistanceFieldTextureData *m_textureData;
static QHash<QString, QOpenGLMultiGroupSharedResource> m_textures_data;
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
index 79e5c3b0f4..a86e663755 100644
--- a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
@@ -71,11 +71,9 @@ QSGDistanceFieldGlyphNode::~QSGDistanceFieldGlyphNode()
delete m_material;
if (m_glyph_cache) {
- 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->release(m_glyphs.glyphIndexes());
m_glyph_cache->unregisterGlyphNode(this);
+ m_glyph_cache->unregisterOwnerElement(ownerElement());
}
for (int i = 0; i < m_nodesToDelete.count(); ++i)
@@ -122,15 +120,9 @@ void QSGDistanceFieldGlyphNode::setGlyphs(const QPointF &position, const QGlyphR
}
m_glyph_cache->populate(glyphs.glyphIndexes());
- const QVector<quint32> &glyphIndexes = m_glyphs.glyphIndexes();
- const QVector<QPointF> &glyphPositions = m_glyphs.positions();
- for (int i = 0; i < glyphIndexes.count(); ++i) {
- GlyphInfo gi;
- gi.glyphIndex = glyphIndexes.at(i);
- gi.position = glyphPositions.at(i);
- m_allGlyphs.append(gi);
- m_allGlyphIndexesLookup.insert(gi.glyphIndex);
- }
+ const QVector<quint32> glyphIndexes = m_glyphs.glyphIndexes();
+ for (int i = 0; i < glyphIndexes.count(); ++i)
+ m_allGlyphIndexesLookup.insert(glyphIndexes.at(i));
m_dirtyGeometry = true;
m_dirtyMaterial = true;
@@ -204,34 +196,43 @@ void QSGDistanceFieldGlyphNode::updateGeometry()
Q_ASSERT(g->indexType() == GL_UNSIGNED_SHORT);
- QHash<const QSGDistanceFieldGlyphCache::Texture *, QList<GlyphInfo> > glyphsInOtherTextures;
+ QHash<const QSGDistanceFieldGlyphCache::Texture *, GlyphInfo> glyphsInOtherTextures;
+
+ const QVector<quint32> indexes = m_glyphs.glyphIndexes();
+ const QVector<QPointF> positions = m_glyphs.positions();
QVector<QSGGeometry::TexturedPoint2D> vp;
- vp.reserve(m_allGlyphs.size() * 4);
+ vp.reserve(indexes.size() * 4);
QVector<ushort> ip;
- ip.reserve(m_allGlyphs.size() * 6);
+ ip.reserve(indexes.size() * 6);
QPointF margins(2, 2);
QPointF texMargins = margins / m_glyph_cache->fontScale();
- for (int i = 0; i < m_allGlyphs.size(); ++i) {
- GlyphInfo glyphInfo = m_allGlyphs.at(i);
- QSGDistanceFieldGlyphCache::TexCoord c = m_glyph_cache->glyphTexCoord(glyphInfo.glyphIndex);
+
+ for (int i = 0; i < indexes.size(); ++i) {
+ const int glyphIndex = indexes.at(i);
+ QSGDistanceFieldGlyphCache::TexCoord c = m_glyph_cache->glyphTexCoord(glyphIndex);
if (c.isNull())
continue;
- const QSGDistanceFieldGlyphCache::Texture *texture = m_glyph_cache->glyphTexture(glyphInfo.glyphIndex);
+ const QPointF position = positions.at(i);
+
+ const QSGDistanceFieldGlyphCache::Texture *texture = m_glyph_cache->glyphTexture(glyphIndex);
if (texture->textureId && !m_texture)
m_texture = texture;
if (m_texture != texture) {
- if (texture->textureId)
- glyphsInOtherTextures[texture].append(glyphInfo);
+ if (texture->textureId) {
+ GlyphInfo &glyphInfo = glyphsInOtherTextures[texture];
+ glyphInfo.indexes.append(glyphIndex);
+ glyphInfo.positions.append(position);
+ }
continue;
}
- QSGDistanceFieldGlyphCache::Metrics metrics = m_glyph_cache->glyphMetrics(glyphInfo.glyphIndex);
+ QSGDistanceFieldGlyphCache::Metrics metrics = m_glyph_cache->glyphMetrics(glyphIndex);
if (!metrics.isNull() && !c.isNull()) {
metrics.width += margins.x() * 2;
@@ -244,8 +245,8 @@ void QSGDistanceFieldGlyphNode::updateGeometry()
c.height += texMargins.y() * 2;
}
- qreal x = glyphInfo.position.x() + metrics.baselineX + m_position.x();
- qreal y = glyphInfo.position.y() - metrics.baselineY + m_position.y();
+ qreal x = position.x() + metrics.baselineX + m_position.x();
+ qreal y = position.y() - metrics.baselineY + m_position.y();
m_boundingRect |= QRectF(x, y, metrics.width, metrics.height);
@@ -260,7 +261,7 @@ void QSGDistanceFieldGlyphNode::updateGeometry()
float ty2 = ty1 + c.height;
if (m_baseLine.isNull())
- m_baseLine = glyphInfo.position;
+ m_baseLine = position;
int o = vp.size();
@@ -285,7 +286,7 @@ void QSGDistanceFieldGlyphNode::updateGeometry()
ip.append(o + 0);
}
- QHash<const QSGDistanceFieldGlyphCache::Texture *, QList<GlyphInfo> >::const_iterator ite = glyphsInOtherTextures.constBegin();
+ QHash<const QSGDistanceFieldGlyphCache::Texture *, GlyphInfo>::const_iterator ite = glyphsInOtherTextures.constBegin();
while (ite != glyphsInOtherTextures.constEnd()) {
QHash<const QSGDistanceFieldGlyphCache::Texture *, QSGDistanceFieldGlyphNode *>::iterator subIt = m_subNodes.find(ite.key());
if (subIt == m_subNodes.end()) {
@@ -299,17 +300,9 @@ void QSGDistanceFieldGlyphNode::updateGeometry()
subIt = m_subNodes.insert(ite.key(), subNode);
}
- QVector<quint32> glyphIndexes;
- QVector<QPointF> positions;
- const QList<GlyphInfo> &subNodeGlyphs = ite.value();
- for (int i = 0; i < subNodeGlyphs.count(); ++i) {
- const GlyphInfo &info = subNodeGlyphs.at(i);
- glyphIndexes.append(info.glyphIndex);
- positions.append(info.position);
- }
QGlyphRun subNodeGlyphRun(m_glyphs);
- subNodeGlyphRun.setGlyphIndexes(glyphIndexes);
- subNodeGlyphRun.setPositions(positions);
+ subNodeGlyphRun.setGlyphIndexes(ite->indexes);
+ subNodeGlyphRun.setPositions(ite->positions);
subIt.value()->setGlyphs(m_originalPosition, subNodeGlyphRun);
subIt.value()->update();
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h
index 65ac2d499c..9406ee1bc8 100644
--- a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h
@@ -96,11 +96,10 @@ private:
QList<QSGDistanceFieldGlyphNode *> m_nodesToDelete;
struct GlyphInfo {
- quint32 glyphIndex;
- QPointF position;
+ QVector<quint32> indexes;
+ QVector<QPointF> positions;
};
QSet<quint32> m_allGlyphIndexesLookup;
- QList<GlyphInfo> m_allGlyphs;
uint m_dirtyGeometry: 1;
uint m_dirtyMaterial: 1;
diff --git a/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp
index 76fb9036f4..cd5aaaedd7 100644
--- a/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp
+++ b/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp
@@ -234,14 +234,25 @@ void QSGSharedDistanceFieldGlyphCache::releaseGlyphs(const QSet<glyph_t> &glyphs
void QSGSharedDistanceFieldGlyphCache::registerOwnerElement(QQuickItem *ownerElement)
{
- bool ok = connect(this, SIGNAL(glyphsPending()), ownerElement, SLOT(triggerPreprocess()));
- Q_ASSERT_X(ok, Q_FUNC_INFO, "QML element that owns a glyph node must have triggerPreprocess() slot");
- Q_UNUSED(ok);
+ Owner &owner = m_registeredOwners[ownerElement];
+ if (owner.ref == 0) {
+ owner.item = ownerElement;
+
+ bool ok = connect(this, SIGNAL(glyphsPending()), ownerElement, SLOT(triggerPreprocess()));
+ Q_ASSERT_X(ok, Q_FUNC_INFO, "QML element that owns a glyph node must have triggerPreprocess() slot");
+ Q_UNUSED(ok);
+ }
+ ++owner.ref;
}
void QSGSharedDistanceFieldGlyphCache::unregisterOwnerElement(QQuickItem *ownerElement)
{
- disconnect(this, SIGNAL(glyphsPending()), ownerElement, SLOT(triggerPreprocess()));
+ QHash<QQuickItem *, Owner>::iterator it = m_registeredOwners.find(ownerElement);
+ if (it != m_registeredOwners.end() && --it->ref <= 0) {
+ if (it->item)
+ disconnect(this, SIGNAL(glyphsPending()), ownerElement, SLOT(triggerPreprocess()));
+ m_registeredOwners.erase(it);
+ }
}
#if defined(QSGSHAREDDISTANCEFIELDGLYPHCACHE_DEBUG_)
diff --git a/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h b/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h
index 4a91b4473a..19844bbda4 100644
--- a/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h
+++ b/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h
@@ -44,6 +44,7 @@
#include <QtCore/qwaitcondition.h>
#include <private/qsgadaptationlayer_p.h>
+#include <private/qqmlguard_p.h>
QT_BEGIN_HEADER
@@ -105,8 +106,19 @@ private:
QPoint position;
};
+ struct Owner
+ {
+ Owner() : ref(0) {}
+ Owner(const Owner &o) : item(o.item), ref(o.ref) {}
+ Owner &operator =(const Owner &o) { item = o.item; ref = o.ref; return *this; }
+
+ QQmlGuard<QQuickItem> item;
+ int ref;
+ };
+
QHash<quint32, PendingGlyph> m_pendingReadyGlyphs;
QHash<glyph_t, void *> m_bufferForGlyph;
+ QHash<QQuickItem *, Owner> m_registeredOwners;
};
QT_END_NAMESPACE