summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2018-01-22 10:00:02 +0000
committerThe Qt Project <gerrit-noreply@qt-project.org>2018-01-22 10:00:02 +0000
commit2b19bde378e084331b1b7ba9aa076270492999bb (patch)
treed0f00fdbf48852e5b872dcd315ba3ee6e83b2556 /src
parente335ab9fbcb45840857a2abd107853947fedc178 (diff)
parent520b9823954628f66b256bcf6e0c96f30ed4f625 (diff)
Merge "Merge remote-tracking branch 'origin/5.9' into 5.10" into refs/staging/5.10
Diffstat (limited to 'src')
-rw-r--r--src/core/nodes/qnode.cpp23
-rw-r--r--src/plugins/sceneparsers/assimp/assimpimporter.cpp1
-rw-r--r--src/quick3d/imports/scene3d/scene3drenderer.cpp6
-rw-r--r--src/quick3d/imports/scene3d/scene3drenderer_p.h1
-rw-r--r--src/render/backend/abstractrenderer_p.h2
-rw-r--r--src/render/backend/renderer.cpp17
-rw-r--r--src/render/backend/renderer_p.h2
-rw-r--r--src/render/frontend/qrenderaspect.cpp4
-rw-r--r--src/render/frontend/qrenderaspect_p.h2
-rw-r--r--src/render/graphicshelpers/graphicscontext.cpp3
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