diff options
| -rw-r--r-- | src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp | 3 | ||||
| -rw-r--r-- | src/quick/scenegraph/qsgcontext.cpp | 8 | ||||
| -rw-r--r-- | src/quick/scenegraph/qsgcontext_p.h | 5 | ||||
| -rw-r--r-- | src/quick/scenegraph/qsgdefaultglyphnode_p.cpp | 8 | ||||
| -rw-r--r-- | src/quick/scenegraph/qsgdefaultglyphnode_p_p.h | 1 | ||||
| -rw-r--r-- | src/quick/scenegraph/qsgdefaultrendercontext.cpp | 39 |
6 files changed, 48 insertions, 16 deletions
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp index 0c0ee5e579..4fd0003e54 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarecontext.cpp @@ -113,8 +113,7 @@ void QSGSoftwareRenderContext::invalidate() qDeleteAll(m_textures); m_textures.clear(); - qDeleteAll(m_fontEnginesToClean); - m_fontEnginesToClean.clear(); + Q_ASSERT(m_fontEnginesToClean.isEmpty()); qDeleteAll(m_glyphCaches); m_glyphCaches.clear(); diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp index be7c934fd7..7668db7a69 100644 --- a/src/quick/scenegraph/qsgcontext.cpp +++ b/src/quick/scenegraph/qsgcontext.cpp @@ -475,7 +475,13 @@ void QSGRenderContext::invalidateGlyphCaches() void QSGRenderContext::registerFontengineForCleanup(QFontEngine *engine) { engine->ref.ref(); - m_fontEnginesToClean << engine; + m_fontEnginesToClean[engine]++; +} + +void QSGRenderContext::unregisterFontengineForCleanup(QFontEngine *engine) +{ + m_fontEnginesToClean[engine]--; + Q_ASSERT(m_fontEnginesToClean.value(engine) >= 0); } QRhi *QSGRenderContext::rhi() const diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h index 299b003716..19585c6f4b 100644 --- a/src/quick/scenegraph/qsgcontext_p.h +++ b/src/quick/scenegraph/qsgcontext_p.h @@ -166,6 +166,7 @@ public: virtual int maxTextureSize() const = 0; + void unregisterFontengineForCleanup(QFontEngine *engine); void registerFontengineForCleanup(QFontEngine *engine); virtual QRhi *rhi() const; @@ -187,7 +188,9 @@ protected: QSet<QSGTexture *> m_texturesToDelete; QHash<QString, QSGDistanceFieldGlyphCache *> m_glyphCaches; - QSet<QFontEngine *> m_fontEnginesToClean; + // References to font engines that are currently in use by native rendering glyph nodes + // and which must be kept alive as long as they are used in the render thread. + QHash<QFontEngine *, int> m_fontEnginesToClean; }; QT_END_NAMESPACE diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp index e9e6c26d88..f10dbd4bc6 100644 --- a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp +++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp @@ -322,6 +322,8 @@ QSGTextMaskMaterial::QSGTextMaskMaterial(QSGRenderContext *rc, const QVector4D & QSGTextMaskMaterial::~QSGTextMaskMaterial() { + if (m_retainedFontEngine != nullptr) + m_rc->unregisterFontengineForCleanup(m_retainedFontEngine); delete m_texture; } @@ -385,6 +387,12 @@ void QSGTextMaskMaterial::updateCache(QFontEngine::GlyphFormat glyphFormat) if (!m_glyphCache || int(m_glyphCache->glyphFormat()) != glyphFormat) { m_glyphCache = new QSGRhiTextureGlyphCache(m_rc, glyphFormat, glyphCacheTransform, color); fontEngine->setGlyphCache(cacheKey, m_glyphCache.data()); + if (m_retainedFontEngine != nullptr) + m_rc->unregisterFontengineForCleanup(m_retainedFontEngine); + + // Note: This is reference counted by the render context, so it will stay alive until + // we release that reference + m_retainedFontEngine = fontEngine; m_rc->registerFontengineForCleanup(fontEngine); } } diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p_p.h b/src/quick/scenegraph/qsgdefaultglyphnode_p_p.h index e77e2715cd..d3b919c275 100644 --- a/src/quick/scenegraph/qsgdefaultglyphnode_p_p.h +++ b/src/quick/scenegraph/qsgdefaultglyphnode_p_p.h @@ -69,6 +69,7 @@ private: QSGPlainTexture *m_texture; QExplicitlySharedDataPointer<QFontEngineGlyphCache> m_glyphCache; QRawFont m_font; + QFontEngine *m_retainedFontEngine = nullptr; QRhi *m_rhi; QVector4D m_color; QSize m_size; diff --git a/src/quick/scenegraph/qsgdefaultrendercontext.cpp b/src/quick/scenegraph/qsgdefaultrendercontext.cpp index 462196927b..73f4bec27f 100644 --- a/src/quick/scenegraph/qsgdefaultrendercontext.cpp +++ b/src/quick/scenegraph/qsgdefaultrendercontext.cpp @@ -59,13 +59,29 @@ void QSGDefaultRenderContext::initialize(const QSGRenderContext::InitParams *par void QSGDefaultRenderContext::invalidateGlyphCaches() { - auto it = m_glyphCaches.begin(); - while (it != m_glyphCaches.end()) { - if (!(*it)->isActive()) { - delete *it; - it = m_glyphCaches.erase(it); - } else { - ++it; + { + auto it = m_glyphCaches.begin(); + while (it != m_glyphCaches.end()) { + if (!(*it)->isActive()) { + delete *it; + it = m_glyphCaches.erase(it); + } else { + ++it; + } + } + } + + { + auto it = m_fontEnginesToClean.begin(); + while (it != m_fontEnginesToClean.end()) { + if (it.value() == 0) { + it.key()->clearGlyphCache(this); + if (!it.key()->ref.deref()) + delete it.key(); + it = m_fontEnginesToClean.erase(it); + } else { + ++it; + } } } } @@ -108,11 +124,10 @@ void QSGDefaultRenderContext::invalidate() // code is only called from QQuickWindow's shutdown which is called // only when the GUI is blocked, and multiple threads will call it in // sequence. (see qsgdefaultglyphnode_p.cpp's init()) - for (QSet<QFontEngine *>::const_iterator it = m_fontEnginesToClean.constBegin(), - end = m_fontEnginesToClean.constEnd(); it != end; ++it) { - (*it)->clearGlyphCache(this); - if (!(*it)->ref.deref()) - delete *it; + for (auto it = m_fontEnginesToClean.constBegin(); it != m_fontEnginesToClean.constEnd(); ++it) { + it.key()->clearGlyphCache(this); + if (!it.key()->ref.deref()) + delete it.key(); } m_fontEnginesToClean.clear(); |
