From 2c750b45709fa164b758c5ec9e0e9ee744c51555 Mon Sep 17 00:00:00 2001 From: Alan Alpert <416365416c@gmail.com> Date: Fri, 13 Sep 2013 16:34:07 -0700 Subject: [PATCH] Load image data on main thread QQuickPixmap use should be done on the main thread, if not it can lead to an exception when creating the file loading thread (owned by the engine). Change-Id: Id59cec4312ecdee537dcba85778bd90ea4433b2e Reviewed-by: Gunnar Sletta --- src/particles/qquickimageparticle.cpp | 62 +++++++++++++++------------ src/particles/qquickimageparticle_p.h | 3 +- 2 files changed, 37 insertions(+), 28 deletions(-) diff --git a/src/particles/qquickimageparticle.cpp b/src/particles/qquickimageparticle.cpp index 036dfb901e..01cd487664 100644 --- a/src/particles/qquickimageparticle.cpp +++ b/src/particles/qquickimageparticle.cpp @@ -846,7 +846,7 @@ QQuickImageParticle::QQuickImageParticle(QQuickItem* parent) , m_lastLevel(Unknown) , m_debugMode(false) , m_entryEffect(Fade) - , m_buildingNodes(false) + , m_startedImageLoading(0) { setFlag(ItemHasContents); } @@ -1293,39 +1293,47 @@ bool QQuickImageParticle::loadingSomething() || (m_spriteEngine && m_spriteEngine->isLoading()); } -void QQuickImageParticle::buildParticleNodes()//Starts async parts, like loading images. +void QQuickImageParticle::mainThreadFetchImageData() { + if (m_image) {//ImageData created on setSource + m_image->pix.clear(this); + m_image->pix.load(qmlEngine(this), m_image->source); + } + + if (m_spriteEngine) + m_spriteEngine->startAssemblingImage(); + + if (m_colorTable) + m_colorTable->pix.load(qmlEngine(this), m_colorTable->source); + + if (m_sizeTable) + m_sizeTable->pix.load(qmlEngine(this), m_sizeTable->source); + + if (m_opacityTable) + m_opacityTable->pix.load(qmlEngine(this), m_opacityTable->source); + + m_startedImageLoading = 2; +} + +void QQuickImageParticle::buildParticleNodes() +{ + // Starts async parts, like loading images, on gui thread + // Not on individual properties, because we delay until system is running if (m_rootNode || loadingSomething()) return; - if (!m_buildingNodes) { - if (m_image) {//ImageData created on setSource - m_image->pix.clear(this); - m_image->pix.load(qmlEngine(this), m_image->source); - } - - if (m_spriteEngine) - m_spriteEngine->startAssemblingImage(); - - if (m_colorTable) - m_colorTable->pix.load(qmlEngine(this), m_colorTable->source); - - if (m_sizeTable) - m_sizeTable->pix.load(qmlEngine(this), m_sizeTable->source); - - if (m_opacityTable) - m_opacityTable->pix.load(qmlEngine(this), m_opacityTable->source); - - m_buildingNodes = true; - if (loadingSomething()) - return; + if (m_startedImageLoading == 0) { + m_startedImageLoading = 1; + QQuickImageParticle::staticMetaObject.invokeMethod(this, "mainThreadFetchImageData", Qt::QueuedConnection); + } else if (m_startedImageLoading == 2) { //stage 1 is in gui thread + finishBuildParticleNodes(); //rest happens in render thread } - finishBuildParticleNodes(); + + //No mutex, because it's slow and a compare that fails due to a race condition means just a dropped frame } void QQuickImageParticle::finishBuildParticleNodes() { - m_buildingNodes = false; #ifdef QT_OPENGL_ES_2 if (m_count * 4 > 0xffff) { printf("ImageParticle: Too many particles - maximum 16,000 per ImageParticle.\n");//ES 2 vertex count limit is ushort @@ -1574,7 +1582,7 @@ QSGNode *QQuickImageParticle::updatePaintNode(QSGNode *, UpdatePaintNodeData *) m_material = 0; m_pleaseReset = false; - m_buildingNodes = false;//Cancel a part-way build + m_startedImageLoading = 0;//Cancel a part-way build (may still have a pending load) } if (m_system && m_system->isRunning() && !m_system->isPaused()){ @@ -1583,7 +1591,7 @@ QSGNode *QQuickImageParticle::updatePaintNode(QSGNode *, UpdatePaintNodeData *) update(); foreach (QSGGeometryNode* node, m_nodes) node->markDirty(QSGNode::DirtyGeometry); - } else if (m_buildingNodes) { + } else if (m_startedImageLoading < 2) { update();//To call prepareNextFrame() again from the renderThread } } diff --git a/src/particles/qquickimageparticle_p.h b/src/particles/qquickimageparticle_p.h index 8f2bb715f8..3a5d72e727 100644 --- a/src/particles/qquickimageparticle_p.h +++ b/src/particles/qquickimageparticle_p.h @@ -353,6 +353,7 @@ private Q_SLOTS: void spriteAdvance(int spriteIndex); void spritesUpdate(qreal time = 0 ); + void mainThreadFetchImageData(); void finishBuildParticleNodes(); private: struct ImageData { @@ -436,7 +437,7 @@ private: } EntryEffect m_entryEffect; Status m_status; - bool m_buildingNodes; + int m_startedImageLoading; }; QT_END_NAMESPACE