aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew den Exter <andrew.den-exter@nokia.com>2012-03-14 15:28:27 +1000
committerQt by Nokia <qt-info@nokia.com>2012-03-14 10:26:52 +0100
commit4cd2f0bb2ff262bafb09eae23db919714858e4a2 (patch)
treebcc4f9a913dd9f52eae0d0e948ba3cb37b6f11b0
parentd73e6d4374e21a4137b1b83fa76cf9600b214a8b (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>
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode.cpp1
-rw-r--r--src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp19
-rw-r--r--src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h12
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