diff options
author | Liang Qi <liang.qi@qt.io> | 2018-01-22 09:24:26 +0100 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2018-01-22 09:24:57 +0100 |
commit | 520b9823954628f66b256bcf6e0c96f30ed4f625 (patch) | |
tree | aa8cb07880d8c96b1020bfd8dd43c9dc7bcd8df5 /src | |
parent | f91ee783c5704b0d55da0d96dacf6eca8933e748 (diff) | |
parent | 9409dd81287af75108023abbd66e49e07ba65de6 (diff) |
Merge remote-tracking branch 'origin/5.9' into 5.10
Conflicts:
src/render/backend/renderer.cpp
Change-Id: I691f54cd6daef8a966df37d447164c94badce34c
Diffstat (limited to 'src')
-rw-r--r-- | src/core/nodes/qnode.cpp | 23 | ||||
-rw-r--r-- | src/plugins/sceneparsers/assimp/assimpimporter.cpp | 1 | ||||
-rw-r--r-- | src/quick3d/imports/scene3d/scene3drenderer.cpp | 6 | ||||
-rw-r--r-- | src/quick3d/imports/scene3d/scene3drenderer_p.h | 1 | ||||
-rw-r--r-- | src/render/backend/abstractrenderer_p.h | 2 | ||||
-rw-r--r-- | src/render/backend/renderer.cpp | 17 | ||||
-rw-r--r-- | src/render/backend/renderer_p.h | 2 | ||||
-rw-r--r-- | src/render/frontend/qrenderaspect.cpp | 4 | ||||
-rw-r--r-- | src/render/frontend/qrenderaspect_p.h | 2 | ||||
-rw-r--r-- | src/render/graphicshelpers/graphicscontext.cpp | 3 |
10 files changed, 51 insertions, 10 deletions
diff --git a/src/core/nodes/qnode.cpp b/src/core/nodes/qnode.cpp index 58e016cda..dbe3fd102 100644 --- a/src/core/nodes/qnode.cpp +++ b/src/core/nodes/qnode.cpp @@ -173,11 +173,21 @@ void QNodePrivate::_q_postConstructorInit() { Q_Q(QNode); + // If we've already done the work then bail out. This can happen if the + // user creates a QNode subclass with an explicit parent, then immediately + // sets the new QNode as a property on another node. In this case, the + // property setter will call this function directly, but as we can't + // un-schedule a deferred invocation, this function will be called again + // the next time the event loop spins. So, catch this case and abort. + if (m_hasBackendNode) + return; + // Check that the parent hasn't been unset since this call was enqueued auto parentNode = q->parentNode(); if (!parentNode) return; + if (m_scene) m_scene->addObservable(q); // Sets the m_changeArbiter to that of the scene @@ -369,7 +379,18 @@ void QNodePrivate::propertyChanged(int propertyIndex) const QVariant data = property.read(q); if (data.canConvert<QNode*>()) { - const QNode * const node = data.value<QNode*>(); + QNode *node = data.value<QNode*>(); + + // Ensure the node has issued a node creation change. We can end + // up here if a newly created node with a parent is immediately set + // as a property on another node. In this case the deferred call to + // _q_postConstructorInit() will not have happened yet as the event + // loop will still be blocked. So force it here and we catch this + // eventuality in the _q_postConstructorInit() function so that we + // do not repeat the creation and new child scene change events. + if (node) + QNodePrivate::get(node)->_q_postConstructorInit(); + const QNodeId id = node ? node->id() : QNodeId(); notifyPropertyChange(property.name(), QVariant::fromValue(id)); } else { diff --git a/src/plugins/sceneparsers/assimp/assimpimporter.cpp b/src/plugins/sceneparsers/assimp/assimpimporter.cpp index 5af2104c5..a2264964c 100644 --- a/src/plugins/sceneparsers/assimp/assimpimporter.cpp +++ b/src/plugins/sceneparsers/assimp/assimpimporter.cpp @@ -1290,6 +1290,7 @@ void AssimpImporter::copyMaterialTextures(QMaterial *material, aiMaterial *assim QAbstractTexture *tex = QAbstractNodeFactory::createNode<QTexture2D>("QTexture2D"); QTextureImage *texImage = QAbstractNodeFactory::createNode<QTextureImage>("QTextureImage"); texImage->setSource(QUrl::fromLocalFile(fullPath)); + texImage->setMirrored(false); tex->addTextureImage(texImage); // Set proper wrapping mode diff --git a/src/quick3d/imports/scene3d/scene3drenderer.cpp b/src/quick3d/imports/scene3d/scene3drenderer.cpp index 37ae8e48b..1c9fec4d2 100644 --- a/src/quick3d/imports/scene3d/scene3drenderer.cpp +++ b/src/quick3d/imports/scene3d/scene3drenderer.cpp @@ -135,6 +135,7 @@ Scene3DRenderer::Scene3DRenderer(Scene3DItem *item, Qt3DCore::QAspectEngine *asp , m_multisample(false) // this value is not used, will be synced from the Scene3DItem instead , m_lastMultisample(false) , m_needsShutdown(true) + , m_blocking(false) { Q_CHECK_PTR(m_item); Q_CHECK_PTR(m_item->window()); @@ -154,6 +155,9 @@ Scene3DRenderer::Scene3DRenderer(Scene3DItem *item, Qt3DCore::QAspectEngine *asp ContextSaver saver; static_cast<QRenderAspectPrivate*>(QRenderAspectPrivate::get(m_renderAspect))->renderInitialize(saver.context()); scheduleRootEntityChange(); + + const bool blockingRendermode = !qgetenv("SCENE3D_BLOCKING_RENDERMODE").isEmpty(); + m_blocking = blockingRendermode; } Scene3DRenderer::~Scene3DRenderer() @@ -307,7 +311,7 @@ void Scene3DRenderer::render() m_finalFBO->bind(); // Render Qt3D Scene - static_cast<QRenderAspectPrivate*>(QRenderAspectPrivate::get(m_renderAspect))->renderSynchronous(); + static_cast<QRenderAspectPrivate*>(QRenderAspectPrivate::get(m_renderAspect))->renderSynchronous(m_blocking); // We may have called doneCurrent() so restore the context if the rendering surface was changed // Note: keep in mind that the ContextSave also restores the surface when destroyed diff --git a/src/quick3d/imports/scene3d/scene3drenderer_p.h b/src/quick3d/imports/scene3d/scene3drenderer_p.h index 7a85bc774..eb2b930ef 100644 --- a/src/quick3d/imports/scene3d/scene3drenderer_p.h +++ b/src/quick3d/imports/scene3d/scene3drenderer_p.h @@ -109,6 +109,7 @@ private: bool m_multisample; bool m_lastMultisample; bool m_needsShutdown; + bool m_blocking; friend class Scene3DCleaner; }; diff --git a/src/render/backend/abstractrenderer_p.h b/src/render/backend/abstractrenderer_p.h index 4d80ec87d..c934dbfae 100644 --- a/src/render/backend/abstractrenderer_p.h +++ b/src/render/backend/abstractrenderer_p.h @@ -133,7 +133,7 @@ public: // Threaded renderer virtual void render() = 0; // Synchronous renderer - virtual void doRender() = 0; + virtual void doRender(bool scene3dBlocking = false) = 0; virtual void cleanGraphicsResources() = 0; diff --git a/src/render/backend/renderer.cpp b/src/render/backend/renderer.cpp index 53f4fa20a..20aeaf2df 100644 --- a/src/render/backend/renderer.cpp +++ b/src/render/backend/renderer.cpp @@ -556,7 +556,7 @@ void Renderer::render() } } -void Renderer::doRender() +void Renderer::doRender(bool scene3dBlocking) { Renderer::ViewSubmissionResultData submissionData; bool hasCleanedQueueAndProceeded = false; @@ -566,9 +566,22 @@ void Renderer::doRender() // Lock the mutex to protect access to the renderQueue while we look for its state QMutexLocker locker(m_renderQueue->mutex()); - const bool queueIsComplete = m_renderQueue->isFrameQueueComplete(); + bool queueIsComplete = m_renderQueue->isFrameQueueComplete(); const bool queueIsEmpty = m_renderQueue->targetRenderViewCount() == 0; + // Scene3D Blocking Mode + if (scene3dBlocking && !queueIsComplete && !queueIsEmpty) { + int i = 0; + // We wait at most 10ms to avoid a case we could never recover from + while (!queueIsComplete && i++ < 10) { + QThread::msleep(1); + qCDebug(Backend) << Q_FUNC_INFO << "Waiting for ready queue (try:" << i << "/ 10)"; + locker.unlock(); + queueIsComplete = m_renderQueue->isFrameQueueComplete(); + locker.relock(); + } + } + // When using synchronous rendering (QtQuick) // We are not sure that the frame queue is actually complete // Since a call to render may not be synched with the completions diff --git a/src/render/backend/renderer_p.h b/src/render/backend/renderer_p.h index 28e8711a8..d4917e28c 100644 --- a/src/render/backend/renderer_p.h +++ b/src/render/backend/renderer_p.h @@ -170,7 +170,7 @@ public: void releaseGraphicsResources() Q_DECL_OVERRIDE; void render() Q_DECL_OVERRIDE; - void doRender() Q_DECL_OVERRIDE; + void doRender(bool scene3dBlocking = false) Q_DECL_OVERRIDE; void cleanGraphicsResources() Q_DECL_OVERRIDE; bool isRunning() const Q_DECL_OVERRIDE { return m_running.load(); } diff --git a/src/render/frontend/qrenderaspect.cpp b/src/render/frontend/qrenderaspect.cpp index ba9fd4451..53adf96a9 100644 --- a/src/render/frontend/qrenderaspect.cpp +++ b/src/render/frontend/qrenderaspect.cpp @@ -405,9 +405,9 @@ void QRenderAspectPrivate::renderInitialize(QOpenGLContext *context) } /*! \internal */ -void QRenderAspectPrivate::renderSynchronous() +void QRenderAspectPrivate::renderSynchronous(bool blocking) { - m_renderer->doRender(); + m_renderer->doRender(blocking); } /*! diff --git a/src/render/frontend/qrenderaspect_p.h b/src/render/frontend/qrenderaspect_p.h index b8c8538ee..26ca091f6 100644 --- a/src/render/frontend/qrenderaspect_p.h +++ b/src/render/frontend/qrenderaspect_p.h @@ -90,7 +90,7 @@ public: void loadSceneParsers(); void loadRenderPlugin(const QString &pluginName); void renderInitialize(QOpenGLContext *context); - void renderSynchronous(); + void renderSynchronous(bool blocking = false); void renderShutdown(); void registerBackendType(const QMetaObject &, const Qt3DCore::QBackendNodeMapperPtr &functor); QVector<Qt3DCore::QAspectJobPtr> createGeometryRendererJobs(); diff --git a/src/render/graphicshelpers/graphicscontext.cpp b/src/render/graphicshelpers/graphicscontext.cpp index d33aca825..9e8e3d610 100644 --- a/src/render/graphicshelpers/graphicscontext.cpp +++ b/src/render/graphicshelpers/graphicscontext.cpp @@ -515,7 +515,8 @@ void GraphicsContext::loadShader(Shader *shader, ShaderManager *manager) shaderProgram = createShaderProgram(shader); // Store in cache - m_shaderCache.insert(shader->dna(), shader->peerId(), shaderProgram); + if (shaderProgram) + m_shaderCache.insert(shader->dna(), shader->peerId(), shaderProgram); } // Ensure the Shader node knows about the program interface |