aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp
diff options
context:
space:
mode:
authorEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>2012-05-15 14:37:37 +0200
committerQt by Nokia <qt-info@nokia.com>2012-05-15 16:07:15 +0200
commitf18b5bd1588e43f2e46325646b36247e4ba473f0 (patch)
tree29c8bd4ae4febe61dbfb2584d9acd0477f52bd75 /src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp
parent80040425830483d9e228de8841e92bf020855d0a (diff)
Optimize cross-thread calls into the shared graphics cache
QMetaObject::invokeMethod() is quite slow compared to just posting events, since we don't really require deep copies of the input data as long as it's read-only. Change-Id: Ib5c0a14e1aac3120871a9bcf4aee8804e7d8b287 Reviewed-by: Gunnar Sletta <gunnar.sletta@nokia.com>
Diffstat (limited to 'src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp')
-rw-r--r--src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp137
1 files changed, 119 insertions, 18 deletions
diff --git a/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp
index cece95d85a..2dd872996a 100644
--- a/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp
+++ b/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp
@@ -50,17 +50,120 @@
#include <QtCore/qhash.h>
#include <QtCore/qthread.h>
+#include <QtCore/qcoreapplication.h>
+
#include <qpa/qplatformsharedgraphicscache.h>
#include <QtQuick/qquickcanvas.h>
// #define QSGSHAREDDISTANCEFIELDGLYPHCACHE_DEBUG
-Q_DECLARE_METATYPE(QVector<quint32>)
-Q_DECLARE_METATYPE(QVector<QImage>)
-
QT_BEGIN_NAMESPACE
+namespace {
+
+ class QSGInvokeEvent: public QEvent
+ {
+ public:
+ QSGInvokeEvent(QPlatformSharedGraphicsCache *cache,
+ const QByteArray &cacheId,
+ const QVector<quint32> &glyphIds)
+ : QEvent(User)
+ , m_cache(cache)
+ , m_cacheId(cacheId)
+ , m_glyphIds(glyphIds)
+ {}
+
+ virtual void invoke() = 0;
+ protected:
+ QPlatformSharedGraphicsCache *m_cache;
+ QByteArray m_cacheId;
+ QVector<quint32> m_glyphIds;
+ };
+
+ class QSGReleaseItemsEvent: public QSGInvokeEvent
+ {
+ public:
+ QSGReleaseItemsEvent(QPlatformSharedGraphicsCache *cache,
+ const QByteArray &cacheId,
+ const QVector<quint32> &glyphIds)
+ : QSGInvokeEvent(cache, cacheId, glyphIds)
+ {
+ }
+
+ void invoke()
+ {
+ m_cache->releaseItems(m_cacheId, m_glyphIds);
+ }
+ };
+
+ class QSGRequestItemsEvent: public QSGInvokeEvent
+ {
+ public:
+ QSGRequestItemsEvent(QPlatformSharedGraphicsCache *cache,
+ const QByteArray &cacheId,
+ const QVector<quint32> &glyphIds)
+ : QSGInvokeEvent(cache, cacheId, glyphIds)
+ {
+ }
+
+ void invoke()
+ {
+ m_cache->requestItems(m_cacheId, m_glyphIds);
+ }
+ };
+
+ class QSGInsertItemsEvent: public QSGInvokeEvent
+ {
+ public:
+ QSGInsertItemsEvent(QPlatformSharedGraphicsCache *cache,
+ const QByteArray &cacheId,
+ const QVector<quint32> &glyphIds,
+ const QVector<QImage> &images)
+ : QSGInvokeEvent(cache, cacheId, glyphIds)
+ , m_images(images)
+ {
+ }
+
+ void invoke()
+ {
+ m_cache->insertItems(m_cacheId, m_glyphIds, m_images);
+ }
+
+ private:
+ QVector<QImage> m_images;
+ };
+
+ class QSGMainThreadInvoker: public QObject
+ {
+ public:
+ bool event(QEvent *e)
+ {
+ if (e->type() == QEvent::User) {
+ Q_ASSERT(QThread::currentThread() == QCoreApplication::instance()->thread());
+ static_cast<QSGInvokeEvent *>(e)->invoke();
+ return true;
+ }
+ return QObject::event(e);
+ }
+
+ static QSGMainThreadInvoker *instance()
+ {
+ if (m_invoker == 0) {
+ m_invoker = new QSGMainThreadInvoker;
+ m_invoker->moveToThread(QCoreApplication::instance()->thread());
+ }
+
+ return m_invoker;
+ }
+
+ private:
+ static QSGMainThreadInvoker *m_invoker;
+ };
+
+ QSGMainThreadInvoker* QSGMainThreadInvoker::m_invoker = 0;
+}
+
QSGSharedDistanceFieldGlyphCache::QSGSharedDistanceFieldGlyphCache(const QByteArray &cacheId,
QPlatformSharedGraphicsCache *sharedGraphicsCache,
QSGDistanceFieldGlyphCacheManager *man,
@@ -78,9 +181,6 @@ QSGSharedDistanceFieldGlyphCache::QSGSharedDistanceFieldGlyphCache(const QByteAr
Q_ASSERT(sizeof(glyph_t) == sizeof(quint32));
Q_ASSERT(sharedGraphicsCache != 0);
- qRegisterMetaType<QVector<quint32> >();
- qRegisterMetaType<QVector<QImage> >();
-
connect(sharedGraphicsCache, SIGNAL(itemsMissing(QByteArray,QVector<quint32>)),
this, SLOT(reportItemsMissing(QByteArray,QVector<quint32>)),
Qt::DirectConnection);
@@ -135,11 +235,10 @@ void QSGSharedDistanceFieldGlyphCache::requestGlyphs(const QSet<glyph_t> &glyphs
glyphsVector.append(*it);
}
- // Invoke method on queued connection to make sure it's called asynchronously on the
- // correct thread (requestGlyphs() is called from the rendering thread.)
- QMetaObject::invokeMethod(m_sharedGraphicsCache, "requestItems", Qt::QueuedConnection,
- Q_ARG(QByteArray, m_cacheId),
- Q_ARG(QVector<quint32>, glyphsVector));
+ QSGMainThreadInvoker *invoker = QSGMainThreadInvoker::instance();
+ QCoreApplication::postEvent(invoker, new QSGRequestItemsEvent(m_sharedGraphicsCache,
+ m_cacheId,
+ glyphsVector));
}
void QSGSharedDistanceFieldGlyphCache::waitForGlyphs()
@@ -173,10 +272,11 @@ void QSGSharedDistanceFieldGlyphCache::storeGlyphs(const QHash<glyph_t, QImage>
++it; ++i;
}
- QMetaObject::invokeMethod(m_sharedGraphicsCache, "insertItems", Qt::QueuedConnection,
- Q_ARG(QByteArray, m_cacheId),
- Q_ARG(QVector<quint32>, glyphIds),
- Q_ARG(QVector<QImage>, images));
+ QSGMainThreadInvoker *invoker = QSGMainThreadInvoker::instance();
+ QCoreApplication::postEvent(invoker, new QSGInsertItemsEvent(m_sharedGraphicsCache,
+ m_cacheId,
+ glyphIds,
+ images));
}
processPendingGlyphs();
@@ -225,9 +325,10 @@ void QSGSharedDistanceFieldGlyphCache::releaseGlyphs(const QSet<glyph_t> &glyphs
glyphsVector.append(*glyphsIt);
}
- QMetaObject::invokeMethod(m_sharedGraphicsCache, "releaseItems", Qt::QueuedConnection,
- Q_ARG(QByteArray, m_cacheId),
- Q_ARG(QVector<quint32>, glyphsVector));
+ QSGMainThreadInvoker *mainThreadInvoker = QSGMainThreadInvoker::instance();
+ QCoreApplication::postEvent(mainThreadInvoker, new QSGReleaseItemsEvent(m_sharedGraphicsCache,
+ m_cacheId,
+ glyphsVector));
}
void QSGSharedDistanceFieldGlyphCache::registerOwnerElement(QQuickItem *ownerElement)