aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer.cpp37
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer_p.h4
-rw-r--r--src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp7
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode.cpp148
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp10
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode_p.h12
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode_p_p.h2
7 files changed, 105 insertions, 115 deletions
diff --git a/src/quick/scenegraph/qsgadaptationlayer.cpp b/src/quick/scenegraph/qsgadaptationlayer.cpp
index 972bff80e0..57c0990f1d 100644
--- a/src/quick/scenegraph/qsgadaptationlayer.cpp
+++ b/src/quick/scenegraph/qsgadaptationlayer.cpp
@@ -228,8 +228,10 @@ void QSGDistanceFieldGlyphCache::update()
storeGlyphs(distanceFields);
}
-void QSGDistanceFieldGlyphCache::addGlyphPositions(const QList<GlyphPosition> &glyphs)
+void QSGDistanceFieldGlyphCache::setGlyphsPosition(const QList<GlyphPosition> &glyphs)
{
+ QVector<quint32> invalidatedGlyphs;
+
int count = glyphs.count();
for (int i = 0; i < count; ++i) {
GlyphPosition glyph = glyphs.at(i);
@@ -244,11 +246,22 @@ void QSGDistanceFieldGlyphCache::addGlyphPositions(const QList<GlyphPosition> &g
c.width = br.width();
c.height = br.height();
+ if (m_cacheData->texCoords.contains(glyph.glyph))
+ invalidatedGlyphs.append(glyph.glyph);
+
m_cacheData->texCoords.insert(glyph.glyph, c);
}
+
+ if (!invalidatedGlyphs.isEmpty()) {
+ QLinkedList<QSGDistanceFieldGlyphNode *>::iterator it = m_cacheData->m_registeredNodes.begin();
+ while (it != m_cacheData->m_registeredNodes.end()) {
+ (*it)->invalidateGlyphs(invalidatedGlyphs);
+ ++it;
+ }
+ }
}
-void QSGDistanceFieldGlyphCache::addGlyphTextures(const QVector<glyph_t> &glyphs, const Texture &tex)
+void QSGDistanceFieldGlyphCache::setGlyphsTexture(const QVector<glyph_t> &glyphs, const Texture &tex)
{
int i = m_cacheData->textures.indexOf(tex);
if (i == -1) {
@@ -259,14 +272,22 @@ void QSGDistanceFieldGlyphCache::addGlyphTextures(const QVector<glyph_t> &glyphs
}
Texture *texture = &(m_cacheData->textures[i]);
+ QVector<quint32> invalidatedGlyphs;
+
int count = glyphs.count();
- for (int j = 0; j < count; ++j)
- m_cacheData->glyphTextures.insert(glyphs.at(j), texture);
+ for (int j = 0; j < count; ++j) {
+ glyph_t glyphIndex = glyphs.at(j);
+ if (m_cacheData->glyphTextures.contains(glyphIndex))
+ invalidatedGlyphs.append(glyphIndex);
+ m_cacheData->glyphTextures.insert(glyphIndex, texture);
+ }
- QLinkedList<QSGDistanceFieldGlyphNode *>::iterator it = m_cacheData->m_registeredNodes.begin();
- while (it != m_cacheData->m_registeredNodes.end()) {
- (*it)->updateGeometry();
- ++it;
+ if (!invalidatedGlyphs.isEmpty()) {
+ QLinkedList<QSGDistanceFieldGlyphNode *>::iterator it = m_cacheData->m_registeredNodes.begin();
+ while (it != m_cacheData->m_registeredNodes.end()) {
+ (*it)->invalidateGlyphs(invalidatedGlyphs);
+ ++it;
+ }
}
}
diff --git a/src/quick/scenegraph/qsgadaptationlayer_p.h b/src/quick/scenegraph/qsgadaptationlayer_p.h
index 5912802a84..0c777ef639 100644
--- a/src/quick/scenegraph/qsgadaptationlayer_p.h
+++ b/src/quick/scenegraph/qsgadaptationlayer_p.h
@@ -195,8 +195,8 @@ protected:
virtual void storeGlyphs(const QHash<glyph_t, QImage> &glyphs) = 0;
virtual void releaseGlyphs(const QVector<glyph_t> &glyphs) = 0;
- void addGlyphPositions(const QList<GlyphPosition> &glyphs);
- void addGlyphTextures(const QVector<glyph_t> &glyphs, const Texture &tex);
+ void setGlyphsPosition(const QList<GlyphPosition> &glyphs);
+ void setGlyphsTexture(const QVector<glyph_t> &glyphs, const Texture &tex);
void markGlyphsToRender(const QVector<glyph_t> &glyphs);
void removeGlyph(glyph_t glyph);
diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
index 95ccc8f437..4f69ad8c44 100644
--- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
+++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
@@ -117,7 +117,7 @@ void QSGDefaultDistanceFieldGlyphCache::requestGlyphs(const QVector<glyph_t> &gl
}
}
- addGlyphPositions(glyphPositions);
+ setGlyphsPosition(glyphPositions);
markGlyphsToRender(glyphsToRender);
}
@@ -159,7 +159,7 @@ void QSGDefaultDistanceFieldGlyphCache::storeGlyphs(const QHash<glyph_t, QImage>
Texture t;
t.textureId = m_textureData->texture;
t.size = m_textureData->size;
- addGlyphTextures(glyphTextures, t);
+ setGlyphsTexture(glyphTextures, t);
}
void QSGDefaultDistanceFieldGlyphCache::releaseGlyphs(const QVector<glyph_t> &glyphs)
@@ -300,6 +300,9 @@ void QSGDefaultDistanceFieldGlyphCache::resizeTexture(int width, int height)
glEnable(GL_BLEND);
glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
ctx->functions()->glUseProgram(oldProgram);
+
+ m_textureData->blitProgram->disableAttributeArray(int(QT_VERTEX_COORDS_ATTR));
+ m_textureData->blitProgram->disableAttributeArray(int(QT_TEXTURE_COORDS_ATTR));
}
bool QSGDefaultDistanceFieldGlyphCache::useWorkaroundBrokenFBOReadback() const
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
index d3b90bed60..def4d9486b 100644
--- a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
@@ -56,6 +56,7 @@ QSGDistanceFieldGlyphNode::QSGDistanceFieldGlyphNode(QSGDistanceFieldGlyphCacheM
, m_dirtyGeometry(false)
, m_dirtyMaterial(false)
{
+ setFlag(UsePreprocess);
m_geometry.setDrawingMode(GL_TRIANGLES);
setGeometry(&m_geometry);
setPreferredAntialiasingMode(cacheManager->defaultAntialiasingMode());
@@ -106,13 +107,10 @@ 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.size(); ++i) {
- GlyphInfo g;
- g.glyphIndex = glyphIndexes.at(i);
- g.position = glyphPositions.at(i);
- m_glyphsToAdd.append(g);
- }
+ m_allGlyphIndexes += glyphIndexes;
+ m_allGlyphPositions += m_glyphs.positions();
+ for (int i = 0; i < glyphIndexes.count(); ++i)
+ m_allGlyphIndexesLookup.insert(glyphIndexes.at(i));
m_dirtyGeometry = true;
m_dirtyMaterial = true;
@@ -138,68 +136,70 @@ void QSGDistanceFieldGlyphNode::update()
{
if (m_dirtyMaterial)
updateMaterial();
+}
+
+void QSGDistanceFieldGlyphNode::preprocess()
+{
+ Q_ASSERT(m_glyph_cache);
+
+ m_glyph_cache->update();
+
if (m_dirtyGeometry)
updateGeometry();
}
+void QSGDistanceFieldGlyphNode::invalidateGlyphs(const QVector<quint32> &glyphs)
+{
+ if (m_dirtyGeometry)
+ return;
+
+ for (int i = 0; i < glyphs.count(); ++i) {
+ if (m_allGlyphIndexesLookup.contains(glyphs.at(i))) {
+ m_dirtyGeometry = true;
+ return;
+ }
+ }
+}
+
void QSGDistanceFieldGlyphNode::updateGeometry()
{
Q_ASSERT(m_glyph_cache);
- if (m_glyphsToAdd.isEmpty())
- return;
-
QSGGeometry *g = geometry();
Q_ASSERT(g->indexType() == GL_UNSIGNED_SHORT);
- int oldVertexCount = g->vertexCount();
- int oldIndexCount = g->indexCount();
+ g->allocate(m_allGlyphIndexes.size() * 4, m_allGlyphIndexes.size() * 6);
- QVector<QSGGeometry::TexturedPoint2D> vp;
- vp.reserve(m_glyphsToAdd.size() * 4);
- QVector<ushort> ip;
- ip.reserve(m_glyphsToAdd.size() * 6);
+ QSGGeometry::TexturedPoint2D *vp = g->vertexDataAsTexturedPoint2D();
+ ushort *ip = g->indexDataAsUShort();
QPointF margins(2, 2);
QPointF texMargins = margins / m_glyph_cache->fontScale();
const QSGDistanceFieldGlyphCache::Texture *textureToUse = 0;
- QLinkedList<GlyphInfo>::iterator it = m_glyphsToAdd.begin();
- while (it != m_glyphsToAdd.end()) {
- quint32 glyphIndex = it->glyphIndex;
+ for (int i = 0; i < m_allGlyphIndexes.size(); ++i) {
+ quint32 glyphIndex = m_allGlyphIndexes.at(i);
+ QSGDistanceFieldGlyphCache::Metrics metrics = m_glyph_cache->glyphMetrics(glyphIndex);
QSGDistanceFieldGlyphCache::TexCoord c = m_glyph_cache->glyphTexCoord(glyphIndex);
- if (c.isNull()) {
- if (!c.isValid())
- ++it;
- else
- it = m_glyphsToAdd.erase(it);
- continue;
- }
-
const QSGDistanceFieldGlyphCache::Texture *texture = m_glyph_cache->glyphTexture(glyphIndex);
- if (!texture->textureId) {
- ++it;
- continue;
- }
-
- QSGDistanceFieldGlyphCache::Metrics metrics = m_glyph_cache->glyphMetrics(glyphIndex);
-
- if (!textureToUse)
+ if (texture->textureId && !textureToUse)
textureToUse = texture;
- metrics.width += margins.x() * 2;
- metrics.height += margins.y() * 2;
- metrics.baselineX -= margins.x();
- metrics.baselineY += margins.y();
- c.xMargin -= texMargins.x();
- c.yMargin -= texMargins.y();
- c.width += texMargins.x() * 2;
- c.height += texMargins.y() * 2;
+ if (!metrics.isNull() && !c.isNull()) {
+ metrics.width += margins.x() * 2;
+ metrics.height += margins.y() * 2;
+ metrics.baselineX -= margins.x();
+ metrics.baselineY += margins.y();
+ c.xMargin -= texMargins.x();
+ c.yMargin -= texMargins.y();
+ c.width += texMargins.x() * 2;
+ c.height += texMargins.y() * 2;
+ }
- const QPointF &glyphPosition = it->position;
+ const QPointF &glyphPosition = m_allGlyphPositions.at(i);
qreal x = glyphPosition.x() + metrics.baselineX + m_position.x();
qreal y = glyphPosition.y() - metrics.baselineY + m_position.y();
@@ -218,55 +218,21 @@ void QSGDistanceFieldGlyphNode::updateGeometry()
if (m_baseLine.isNull())
m_baseLine = glyphPosition;
- int i = vp.size();
-
- QSGGeometry::TexturedPoint2D v1;
- v1.set(cx1, cy1, tx1, ty1);
- QSGGeometry::TexturedPoint2D v2;
- v2.set(cx2, cy1, tx2, ty1);
- QSGGeometry::TexturedPoint2D v3;
- v3.set(cx1, cy2, tx1, ty2);
- QSGGeometry::TexturedPoint2D v4;
- v4.set(cx2, cy2, tx2, ty2);
- vp.append(v1);
- vp.append(v2);
- vp.append(v3);
- vp.append(v4);
-
- int o = i + oldVertexCount;
- ip.append(o + 0);
- ip.append(o + 2);
- ip.append(o + 3);
- ip.append(o + 3);
- ip.append(o + 1);
- ip.append(o + 0);
-
- it = m_glyphsToAdd.erase(it);
+ int vi = i & 1 ? (m_allGlyphIndexes.size() + 1) / 2 + i / 2 : i / 2;
+ vp[4 * vi + 0].set(cx1, cy1, tx1, ty1);
+ vp[4 * vi + 1].set(cx2, cy1, tx2, ty1);
+ vp[4 * vi + 2].set(cx1, cy2, tx1, ty2);
+ vp[4 * vi + 3].set(cx2, cy2, tx2, ty2);
+
+ int o = i * 4;
+ ip[6 * i + 0] = o + 0;
+ ip[6 * i + 1] = o + 2;
+ ip[6 * i + 2] = o + 3;
+ ip[6 * i + 3] = o + 3;
+ ip[6 * i + 4] = o + 1;
+ ip[6 * i + 5] = o + 0;
}
- if (vp.isEmpty())
- return;
-
- void *data = 0;
- if (oldVertexCount && oldIndexCount) {
- int byteSize = oldVertexCount * sizeof(QSGGeometry::TexturedPoint2D)
- + oldIndexCount * sizeof(quint16);
- data = qMalloc(byteSize);
- memcpy(data, g->vertexData(), byteSize);
- }
-
- g->allocate(oldVertexCount + vp.size(), oldIndexCount + ip.size());
-
- if (data) {
- memcpy(g->vertexData(), data, oldVertexCount * sizeof(QSGGeometry::TexturedPoint2D));
- memcpy(g->indexData(), ((char *) data) + oldVertexCount * sizeof(QSGGeometry::TexturedPoint2D),
- oldIndexCount * sizeof(quint16));
- qFree(data);
- }
-
- memcpy(g->vertexDataAsTexturedPoint2D() + oldVertexCount, vp.constData(), vp.size() * sizeof(QSGGeometry::TexturedPoint2D));
- memcpy(g->indexDataAsUShort() + oldIndexCount, ip.constData(), ip.size() * sizeof(quint16));
-
setBoundingRect(m_boundingRect);
markDirty(DirtyGeometry);
m_dirtyGeometry = false;
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp
index 164af0b2e7..938fe9b42d 100644
--- a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp
@@ -138,7 +138,7 @@ void QSGDistanceFieldTextMaterialShader::updateState(const RenderState &state, Q
QSGDistanceFieldTextMaterial *material = static_cast<QSGDistanceFieldTextMaterial *>(newEffect);
QSGDistanceFieldTextMaterial *oldMaterial = static_cast<QSGDistanceFieldTextMaterial *>(oldEffect);
- bool updated = material->updateCache();
+ bool updated = material->updateTextureSize();
if (oldMaterial == 0
|| material->color() != oldMaterial->color()
@@ -207,15 +207,13 @@ QSGMaterialShader *QSGDistanceFieldTextMaterial::createShader() const
return new QSGDistanceFieldTextMaterialShader;
}
-bool QSGDistanceFieldTextMaterial::updateCache()
+bool QSGDistanceFieldTextMaterial::updateTextureSize()
{
- m_glyph_cache->update();
if (!m_texture)
m_texture = m_glyph_cache->glyphTexture(-1); // invalid texture
- QSize glyphCacheSize = m_texture->size;
- if (glyphCacheSize != m_size) {
- m_size = glyphCacheSize;
+ if (m_texture->size != m_size) {
+ m_size = m_texture->size;
return true;
} else {
return false;
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h
index 8096d4ae70..0669fd4a80 100644
--- a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h
@@ -70,6 +70,10 @@ public:
virtual void update();
+ void preprocess();
+
+ void invalidateGlyphs(const QVector<quint32> &glyphs);
+
void updateGeometry();
private:
@@ -88,11 +92,9 @@ private:
AntialiasingMode m_antialiasingMode;
QRectF m_boundingRect;
- struct GlyphInfo {
- quint32 glyphIndex;
- QPointF position;
- };
- QLinkedList<GlyphInfo> m_glyphsToAdd;
+ QVector<quint32> m_allGlyphIndexes;
+ QSet<quint32> m_allGlyphIndexesLookup;
+ QVector<QPointF> m_allGlyphPositions;
uint m_dirtyGeometry: 1;
uint m_dirtyMaterial: 1;
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode_p_p.h b/src/quick/scenegraph/qsgdistancefieldglyphnode_p_p.h
index dbdc6e2498..d71cc48196 100644
--- a/src/quick/scenegraph/qsgdistancefieldglyphnode_p_p.h
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode_p_p.h
@@ -69,7 +69,7 @@ public:
QSize textureSize() const { return m_size; }
- bool updateCache();
+ bool updateTextureSize();
protected:
QSize m_size;