aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>2020-06-12 09:53:17 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2020-06-15 07:00:52 +0000
commita54621c231317c5777dea402215c30764ae96a2e (patch)
treea8ca199ed5c88172d474aaef716eb63994742b1c /src
parentbeea6c18f0b6050e4d2633fba462f2b9b67ab134 (diff)
Get rid of preprocess in QQuickText
Preprocessing in the scene graph is actually pretty expensive, so we want to avoid using it for something like text, where you can often have a lot of nodes in a UI. For text it was previously used for two purposes: 1. To make sure the distance field glyph cache was updated with potential new glyphs before the frame was rendered, but *after* all new glyph nodes had been created (this is an optimization to avoid having to resize the cache multiple times in one frame, but rather wait until we know the exact amount of new glyphs that need to be added) 2. Update the coordinates of the glyph based on their position in the glyph cache if the glyph cache says they have moved (or if they have just been added for the first time). Point #1 can actually be handled a lot simpler, by having a separate loop for the existing glyph caches where we ask them to preprocess. There is typically only a few glyph caches, but can be hundreds of glyph nodes in a scene, so in the previous code we would be calling the update() functions on the same glyph cache over and over again every frame. Point #2 does not need preprocessing every frame, but can be reduced to only preprocess when the geometry is marked as dirty. We then do a pass on the glyph node in question to update its geometry and turn the flag off again so that we don't pay the cost every frame. Fixes: QTBUG-84351 Change-Id: If8c492acaef9c512c2db61b64bcab2103db2d997 Reviewed-by: Lars Knoll <lars.knoll@qt.io> (cherry picked from commit 1f3dd3f5db16892739963168c2a76df6354b178c) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'src')
-rw-r--r--src/quick/scenegraph/coreapi/qsgrenderer.cpp2
-rw-r--r--src/quick/scenegraph/qsgcontext.cpp7
-rw-r--r--src/quick/scenegraph/qsgcontext_p.h1
-rw-r--r--src/quick/scenegraph/qsgdefaultrendercontext.cpp8
-rw-r--r--src/quick/scenegraph/qsgdefaultrendercontext_p.h1
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode.cpp10
6 files changed, 23 insertions, 6 deletions
diff --git a/src/quick/scenegraph/coreapi/qsgrenderer.cpp b/src/quick/scenegraph/coreapi/qsgrenderer.cpp
index 90090e1cc0..381fd7eb69 100644
--- a/src/quick/scenegraph/coreapi/qsgrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgrenderer.cpp
@@ -323,6 +323,8 @@ void QSGRenderer::preprocess()
// For the default case, when this does not happen, the cost is negligible.
QSet<QSGNode *> items = m_nodes_to_preprocess;
+ m_context->preprocess();
+
for (QSet<QSGNode *>::const_iterator it = items.constBegin();
it != items.constEnd(); ++it) {
QSGNode *n = *it;
diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp
index e3c951e5ed..28d8c19d5d 100644
--- a/src/quick/scenegraph/qsgcontext.cpp
+++ b/src/quick/scenegraph/qsgcontext.cpp
@@ -395,6 +395,13 @@ void QSGRenderContext::endSync()
}
/*!
+ Do necessary preprocessing before the frame
+*/
+void QSGRenderContext::preprocess()
+{
+}
+
+/*!
Factory function for scene graph backends of the distance-field glyph cache.
*/
QSGDistanceFieldGlyphCache *QSGRenderContext::distanceFieldGlyphCache(const QRawFont &)
diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h
index d389420907..275a753fb3 100644
--- a/src/quick/scenegraph/qsgcontext_p.h
+++ b/src/quick/scenegraph/qsgcontext_p.h
@@ -192,6 +192,7 @@ public:
virtual void endSync();
+ virtual void preprocess();
virtual QSGDistanceFieldGlyphCache *distanceFieldGlyphCache(const QRawFont &font);
QSGTexture *textureForFactory(QQuickTextureFactory *factory, QQuickWindow *window);
diff --git a/src/quick/scenegraph/qsgdefaultrendercontext.cpp b/src/quick/scenegraph/qsgdefaultrendercontext.cpp
index 16f9b63036..bf7bb052bb 100644
--- a/src/quick/scenegraph/qsgdefaultrendercontext.cpp
+++ b/src/quick/scenegraph/qsgdefaultrendercontext.cpp
@@ -430,6 +430,14 @@ bool QSGDefaultRenderContext::separateIndexBuffer() const
return isWebGL;
}
+void QSGDefaultRenderContext::preprocess()
+{
+ for (auto it = m_glyphCaches.begin(); it != m_glyphCaches.end(); ++it) {
+ it.value()->processPendingGlyphs();
+ it.value()->update();
+ }
+}
+
QSGDistanceFieldGlyphCache *QSGDefaultRenderContext::distanceFieldGlyphCache(const QRawFont &font)
{
QString key = fontKey(font);
diff --git a/src/quick/scenegraph/qsgdefaultrendercontext_p.h b/src/quick/scenegraph/qsgdefaultrendercontext_p.h
index 97ed681f9a..e90a11eda6 100644
--- a/src/quick/scenegraph/qsgdefaultrendercontext_p.h
+++ b/src/quick/scenegraph/qsgdefaultrendercontext_p.h
@@ -120,6 +120,7 @@ public:
void renderNextRhiFrame(QSGRenderer *renderer) override;
void endNextRhiFrame(QSGRenderer *renderer) override;
+ void preprocess() override;
QSGDistanceFieldGlyphCache *distanceFieldGlyphCache(const QRawFont &font) override;
virtual QSharedPointer<QSGDepthStencilBuffer> depthStencilBufferForFbo(QOpenGLFramebufferObject *fbo);
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
index 0fa680a244..45996aff87 100644
--- a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
@@ -57,7 +57,6 @@ QSGDistanceFieldGlyphNode::QSGDistanceFieldGlyphNode(QSGRenderContext *context)
{
m_geometry.setDrawingMode(GL_TRIANGLES);
setGeometry(&m_geometry);
- setFlag(UsePreprocess);
#ifdef QSG_RUNTIME_DESCRIPTION
qsgnode_set_description(this, QLatin1String("glyphs"));
#endif
@@ -105,6 +104,7 @@ void QSGDistanceFieldGlyphNode::setGlyphs(const QPointF &position, const QGlyphR
m_dirtyGeometry = true;
m_dirtyMaterial = true;
+ setFlag(UsePreprocess);
QSGDistanceFieldGlyphCache *oldCache = m_glyph_cache;
m_glyph_cache = m_context->distanceFieldGlyphCache(m_glyphs.rawFont());
@@ -152,13 +152,10 @@ void QSGDistanceFieldGlyphNode::update()
void QSGDistanceFieldGlyphNode::preprocess()
{
- Q_ASSERT(m_glyph_cache);
-
- m_glyph_cache->processPendingGlyphs();
- m_glyph_cache->update();
-
if (m_dirtyGeometry)
updateGeometry();
+
+ setFlag(UsePreprocess, false);
}
void QSGDistanceFieldGlyphNode::invalidateGlyphs(const QVector<quint32> &glyphs)
@@ -169,6 +166,7 @@ void QSGDistanceFieldGlyphNode::invalidateGlyphs(const QVector<quint32> &glyphs)
for (int i = 0; i < glyphs.count(); ++i) {
if (m_allGlyphIndexesLookup.contains(glyphs.at(i))) {
m_dirtyGeometry = true;
+ setFlag(UsePreprocess);
return;
}
}