From 0b3f46014764d6e35da321bbba2d0232ec99d1b1 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 24 May 2012 15:51:27 +0200 Subject: [PATCH] Uses new batching API to potentially speed up glyph cache Give the cache information that a burst of requests/releases are coming, so it can potentially optimize this. Change-Id: Icfb591a63075c2f1e93bf269402649116de9e5be Reviewed-by: Jiang Jiang --- src/quick/items/qquickcanvas.cpp | 8 ++ src/quick/items/qquickcanvas.h | 1 + .../qsgshareddistancefieldglyphcache.cpp | 93 +++++++++++++++++++--- .../qsgshareddistancefieldglyphcache_p.h | 6 ++ 4 files changed, 97 insertions(+), 11 deletions(-) diff --git a/src/quick/items/qquickcanvas.cpp b/src/quick/items/qquickcanvas.cpp index 2481951..08f9b44 100644 --- a/src/quick/items/qquickcanvas.cpp +++ b/src/quick/items/qquickcanvas.cpp @@ -282,6 +282,9 @@ void forceUpdate(QQuickItem *item) void QQuickCanvasPrivate::syncSceneGraph() { QML_MEMORY_SCOPE_STRING("SceneGraph"); + Q_Q(QQuickCanvas); + + emit q->beforeSynchronizing(); if (!renderer) { forceUpdate(rootItem); @@ -787,6 +790,11 @@ void QQuickCanvasPrivate::cleanup(QSGNode *n) \list + \li The QQuickCanvas::beforeSynchronizing() signal is emitted. + Applications can make direct connections (Qt::DirectConnection) + to this signal to do any preparation required before calls to + QQuickItem::updatePaintNode(). + \li Synchronzation of the QML state into the scene graph. This is done by calling the QQuickItem::updatePaintNode() function on all items that have changed since the previous frame. When a dedicated diff --git a/src/quick/items/qquickcanvas.h b/src/quick/items/qquickcanvas.h index c3a6e45..1d23996 100644 --- a/src/quick/items/qquickcanvas.h +++ b/src/quick/items/qquickcanvas.h @@ -125,6 +125,7 @@ Q_SIGNALS: void frameSwapped(); void sceneGraphInitialized(); void sceneGraphInvalidated(); + void beforeSynchronizing(); void beforeRendering(); void afterRendering(); void clearColorChanged(const QColor &); diff --git a/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp index 2dd8729..e6bd529 100644 --- a/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp +++ b/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp @@ -66,19 +66,25 @@ namespace { { public: QSGInvokeEvent(QPlatformSharedGraphicsCache *cache, - const QByteArray &cacheId, - const QVector &glyphIds) + const QByteArray &cacheId = QByteArray(), + const QVector &glyphIds = QVector(), + bool inSceneGraphUpdate = false) : QEvent(User) , m_cache(cache) , m_cacheId(cacheId) , m_glyphIds(glyphIds) + , m_inSceneGraphUpdate(inSceneGraphUpdate) {} + bool inSceneGraphUpdate() const { return m_inSceneGraphUpdate; } + QPlatformSharedGraphicsCache *cache() const { return m_cache; } + virtual void invoke() = 0; protected: QPlatformSharedGraphicsCache *m_cache; QByteArray m_cacheId; QVector m_glyphIds; + bool m_inSceneGraphUpdate; }; class QSGReleaseItemsEvent: public QSGInvokeEvent @@ -86,8 +92,9 @@ namespace { public: QSGReleaseItemsEvent(QPlatformSharedGraphicsCache *cache, const QByteArray &cacheId, - const QVector &glyphIds) - : QSGInvokeEvent(cache, cacheId, glyphIds) + const QVector &glyphIds, + bool inSceneGraphUpdate) + : QSGInvokeEvent(cache, cacheId, glyphIds, inSceneGraphUpdate) { } @@ -102,8 +109,9 @@ namespace { public: QSGRequestItemsEvent(QPlatformSharedGraphicsCache *cache, const QByteArray &cacheId, - const QVector &glyphIds) - : QSGInvokeEvent(cache, cacheId, glyphIds) + const QVector &glyphIds, + bool inSceneGraphUpdate) + : QSGInvokeEvent(cache, cacheId, glyphIds, inSceneGraphUpdate) { } @@ -119,8 +127,9 @@ namespace { QSGInsertItemsEvent(QPlatformSharedGraphicsCache *cache, const QByteArray &cacheId, const QVector &glyphIds, - const QVector &images) - : QSGInvokeEvent(cache, cacheId, glyphIds) + const QVector &images, + bool inSceneGraphUpdate) + : QSGInvokeEvent(cache, cacheId, glyphIds, inSceneGraphUpdate) , m_images(images) { } @@ -134,6 +143,21 @@ namespace { QVector m_images; }; + class QSGEndRequestBatchEvent: public QSGInvokeEvent + { + public: + QSGEndRequestBatchEvent(QPlatformSharedGraphicsCache *cache) + : QSGInvokeEvent(cache) + { + } + + void invoke() + { + if (m_cache->requestBatchStarted()) + m_cache->endRequestBatch(); + } + }; + class QSGMainThreadInvoker: public QObject { public: @@ -141,6 +165,14 @@ namespace { { if (e->type() == QEvent::User) { Q_ASSERT(QThread::currentThread() == QCoreApplication::instance()->thread()); + + QSGInvokeEvent *invokeEvent = static_cast(e); + if (invokeEvent->inSceneGraphUpdate()) { + QPlatformSharedGraphicsCache *cache = invokeEvent->cache(); + if (!cache->requestBatchStarted()) + cache->beginRequestBatch(); + } + static_cast(e)->invoke(); return true; } @@ -172,6 +204,8 @@ QSGSharedDistanceFieldGlyphCache::QSGSharedDistanceFieldGlyphCache(const QByteAr : QSGDistanceFieldGlyphCache(man, c, font) , m_cacheId(cacheId) , m_sharedGraphicsCache(sharedGraphicsCache) + , m_isInSceneGraphUpdate(false) + , m_hasPostedEvents(false) { #if defined(QSGSHAREDDISTANCEFIELDGLYPHCACHE_DEBUG) qDebug("QSGSharedDistanceFieldGlyphCache with id %s created in thread %p", @@ -193,6 +227,14 @@ QSGSharedDistanceFieldGlyphCache::QSGSharedDistanceFieldGlyphCache(const QByteAr connect(sharedGraphicsCache, SIGNAL(itemsInvalidated(QByteArray,QVector)), this, SLOT(reportItemsInvalidated(QByteArray,QVector)), Qt::DirectConnection); + + QQuickCanvas *canvas = static_cast(c->surface()); + Q_ASSERT(canvas != 0); + + connect(canvas, SIGNAL(beforeSynchronizing()), this, SLOT(sceneGraphUpdateStarted()), + Qt::DirectConnection); + connect(canvas, SIGNAL(beforeRendering()), this, SLOT(sceneGraphUpdateDone()), + Qt::DirectConnection); } QSGSharedDistanceFieldGlyphCache::~QSGSharedDistanceFieldGlyphCache() @@ -235,14 +277,22 @@ void QSGSharedDistanceFieldGlyphCache::requestGlyphs(const QSet &glyphs glyphsVector.append(*it); } + m_hasPostedEvents = true; QSGMainThreadInvoker *invoker = QSGMainThreadInvoker::instance(); QCoreApplication::postEvent(invoker, new QSGRequestItemsEvent(m_sharedGraphicsCache, m_cacheId, - glyphsVector)); + glyphsVector, + m_isInSceneGraphUpdate)); } void QSGSharedDistanceFieldGlyphCache::waitForGlyphs() { + Q_ASSERT(!m_isInSceneGraphUpdate); + if (m_isInSceneGraphUpdate) { + qWarning("QSGSharedDistanceFieldGlyphCache::waitForGlyphs: Called from inside " + "scenegraph update. Will freeze."); + } + { QMutexLocker locker(&m_pendingGlyphsMutex); while (!m_requestedGlyphsThatHaveNotBeenReturned.isEmpty()) @@ -272,11 +322,13 @@ void QSGSharedDistanceFieldGlyphCache::storeGlyphs(const QHash ++it; ++i; } + m_hasPostedEvents = true; QSGMainThreadInvoker *invoker = QSGMainThreadInvoker::instance(); QCoreApplication::postEvent(invoker, new QSGInsertItemsEvent(m_sharedGraphicsCache, m_cacheId, glyphIds, - images)); + images, + m_isInSceneGraphUpdate)); } processPendingGlyphs(); @@ -325,10 +377,12 @@ void QSGSharedDistanceFieldGlyphCache::releaseGlyphs(const QSet &glyphs glyphsVector.append(*glyphsIt); } + m_hasPostedEvents = true; QSGMainThreadInvoker *mainThreadInvoker = QSGMainThreadInvoker::instance(); QCoreApplication::postEvent(mainThreadInvoker, new QSGReleaseItemsEvent(m_sharedGraphicsCache, m_cacheId, - glyphsVector)); + glyphsVector, + m_isInSceneGraphUpdate)); } void QSGSharedDistanceFieldGlyphCache::registerOwnerElement(QQuickItem *ownerElement) @@ -761,4 +815,21 @@ void QSGSharedDistanceFieldGlyphCache::reportItemsMissing(const QByteArray &cach emit glyphsPending(); } +void QSGSharedDistanceFieldGlyphCache::sceneGraphUpdateStarted() +{ + m_isInSceneGraphUpdate = true; + m_hasPostedEvents = false; +} + +void QSGSharedDistanceFieldGlyphCache::sceneGraphUpdateDone() +{ + m_isInSceneGraphUpdate = false; + + if (m_hasPostedEvents) { + QSGMainThreadInvoker *invoker = QSGMainThreadInvoker::instance(); + QCoreApplication::postEvent(invoker, new QSGEndRequestBatchEvent(m_sharedGraphicsCache)); + m_hasPostedEvents = false; + } +} + QT_END_NAMESPACE diff --git a/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h b/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h index 2d43246..fd1f28f 100644 --- a/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h +++ b/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h @@ -86,6 +86,9 @@ private Q_SLOTS: const QVector &positions); void reportItemsInvalidated(const QByteArray &cacheId, const QVector &itemIds); + void sceneGraphUpdateStarted(); + void sceneGraphUpdateDone(); + private: void waitForGlyphs(); void saveTexture(GLuint textureId, int width, int height); @@ -122,6 +125,9 @@ private: QHash m_pendingReadyGlyphs; QHash m_bufferForGlyph; QHash m_registeredOwners; + + bool m_isInSceneGraphUpdate; + bool m_hasPostedEvents; }; QT_END_NAMESPACE -- 2.7.4