summaryrefslogtreecommitdiffstats
path: root/src/quick3d/imports/scene3d/scene3drenderer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick3d/imports/scene3d/scene3drenderer.cpp')
-rw-r--r--src/quick3d/imports/scene3d/scene3drenderer.cpp70
1 files changed, 48 insertions, 22 deletions
diff --git a/src/quick3d/imports/scene3d/scene3drenderer.cpp b/src/quick3d/imports/scene3d/scene3drenderer.cpp
index 3065b19ac..b32191391 100644
--- a/src/quick3d/imports/scene3d/scene3drenderer.cpp
+++ b/src/quick3d/imports/scene3d/scene3drenderer.cpp
@@ -38,27 +38,36 @@
****************************************************************************/
#include "scene3drenderer_p.h"
-#include "scene3dcleaner_p.h"
-#include "scene3ditem_p.h"
-#include "scene3dlogging_p.h"
-#include "scene3dsgnode_p.h"
-#include <Qt3DRender/qrenderaspect.h>
-#include <Qt3DRender/private/qrenderaspect_p.h>
#include <Qt3DCore/qaspectengine.h>
-#include <Qt3DCore/private/qaspectengine_p.h>
-
-#include <QtQuick/qquickwindow.h>
-
+#include <Qt3DRender/qrenderaspect.h>
+#include <QtCore/qthread.h>
#include <QtGui/qopenglcontext.h>
#include <QtGui/qopenglframebufferobject.h>
+#include <QtQuick/qquickwindow.h>
-#include <QtCore/qthread.h>
+#include <Qt3DRender/private/qrenderaspect_p.h>
+#include <Qt3DCore/private/qaspectengine_p.h>
+#include <scene3dcleaner_p.h>
+#include <scene3ditem_p.h>
+#include <scene3dlogging_p.h>
+#include <scene3dsgnode_p.h>
QT_BEGIN_NAMESPACE
namespace Qt3DRender {
+namespace {
+
+inline QMetaMethod setItemAreaMethod()
+{
+ const int idx = Scene3DItem::staticMetaObject.indexOfMethod("setItemArea(QSize)");
+ Q_ASSERT(idx != -1);
+ return Scene3DItem::staticMetaObject.method(idx);
+}
+
+} // anonymous
+
class ContextSaver
{
public:
@@ -120,14 +129,18 @@ Scene3DRenderer::Scene3DRenderer(Scene3DItem *item, Qt3DCore::QAspectEngine *asp
, m_multisampledFBO(nullptr)
, m_finalFBO(nullptr)
, m_texture(nullptr)
+ , m_node(nullptr)
+ , m_cleaner(nullptr)
, m_multisample(false) // this value is not used, will be synced from the Scene3DItem instead
, m_lastMultisample(false)
+ , m_needsShutdown(true)
{
Q_CHECK_PTR(m_item);
Q_CHECK_PTR(m_item->window());
QObject::connect(m_item->window(), &QQuickWindow::beforeRendering, this, &Scene3DRenderer::render, Qt::DirectConnection);
- QObject::connect(m_item, &QQuickItem::windowChanged, this, &Scene3DRenderer::onWindowChangedQueued, Qt::QueuedConnection);
+ QObject::connect(m_item->window(), &QQuickWindow::sceneGraphInvalidated, this, &Scene3DRenderer::onSceneGraphInvalidated, Qt::DirectConnection);
+ QObject::connect(m_item, &QQuickItem::windowChanged, this, &Scene3DRenderer::onWindowChanged, Qt::QueuedConnection);
Q_ASSERT(QOpenGLContext::currentContext());
ContextSaver saver;
@@ -173,7 +186,7 @@ void Scene3DRenderer::setCleanerHelper(Scene3DCleaner *cleaner)
}
}
-// Executed in the QtQuick render thread.
+// Executed in the QtQuick render thread (which may even be the gui/main with QQuickWidget / RenderControl).
void Scene3DRenderer::shutdown()
{
qCDebug(Scene3D) << Q_FUNC_INFO << QThread::currentThread();
@@ -195,19 +208,29 @@ void Scene3DRenderer::shutdown()
static_cast<QRenderAspectPrivate*>(QRenderAspectPrivate::get(m_renderAspect))->renderShutdown();
}
-// SGThread
-void Scene3DRenderer::onWindowChangedQueued(QQuickWindow *w)
+// QtQuick render thread (which may also be the gui/main thread with QQuickWidget / RenderControl)
+void Scene3DRenderer::onSceneGraphInvalidated()
{
- if (w == nullptr) {
- qCDebug(Scene3D) << Q_FUNC_INFO << QThread::currentThread();
+ qCDebug(Scene3D) << Q_FUNC_INFO << QThread::currentThread();
+ if (m_needsShutdown) {
+ m_needsShutdown = false;
shutdown();
- // Will only trigger something with the Loader case
- // The window closed cases is handled by the window's destroyed
- // signal
QMetaObject::invokeMethod(m_cleaner, "cleanup");
}
}
+void Scene3DRenderer::onWindowChanged(QQuickWindow *w)
+{
+ qCDebug(Scene3D) << Q_FUNC_INFO << QThread::currentThread() << w;
+ if (!w) {
+ if (m_needsShutdown) {
+ m_needsShutdown = false;
+ shutdown();
+ QMetaObject::invokeMethod(m_cleaner, "cleanup");
+ }
+ }
+}
+
void Scene3DRenderer::synchronize()
{
m_multisample = m_item->multisample();
@@ -238,8 +261,11 @@ void Scene3DRenderer::render()
const bool multisampleHasChanged = m_multisample != m_lastMultisample;
const bool forceRecreate = sizeHasChanged || multisampleHasChanged;
- if (sizeHasChanged)
- m_item->setItemArea(boundingRectSize);
+ if (sizeHasChanged) {
+ // We are in the QSGRenderThread (doing a direct call would result in a race)
+ static const QMetaMethod setItemArea = setItemAreaMethod();
+ setItemArea.invoke(m_item, Qt::QueuedConnection, Q_ARG(QSize, boundingRectSize));
+ }
// Rebuild FBO and textures if never created or a resize has occurred
if ((m_multisampledFBO.isNull() || forceRecreate) && m_multisample) {