diff options
author | Andrew den Exter <andrew.den-exter@nokia.com> | 2012-03-14 15:28:27 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-03-14 10:26:52 +0100 |
commit | 4cd2f0bb2ff262bafb09eae23db919714858e4a2 (patch) | |
tree | bcc4f9a913dd9f52eae0d0e948ba3cb37b6f11b0 | |
parent | d73e6d4374e21a4137b1b83fa76cf9600b214a8b (diff) |
Fix memory leak with the shared distance field glyph cache.
A new glyph node instance registers its owner element with its
glyph cache which in the case of the shared distance field glyph cache
connects a signal from the cache to a slot on the owner, changing the
text creates a new node but destroying the old node didn't remove the
connection causing them to accumulate over time.
In the glyph node; unregister the owner element from the cache on
destruction, and in the cache only connect an owner element the
first time it is registered and keep a reference count so the
items can be disconnected when registrations from all nodes have
been cancelled.
Change-Id: Ibf32a146e146dbbf4e0556d1bd756465bd8e45ba
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>
3 files changed, 28 insertions, 4 deletions
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp index 79e5c3b0f4..e049e92bae 100644 --- a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp +++ b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp @@ -76,6 +76,7 @@ QSGDistanceFieldGlyphNode::~QSGDistanceFieldGlyphNode() glyphIndexes.append(m_allGlyphs.at(i).glyphIndex); m_glyph_cache->release(glyphIndexes); m_glyph_cache->unregisterGlyphNode(this); + m_glyph_cache->unregisterOwnerElement(ownerElement()); } for (int i = 0; i < m_nodesToDelete.count(); ++i) 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 |