diff options
author | Antti Määttä <antti.maatta@qt.io> | 2020-04-21 15:40:17 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2020-04-21 15:41:26 +0200 |
commit | 18b319f919f71c6b476675d832d1b8a2bda118c2 (patch) | |
tree | 0ed74eff9f5892dc372a136d05454c8213ad1d4c /src | |
parent | e326d8b7d7c96a628667d0a464f3c1e776d7cf1b (diff) | |
parent | dec1f5912acb991985e96ca2cb7e5c265c737a6f (diff) |
Merge remote-tracking branch 'origin/5.14' into 5.15
Conflicts:
src/plugins/renderers/opengl/graphicshelpers/submissioncontext.cpp
src/plugins/renderers/opengl/graphicshelpers/submissioncontext_p.h
src/plugins/renderers/opengl/renderer/renderer.cpp
src/render/backend/attachmentpack_p.h
src/render/frontend/qrenderaspect.cpp
src/render/picking/qabstractraycaster.cpp
tests/manual/manual.pro
Change-Id: I617b7e34bf7e11b2921bfc15e1b99c3e81891ec7
Diffstat (limited to 'src')
24 files changed, 204 insertions, 252 deletions
diff --git a/src/animation/frontend/qchannelmapper.cpp b/src/animation/frontend/qchannelmapper.cpp index c5909adbc..aa88add1a 100644 --- a/src/animation/frontend/qchannelmapper.cpp +++ b/src/animation/frontend/qchannelmapper.cpp @@ -94,7 +94,8 @@ void QChannelMapper::removeMapping(QAbstractChannelMapping *mapping) { Q_ASSERT(mapping); Q_D(QChannelMapper); - d->m_mappings.removeOne(mapping); + if (!d->m_mappings.removeOne(mapping)) + return; d->updateNode(mapping, "mappings", Qt3DCore::PropertyValueRemoved); // Remove bookkeeping connection d->unregisterDestructionHelper(mapping); diff --git a/src/extras/defaults/qmetalroughmaterial.cpp b/src/extras/defaults/qmetalroughmaterial.cpp index a969593db..7d5ee61ea 100644 --- a/src/extras/defaults/qmetalroughmaterial.cpp +++ b/src/extras/defaults/qmetalroughmaterial.cpp @@ -143,6 +143,11 @@ void QMetalRoughMaterialPrivate::init() m_metalRoughES3Technique->addRenderPass(m_metalRoughES3RenderPass); m_metalRoughEffect->addTechnique(m_metalRoughES3Technique); + // Given parameters a parent + m_baseColorMapParameter->setParent(m_metalRoughEffect); + m_metalnessMapParameter->setParent(m_metalRoughEffect); + m_roughnessMapParameter->setParent(m_metalRoughEffect); + m_metalRoughEffect->addParameter(m_baseColorParameter); m_metalRoughEffect->addParameter(m_metalnessParameter); m_metalRoughEffect->addParameter(m_roughnessParameter); @@ -338,11 +343,13 @@ void QMetalRoughMaterial::setBaseColor(const QVariant &baseColor) layers.removeAll(QStringLiteral("baseColor")); layers.append(QStringLiteral("baseColorMap")); d->m_metalRoughEffect->addParameter(d->m_baseColorMapParameter); - d->m_metalRoughEffect->removeParameter(d->m_baseColorParameter); + if (d->m_metalRoughEffect->parameters().contains(d->m_baseColorParameter)) + d->m_metalRoughEffect->removeParameter(d->m_baseColorParameter); } else { layers.removeAll(QStringLiteral("baseColorMap")); layers.append(QStringLiteral("baseColor")); - d->m_metalRoughEffect->removeParameter(d->m_baseColorMapParameter); + if (d->m_metalRoughEffect->parameters().contains(d->m_baseColorMapParameter)) + d->m_metalRoughEffect->removeParameter(d->m_baseColorMapParameter); d->m_metalRoughEffect->addParameter(d->m_baseColorParameter); } d->m_metalRoughGL3ShaderBuilder->setEnabledLayers(layers); @@ -360,11 +367,13 @@ void QMetalRoughMaterial::setMetalness(const QVariant &metalness) layers.removeAll(QStringLiteral("metalness")); layers.append(QStringLiteral("metalnessMap")); d->m_metalRoughEffect->addParameter(d->m_metalnessMapParameter); - d->m_metalRoughEffect->removeParameter(d->m_metalnessParameter); + if (d->m_metalRoughEffect->parameters().contains(d->m_metalnessParameter)) + d->m_metalRoughEffect->removeParameter(d->m_metalnessParameter); } else { layers.removeAll(QStringLiteral("metalnessMap")); layers.append(QStringLiteral("metalness")); - d->m_metalRoughEffect->removeParameter(d->m_metalnessMapParameter); + if (d->m_metalRoughEffect->parameters().contains(d->m_metalnessMapParameter)) + d->m_metalRoughEffect->removeParameter(d->m_metalnessMapParameter); d->m_metalRoughEffect->addParameter(d->m_metalnessParameter); } d->m_metalRoughGL3ShaderBuilder->setEnabledLayers(layers); @@ -382,11 +391,13 @@ void QMetalRoughMaterial::setRoughness(const QVariant &roughness) layers.removeAll(QStringLiteral("roughness")); layers.append(QStringLiteral("roughnessMap")); d->m_metalRoughEffect->addParameter(d->m_roughnessMapParameter); - d->m_metalRoughEffect->removeParameter(d->m_roughnessParameter); + if (d->m_metalRoughEffect->parameters().contains(d->m_roughnessParameter)) + d->m_metalRoughEffect->removeParameter(d->m_roughnessParameter); } else { layers.removeAll(QStringLiteral("roughnessMap")); layers.append(QStringLiteral("roughness")); - d->m_metalRoughEffect->removeParameter(d->m_roughnessMapParameter); + if (d->m_metalRoughEffect->parameters().contains(d->m_roughnessMapParameter)) + d->m_metalRoughEffect->removeParameter(d->m_roughnessMapParameter); d->m_metalRoughEffect->addParameter(d->m_roughnessParameter); } d->m_metalRoughGL3ShaderBuilder->setEnabledLayers(layers); @@ -406,7 +417,8 @@ void QMetalRoughMaterial::setAmbientOcclusion(const QVariant &ambientOcclusion) } else { layers.removeAll(QStringLiteral("ambientOcclusionMap")); layers.append(QStringLiteral("ambientOcclusion")); - d->m_metalRoughEffect->removeParameter(d->m_ambientOcclusionMapParameter); + if (d->m_metalRoughEffect->parameters().contains(d->m_ambientOcclusionMapParameter)) + d->m_metalRoughEffect->removeParameter(d->m_ambientOcclusionMapParameter); } d->m_metalRoughGL3ShaderBuilder->setEnabledLayers(layers); d->m_metalRoughES3ShaderBuilder->setEnabledLayers(layers); @@ -425,7 +437,8 @@ void QMetalRoughMaterial::setNormal(const QVariant &normal) } else { layers.removeAll(QStringLiteral("normalMap")); layers.append(QStringLiteral("normal")); - d->m_metalRoughEffect->removeParameter(d->m_normalMapParameter); + if (d->m_metalRoughEffect->parameters().contains(d->m_normalMapParameter)) + d->m_metalRoughEffect->removeParameter(d->m_normalMapParameter); } d->m_metalRoughGL3ShaderBuilder->setEnabledLayers(layers); d->m_metalRoughES3ShaderBuilder->setEnabledLayers(layers); diff --git a/src/extras/shaders/es2/phong.inc.frag100 b/src/extras/shaders/es2/phong.inc.frag100 index 0c326d0b6..c68c8e41a 100644 --- a/src/extras/shaders/es2/phong.inc.frag100 +++ b/src/extras/shaders/es2/phong.inc.frag100 @@ -66,8 +66,8 @@ void adsModel(const in FP vec3 vpos, const in FP vec3 vnormal, const in FP vec3 if ( lights[0].type != TYPE_DIRECTIONAL ) { s = lights[0].position - vpos; if (lights[0].constantAttenuation != 0.0 - || light[0].linearAttenuation != 0.0 - || light[0].quadraticAttenuation != 0.0) { + || lights[0].linearAttenuation != 0.0 + || lights[0].quadraticAttenuation != 0.0) { FP float dist = length(s); att = 1.0 / (lights[0].constantAttenuation + lights[0].linearAttenuation * dist + lights[0].quadraticAttenuation * dist * dist); } @@ -99,8 +99,8 @@ void adsModel(const in FP vec3 vpos, const in FP vec3 vnormal, const in FP vec3 if ( lights[1].type != TYPE_DIRECTIONAL ) { s = lights[1].position - vpos; if (lights[1].constantAttenuation != 0.0 - || light[1].linearAttenuation != 0.0 - || light[1].quadraticAttenuation != 0.0) { + || lights[1].linearAttenuation != 0.0 + || lights[1].quadraticAttenuation != 0.0) { FP float dist = length(s); att = 1.0 / (lights[1].constantAttenuation + lights[1].linearAttenuation * dist + lights[1].quadraticAttenuation * dist * dist); } diff --git a/src/plugins/renderers/rhi/renderer/renderview.cpp b/src/plugins/renderers/rhi/renderer/renderview.cpp index 4ac7a2b01..f3cc1b811 100644 --- a/src/plugins/renderers/rhi/renderer/renderview.cpp +++ b/src/plugins/renderers/rhi/renderer/renderview.cpp @@ -370,6 +370,7 @@ struct SubRangeSorter<QSortPolicy::Texture> { static void sortSubRange(CommandIt begin, const CommandIt end) { +#ifndef Q_OS_WIN std::stable_sort(begin, end, [] (const RenderCommand &a, const RenderCommand &b) { QVector<ShaderParameterPack::NamedResource> texturesA = a.m_parameterPack.textures(); QVector<ShaderParameterPack::NamedResource> texturesB = b.m_parameterPack.textures(); @@ -388,6 +389,7 @@ struct SubRangeSorter<QSortPolicy::Texture> return identicalTextureCount < originalTextureASize; }); +#endif } }; @@ -590,6 +592,9 @@ EntityRenderCommandData RenderView::buildDrawRenderCommands(const QVector<Entity HGeometry geometryHandle = m_manager->geometryManager()->lookupHandle(geometryRenderer->geometryId()); Geometry *geometry = m_manager->geometryManager()->data(geometryHandle); + if (geometry == nullptr) + continue; + // 1 RenderCommand per RenderPass pass on an Entity with a Mesh for (const RenderPassParameterData &passData : renderPassData) { // Add the RenderPass Parameters diff --git a/src/quick3d/imports/scene3d/importsscene3d.pro b/src/quick3d/imports/scene3d/importsscene3d.pro index 6bf4f5d91..969b7449b 100644 --- a/src/quick3d/imports/scene3d/importsscene3d.pro +++ b/src/quick3d/imports/scene3d/importsscene3d.pro @@ -14,7 +14,6 @@ HEADERS += \ qtquickscene3dplugin.h \ scene3dlogging_p.h \ scene3ditem_p.h \ - scene3dcleaner_p.h \ scene3drenderer_p.h \ scene3dsgnode_p.h \ scene3dsgmaterialshader_p.h \ @@ -25,7 +24,6 @@ SOURCES += \ qtquickscene3dplugin.cpp \ scene3ditem.cpp \ scene3dlogging.cpp \ - scene3dcleaner.cpp \ scene3drenderer.cpp \ scene3dsgnode.cpp \ scene3dsgmaterialshader.cpp \ diff --git a/src/quick3d/imports/scene3d/scene3dcleaner.cpp b/src/quick3d/imports/scene3d/scene3dcleaner.cpp deleted file mode 100644 index ec371410d..000000000 --- a/src/quick3d/imports/scene3d/scene3dcleaner.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "scene3dcleaner_p.h" - -#include <Qt3DCore/qaspectengine.h> -#include <QtCore/qthread.h> - -#include <scene3dlogging_p.h> -#include <scene3drenderer_p.h> - -QT_BEGIN_NAMESPACE - -namespace Qt3DRender { - -Scene3DCleaner::Scene3DCleaner(QObject *parent) - : QObject(parent) - , m_renderer(nullptr) -{ -} - -Scene3DCleaner::~Scene3DCleaner() -{ - qCDebug(Scene3D) << Q_FUNC_INFO << QThread::currentThread(); -} - -void Scene3DCleaner::cleanup() -{ - Q_ASSERT(m_renderer); - delete m_renderer->m_aspectEngine; // also deletes m_renderer->m_renderAspect - m_renderer->m_aspectEngine = nullptr; - m_renderer->m_renderAspect = nullptr; - m_renderer->deleteLater(); - deleteLater(); -} - -} // namespace Qt3DRender - -QT_END_NAMESPACE diff --git a/src/quick3d/imports/scene3d/scene3dcleaner_p.h b/src/quick3d/imports/scene3d/scene3dcleaner_p.h deleted file mode 100644 index a246cbde7..000000000 --- a/src/quick3d/imports/scene3d/scene3dcleaner_p.h +++ /dev/null @@ -1,82 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QT3DRENDER_SCENE3DCLEANER_P_H -#define QT3DRENDER_SCENE3DCLEANER_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/QObject> - -QT_BEGIN_NAMESPACE - -namespace Qt3DRender { - -class Scene3DRenderer; - -class Scene3DCleaner : public QObject -{ - Q_OBJECT -public: - explicit Scene3DCleaner(QObject *parent = 0); - ~Scene3DCleaner(); - - void setRenderer(Scene3DRenderer *renderer) { m_renderer = renderer; } - -public Q_SLOTS: - void cleanup(); - -private: - Scene3DRenderer *m_renderer; -}; - -} // namespace Qt3DRender - -QT_END_NAMESPACE - -#endif // QT3DRENDER_SCENE3DCLEANER_H diff --git a/src/quick3d/imports/scene3d/scene3ditem.cpp b/src/quick3d/imports/scene3d/scene3ditem.cpp index 37310a071..36569f0f7 100644 --- a/src/quick3d/imports/scene3d/scene3ditem.cpp +++ b/src/quick3d/imports/scene3d/scene3ditem.cpp @@ -68,7 +68,6 @@ #include <Qt3DRender/private/qrendersurfaceselector_p.h> #include <Qt3DRender/private/qrenderaspect_p.h> #include <Qt3DRender/private/rendersettings_p.h> -#include <scene3dcleaner_p.h> #include <scene3dlogging_p.h> #include <scene3drenderer_p.h> #include <scene3dsgnode_p.h> @@ -150,8 +149,8 @@ Scene3DItem::Scene3DItem(QQuickItem *parent) , m_viewHolderFG(nullptr) , m_aspectEngine(new Qt3DCore::QAspectEngine()) , m_renderAspect(nullptr) + , m_aspectToDelete(nullptr) , m_renderer(nullptr) - , m_rendererCleaner(new Scene3DCleaner()) , m_multisample(true) , m_dirty(true) , m_dirtyViews(false) @@ -180,6 +179,8 @@ Scene3DItem::~Scene3DItem() // When the window is closed, it first destroys all of its children. At // this point, Scene3DItem is destroyed but the Renderer, AspectEngine and // Scene3DSGNode still exist and will perform their cleanup on their own. + m_aspectEngine->deleteLater(); + m_renderer->deleteLater(); } /*! @@ -205,18 +206,11 @@ QStringList Scene3DItem::aspects() const */ Qt3DCore::QEntity *Scene3DItem::entity() const { - return m_entity; + return m_entity.data(); } -void Scene3DItem::setAspects(const QStringList &aspects) +void Scene3DItem::applyAspects() { - if (!m_aspects.isEmpty()) { - qCWarning(Scene3D) << "Aspects already set on the Scene3D, ignoring"; - return; - } - - m_aspects = aspects; - // Aspects are owned by the aspect engine for (const QString &aspect : qAsConst(m_aspects)) { if (aspect == QLatin1String("render")) // This one is hardwired anyway @@ -247,16 +241,27 @@ void Scene3DItem::setAspects(const QStringList &aspects) } m_aspectEngine->registerAspect(aspect); } +} + +void Scene3DItem::setAspects(const QStringList &aspects) +{ + if (!m_aspects.isEmpty()) { + qWarning() << "Aspects already set on the Scene3D, ignoring"; + return; + } + + m_aspects = aspects; + applyAspects(); emit aspectsChanged(); } void Scene3DItem::setEntity(Qt3DCore::QEntity *entity) { - if (entity == m_entity) + if (entity == m_entity.data()) return; - m_entity = entity; + m_entity.reset(entity); emit entityChanged(); } @@ -397,14 +402,21 @@ void Scene3DItem::removeView(Scene3DView *view) void Scene3DItem::applyRootEntityChange() { - if (m_aspectEngine->rootEntity() != m_entity) { - m_aspectEngine->setRootEntity(Qt3DCore::QEntityPtr(m_entity)); + if (m_aspectEngine->rootEntity() != m_entity.data()) { + m_aspectEngine->setRootEntity(m_entity); + + /* If we changed window, the old aspect engine must be deleted only after we have set + the root entity for the new one so that it doesn't delete the root node. */ + if (m_aspectToDelete) { + delete m_aspectToDelete; + m_aspectToDelete = nullptr; + } // Set the render surface if (!m_entity) return; - setWindowSurface(m_entity); + setWindowSurface(entity()); if (m_cameraAspectRatioMode == AutomaticAspectRatio) { // Set aspect ratio of first camera to match the window @@ -480,6 +492,8 @@ void Scene3DItem::onBeforeSync() // if the Scene3D item is not visible if (!isVisible() && dontRenderWhenHidden) return; + if (m_renderer->m_resetRequested) + return; Q_ASSERT(QThread::currentThread() == thread()); @@ -495,7 +509,7 @@ void Scene3DItem::onBeforeSync() // Make renderer aware of any Scene3DView we are dealing with if (m_dirtyViews) { // Scene3DViews checks - if (m_entity != m_viewHolderEntity) { + if (entity() != m_viewHolderEntity) { qCWarning(Scene3D) << "Scene3DView is not supported if the Scene3D entity property has been set"; } if (!usesFBO) { @@ -543,6 +557,20 @@ void Scene3DItem::requestUpdate() } } +void Scene3DItem::updateWindowSurface() +{ + if (!m_entity || !m_dummySurface) + return; + Qt3DRender::QRenderSurfaceSelector *surfaceSelector = + Qt3DRender::QRenderSurfaceSelectorPrivate::find(entity()); + if (surfaceSelector) { + if (QWindow *rw = QQuickRenderControl::renderWindowFor(this->window())) { + m_dummySurface->deleteLater(); + createDummySurface(rw, surfaceSelector); + } + } +} + void Scene3DItem::setWindowSurface(QObject *rootObject) { Qt3DRender::QRenderSurfaceSelector *surfaceSelector = Qt3DRender::QRenderSurfaceSelectorPrivate::find(rootObject); @@ -553,20 +581,25 @@ void Scene3DItem::setWindowSurface(QObject *rootObject) // We may not have a real, exposed QQuickWindow when the Quick rendering // is redirected via QQuickRenderControl (f.ex. QQuickWidget). if (QWindow *rw = QQuickRenderControl::renderWindowFor(this->window())) { - // rw is the top-level window that is backed by a native window. Do - // not use that though since we must not clash with e.g. the widget - // backingstore compositor in the gui thread. - m_dummySurface = new QOffscreenSurface; - m_dummySurface->setParent(qGuiApp); // parent to something suitably long-living - m_dummySurface->setFormat(rw->format()); - m_dummySurface->setScreen(rw->screen()); - m_dummySurface->create(); - surfaceSelector->setSurface(m_dummySurface); + createDummySurface(rw, surfaceSelector); } else { surfaceSelector->setSurface(this->window()); } } } + +void Scene3DItem::createDummySurface(QWindow *rw, Qt3DRender::QRenderSurfaceSelector *surfaceSelector) +{ + // rw is the top-level window that is backed by a native window. Do + // not use that though since we must not clash with e.g. the widget + // backingstore compositor in the gui thread. + m_dummySurface = new QOffscreenSurface; + m_dummySurface->setParent(qGuiApp); // parent to something suitably long-living + m_dummySurface->setFormat(rw->format()); + m_dummySurface->setScreen(rw->screen()); + m_dummySurface->create(); + surfaceSelector->setSurface(m_dummySurface); +} /*! \qmlmethod void Scene3D::setItemAreaAndDevicePixelRatio(size area, real devicePixelRatio) @@ -574,7 +607,8 @@ void Scene3DItem::setWindowSurface(QObject *rootObject) */ void Scene3DItem::setItemAreaAndDevicePixelRatio(QSize area, qreal devicePixelRatio) { - Qt3DRender::QRenderSurfaceSelector *surfaceSelector = Qt3DRender::QRenderSurfaceSelectorPrivate::find(m_entity); + Qt3DRender::QRenderSurfaceSelector *surfaceSelector + = Qt3DRender::QRenderSurfaceSelectorPrivate::find(entity()); if (surfaceSelector) { surfaceSelector->setExternalRenderTargetSize(area); surfaceSelector->setSurfacePixelRatio(devicePixelRatio); @@ -664,6 +698,22 @@ void Scene3DItem::setMultisample(bool enable) QSGNode *Scene3DItem::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNodeData *) { + // m_resetRequested is set to true by Scene3DRenderer::shutdown() + if (m_renderer && m_renderer->m_resetRequested) { + qCWarning(Scene3D) << "Renderer for Scene3DItem has requested a reset due to the item " + "moving to another window"; + QObject::disconnect(m_windowConnection); + m_aspectEngine->unregisterAspect(m_renderAspect); // Deletes the renderAspect + m_renderAspect = nullptr; + m_aspectToDelete = m_aspectEngine; + m_aspectEngine = new Qt3DCore::QAspectEngine(); + m_aspectEngine->setRunMode(Qt3DCore::QAspectEngine::Manual); + applyAspects(); + // Needs to belong in the same thread as the item which is the same as the original + // QAspectEngine + m_aspectEngine->moveToThread(thread()); + m_renderer->m_resetRequested = false; + } // If the render aspect wasn't created yet, do so now if (m_renderAspect == nullptr) { m_renderAspect = new QRenderAspect(QRenderAspect::Synchronous); @@ -674,16 +724,24 @@ QSGNode *Scene3DItem::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNode // Before Synchronizing is in the SG Thread, we want beforeSync to be triggered // in the context of the main thread - QObject::connect(window(), &QQuickWindow::afterAnimating, - this, &Scene3DItem::onBeforeSync, Qt::DirectConnection); + m_windowConnection = QObject::connect(window(), &QQuickWindow::afterAnimating, + this, &Scene3DItem::onBeforeSync, Qt::DirectConnection); auto renderAspectPriv = static_cast<QRenderAspectPrivate*>(QRenderAspectPrivate::get(m_renderAspect)); QObject::connect(renderAspectPriv->m_aspectManager->changeArbiter(), &Qt3DCore::QChangeArbiter::receivedChange, this, [this] { m_dirty = true; }, Qt::DirectConnection); } if (m_renderer == nullptr) { - m_renderer = new Scene3DRenderer(this, m_aspectEngine, m_renderAspect); - m_renderer->setCleanerHelper(m_rendererCleaner); + m_renderer = new Scene3DRenderer(); + m_renderer->init(this, m_aspectEngine, m_renderAspect); + } else if (m_renderer->renderAspect() != m_renderAspect) { + // If the renderer's renderAspect is not equal to the aspect used + // by the item, then it means that we have created a new one due to + // the fact that shutdown() was called on the renderer previously. + // This is a typical situation when the window the item is in has + // moved from one screen to another. + updateWindowSurface(); + m_renderer->init(this, m_aspectEngine, m_renderAspect); } const bool usesFBO = m_compositingMode == FBO; const bool hasScene3DViews = !m_views.empty(); diff --git a/src/quick3d/imports/scene3d/scene3ditem_p.h b/src/quick3d/imports/scene3d/scene3ditem_p.h index e46bb20af..0beaf94c0 100644 --- a/src/quick3d/imports/scene3d/scene3ditem_p.h +++ b/src/quick3d/imports/scene3d/scene3ditem_p.h @@ -71,6 +71,7 @@ class Scene3DRenderer; class Scene3DCleaner; class Scene3DView; class QFrameGraphNode; +class QRenderSurfaceSelector; class Scene3DItem : public QQuickItem { @@ -138,16 +139,20 @@ private: void updateCameraAspectRatio(); void mousePressEvent(QMouseEvent *event) override; bool needsRender(); + void updateWindowSurface(); + void createDummySurface(QWindow *window, QRenderSurfaceSelector *surfaceSelector); + void applyAspects(); QStringList m_aspects; - Qt3DCore::QEntity *m_entity; + // Store as shared pointer so that aspect engine doesn't delete it. + QSharedPointer<Qt3DCore::QEntity> m_entity; Qt3DCore::QEntity *m_viewHolderEntity; Qt3DRender::QFrameGraphNode *m_viewHolderFG; Qt3DCore::QAspectEngine *m_aspectEngine; + Qt3DCore::QAspectEngine *m_aspectToDelete; QRenderAspect *m_renderAspect; Scene3DRenderer *m_renderer; - Scene3DCleaner *m_rendererCleaner; bool m_multisample; bool m_dirty; @@ -160,6 +165,7 @@ private: CompositingMode m_compositingMode; QOffscreenSurface *m_dummySurface; QVector<Scene3DView *> m_views; + QMetaObject::Connection m_windowConnection; }; } // Qt3DRender diff --git a/src/quick3d/imports/scene3d/scene3drenderer.cpp b/src/quick3d/imports/scene3d/scene3drenderer.cpp index 71cf6c240..96514b32d 100644 --- a/src/quick3d/imports/scene3d/scene3drenderer.cpp +++ b/src/quick3d/imports/scene3d/scene3drenderer.cpp @@ -53,7 +53,6 @@ #include <Qt3DCore/private/qchangearbiter_p.h> #include <Qt3DCore/private/qservicelocator_p.h> -#include <scene3dcleaner_p.h> #include <scene3ditem_p.h> #include <scene3dlogging_p.h> #include <scene3dsgnode_p.h> @@ -144,16 +143,15 @@ private: signal of the window is not called. Therefore the cleanup method is invoked to properly destroy the aspect engine. */ -Scene3DRenderer::Scene3DRenderer(Scene3DItem *item, Qt3DCore::QAspectEngine *aspectEngine, QRenderAspect *renderAspect) +Scene3DRenderer::Scene3DRenderer() : QObject() - , m_item(item) - , m_aspectEngine(aspectEngine) - , m_renderAspect(renderAspect) + , m_item(nullptr) + , m_aspectEngine(nullptr) + , m_renderAspect(nullptr) , m_multisampledFBO(nullptr) , m_finalFBO(nullptr) , m_texture(nullptr) , m_node(nullptr) - , m_cleaner(nullptr) , m_window(nullptr) , m_multisample(false) // this value is not used, will be synced from the Scene3DItem instead , m_lastMultisample(false) @@ -165,6 +163,17 @@ Scene3DRenderer::Scene3DRenderer(Scene3DItem *item, Qt3DCore::QAspectEngine *asp , m_allowRendering(0) , m_compositingMode(Scene3DItem::FBO) { +} + +void Scene3DRenderer::init(Scene3DItem *item, Qt3DCore::QAspectEngine *aspectEngine, + QRenderAspect *renderAspect) +{ + m_item = item; + m_window = m_item->window(); + m_aspectEngine = aspectEngine; + m_renderAspect = renderAspect; + m_needsShutdown = true; + Q_CHECK_PTR(m_item); Q_CHECK_PTR(m_item->window()); @@ -215,21 +224,14 @@ void Scene3DRenderer::scheduleRootEntityChange() QMetaObject::invokeMethod(m_item, "applyRootEntityChange", Qt::QueuedConnection); } -void Scene3DRenderer::setCleanerHelper(Scene3DCleaner *cleaner) -{ - m_cleaner = cleaner; - if (m_cleaner) { - // Window closed case - QObject::connect(m_item->window(), &QQuickWindow::destroyed, m_cleaner, &Scene3DCleaner::cleanup); - m_cleaner->setRenderer(this); - } -} - // 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(); + // In case the same item is rendered on another window reset it + m_resetRequested = true; + // Set to null so that subsequent calls to render // would return early m_item = nullptr; @@ -243,8 +245,13 @@ void Scene3DRenderer::shutdown() // Shutdown the Renderer Aspect while the OpenGL context // is still valid - if (m_renderAspect) + if (m_renderAspect) { static_cast<QRenderAspectPrivate*>(QRenderAspectPrivate::get(m_renderAspect))->renderShutdown(); + m_renderAspect = nullptr; + } + m_aspectEngine = nullptr; + m_finalFBO.reset(); + m_multisampledFBO.reset(); } // QtQuick render thread (which may also be the gui/main thread with QQuickWidget / RenderControl) @@ -254,7 +261,6 @@ void Scene3DRenderer::onSceneGraphInvalidated() if (m_needsShutdown) { m_needsShutdown = false; shutdown(); - QMetaObject::invokeMethod(m_cleaner, "cleanup"); } } @@ -265,7 +271,6 @@ void Scene3DRenderer::onWindowChanged(QQuickWindow *w) if (m_needsShutdown) { m_needsShutdown = false; shutdown(); - QMetaObject::invokeMethod(m_cleaner, "cleanup"); } } } @@ -288,6 +293,7 @@ void Scene3DRenderer::beforeSynchronize() // SceneGraph update for nothing if (m_skipFrame) { m_skipFrame = false; + ContextSaver saver; static_cast<QRenderAspectPrivate*>(QRenderAspectPrivate::get(m_renderAspect))->renderSynchronous(false); return; } diff --git a/src/quick3d/imports/scene3d/scene3drenderer_p.h b/src/quick3d/imports/scene3d/scene3drenderer_p.h index 08a2c60a3..5674f21c2 100644 --- a/src/quick3d/imports/scene3d/scene3drenderer_p.h +++ b/src/quick3d/imports/scene3d/scene3drenderer_p.h @@ -78,9 +78,7 @@ class Scene3DRenderer : public QObject { Q_OBJECT public: - Scene3DRenderer(Scene3DItem *item, - Qt3DCore::QAspectEngine *aspectEngine, - QRenderAspect *renderAspect); + Scene3DRenderer(); ~Scene3DRenderer(); void setSGNode(Scene3DSGNode *node); @@ -89,7 +87,12 @@ public: void setCompositingMode(Scene3DItem::CompositingMode mode); void setSkipFrame(bool skip); void setScene3DViews(const QVector<Scene3DView *> views); + void init(Scene3DItem *item, Qt3DCore::QAspectEngine *aspectEngine, QRenderAspect *renderAspect); + QRenderAspect *renderAspect() const + { + return m_renderAspect; + } public Q_SLOTS: void render(); void shutdown(); @@ -103,13 +106,12 @@ private: void scheduleRootEntityChange(); Scene3DItem *m_item; // Will be released by the QQuickWindow/QML Engine - Qt3DCore::QAspectEngine *m_aspectEngine; // Will be released by the Scene3DRendererCleaner + Qt3DCore::QAspectEngine *m_aspectEngine; // Will be released by the Scene3DItem QRenderAspect *m_renderAspect; // Will be released by the aspectEngine QScopedPointer<QOpenGLFramebufferObject> m_multisampledFBO; QScopedPointer<QOpenGLFramebufferObject> m_finalFBO; QScopedPointer<QSGTexture> m_texture; Scene3DSGNode *m_node; // Will be released by the QtQuick SceneGraph - Scene3DCleaner *m_cleaner; QQuickWindow *m_window; QMutex m_windowMutex; QSize m_lastSize; @@ -123,8 +125,9 @@ private: QSemaphore m_allowRendering; Scene3DItem::CompositingMode m_compositingMode; QVector<Scene3DView *> m_views; + bool m_resetRequested = false; - friend class Scene3DCleaner; + friend class Scene3DItem; }; } // namespace Qt3DRender diff --git a/src/render/framegraph/qlayerfilter.cpp b/src/render/framegraph/qlayerfilter.cpp index 8bad46f5d..5557687ce 100644 --- a/src/render/framegraph/qlayerfilter.cpp +++ b/src/render/framegraph/qlayerfilter.cpp @@ -214,8 +214,9 @@ void QLayerFilter::removeLayer(QLayer *layer) { Q_ASSERT(layer); Q_D(QLayerFilter); + if (!d->m_layers.removeOne(layer)) + return; d->updateNode(layer, "layer", Qt3DCore::PropertyValueRemoved); - d->m_layers.removeOne(layer); // Remove bookkeeping connection d->unregisterDestructionHelper(layer); } diff --git a/src/render/framegraph/qrenderpassfilter.cpp b/src/render/framegraph/qrenderpassfilter.cpp index 952657eb6..34462ebdf 100644 --- a/src/render/framegraph/qrenderpassfilter.cpp +++ b/src/render/framegraph/qrenderpassfilter.cpp @@ -151,8 +151,9 @@ void QRenderPassFilter::removeMatch(QFilterKey *filterKey) Q_ASSERT(filterKey); Q_D(QRenderPassFilter); + if (!d->m_matchList.removeOne(filterKey)) + return; d->updateNode(filterKey, "match", Qt3DCore::PropertyValueRemoved); - d->m_matchList.removeOne(filterKey); // Remove bookkeeping connection d->unregisterDestructionHelper(filterKey); } @@ -189,8 +190,9 @@ void QRenderPassFilter::removeParameter(QParameter *parameter) Q_ASSERT(parameter); Q_D(QRenderPassFilter); + if (!d->m_parameters.removeOne(parameter)) + return; d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueRemoved); - d->m_parameters.removeOne(parameter); // Remove bookkeeping connection d->unregisterDestructionHelper(parameter); } diff --git a/src/render/framegraph/qrenderstateset.cpp b/src/render/framegraph/qrenderstateset.cpp index 5341b3c7d..ac82954c8 100644 --- a/src/render/framegraph/qrenderstateset.cpp +++ b/src/render/framegraph/qrenderstateset.cpp @@ -203,8 +203,9 @@ void QRenderStateSet::removeRenderState(QRenderState *state) Q_ASSERT(state); Q_D(QRenderStateSet); + if (!d->m_renderStates.removeOne(state)) + return; d->updateNode(state, "renderState", Qt3DCore::PropertyValueRemoved); - d->m_renderStates.removeOne(state); // Remove bookkeeping connection d->unregisterDestructionHelper(state); } diff --git a/src/render/framegraph/qtechniquefilter.cpp b/src/render/framegraph/qtechniquefilter.cpp index c22e83381..5377e1297 100644 --- a/src/render/framegraph/qtechniquefilter.cpp +++ b/src/render/framegraph/qtechniquefilter.cpp @@ -155,8 +155,9 @@ void QTechniqueFilter::removeMatch(QFilterKey *filterKey) { Q_ASSERT(filterKey); Q_D(QTechniqueFilter); + if (!d->m_matchList.removeOne(filterKey)) + return; d->updateNode(filterKey, "matchAll", Qt3DCore::PropertyValueRemoved); - d->m_matchList.removeOne(filterKey); // Remove bookkeeping connection d->unregisterDestructionHelper(filterKey); } @@ -192,8 +193,9 @@ void QTechniqueFilter::removeParameter(QParameter *parameter) { Q_ASSERT(parameter); Q_D(QTechniqueFilter); + if (!d->m_parameters.removeOne(parameter)) + return; d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueRemoved); - d->m_parameters.removeOne(parameter); // Remove bookkeeping connection d->unregisterDestructionHelper(parameter); } diff --git a/src/render/frontend/qrendertarget.cpp b/src/render/frontend/qrendertarget.cpp index 57eecd795..7e0403c13 100644 --- a/src/render/frontend/qrendertarget.cpp +++ b/src/render/frontend/qrendertarget.cpp @@ -134,8 +134,9 @@ void QRenderTarget::removeOutput(QRenderTargetOutput *output) { Q_D(QRenderTarget); + if (!d->m_outputs.removeOne(output)) + return; d->updateNode(output, "output", Qt3DCore::PropertyValueRemoved); - d->m_outputs.removeOne(output); // Remove bookkeeping connection d->unregisterDestructionHelper(output); } diff --git a/src/render/geometry/qgeometry.cpp b/src/render/geometry/qgeometry.cpp index 48f054bce..ac22f2db1 100644 --- a/src/render/geometry/qgeometry.cpp +++ b/src/render/geometry/qgeometry.cpp @@ -206,7 +206,8 @@ void QGeometry::removeAttribute(QAttribute *attribute) { Q_ASSERT(attribute); Q_D(QGeometry); - d->m_attributes.removeOne(attribute); + if (!d->m_attributes.removeOne(attribute)) + return; // Remove bookkeeping connection d->unregisterDestructionHelper(attribute); d->updateNode(attribute, "attribute", Qt3DCore::PropertyValueRemoved); diff --git a/src/render/materialsystem/qeffect.cpp b/src/render/materialsystem/qeffect.cpp index 8637a92d4..9f4b3db94 100644 --- a/src/render/materialsystem/qeffect.cpp +++ b/src/render/materialsystem/qeffect.cpp @@ -203,7 +203,8 @@ void QEffect::removeParameter(QParameter *parameter) { Q_D(QEffect); - d->m_parameters.removeOne(parameter); + if (!d->m_parameters.removeOne(parameter)) + return; // Remove bookkeeping connection d->unregisterDestructionHelper(parameter); d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueRemoved); @@ -248,9 +249,9 @@ void QEffect::addTechnique(QTechnique *t) void QEffect::removeTechnique(QTechnique *t) { Q_D(QEffect); - if (t) - d->updateNode(t, "technique", Qt3DCore::PropertyValueRemoved); - d->m_techniques.removeOne(t); + if (!d->m_techniques.removeOne(t)) + return; + d->updateNode(t, "technique", Qt3DCore::PropertyValueRemoved); // Remove bookkeeping connection d->unregisterDestructionHelper(t); } diff --git a/src/render/materialsystem/qmaterial.cpp b/src/render/materialsystem/qmaterial.cpp index edd227500..a1bec183b 100644 --- a/src/render/materialsystem/qmaterial.cpp +++ b/src/render/materialsystem/qmaterial.cpp @@ -283,8 +283,10 @@ void QMaterial::removeParameter(QParameter *parameter) { Q_ASSERT(parameter); Q_D(QMaterial); + if (!d->m_parameters.removeOne(parameter)) + return; + d->unregisterDestructionHelper(parameter); d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueRemoved); - d->m_parameters.removeOne(parameter); } /*! diff --git a/src/render/materialsystem/qrenderpass.cpp b/src/render/materialsystem/qrenderpass.cpp index dcb831b13..33181f4fe 100644 --- a/src/render/materialsystem/qrenderpass.cpp +++ b/src/render/materialsystem/qrenderpass.cpp @@ -285,8 +285,9 @@ void QRenderPass::removeFilterKey(QFilterKey *filterKey) { Q_ASSERT(filterKey); Q_D(QRenderPass); + if (!d->m_filterKeyList.removeOne(filterKey)) + return; d->updateNode(filterKey, "filterKeys", Qt3DCore::PropertyValueRemoved); - d->m_filterKeyList.removeOne(filterKey); // Remove bookkeeping connection d->unregisterDestructionHelper(filterKey); } @@ -333,8 +334,9 @@ void QRenderPass::removeRenderState(QRenderState *state) { Q_ASSERT(state); Q_D(QRenderPass); + if (!d->m_renderStates.removeOne(state)) + return; d->updateNode(state, "renderState", Qt3DCore::PropertyValueRemoved); - d->m_renderStates.removeOne(state); // Remove bookkeeping connection d->unregisterDestructionHelper(state); } @@ -380,8 +382,9 @@ void QRenderPass::removeParameter(QParameter *parameter) { Q_ASSERT(parameter); Q_D(QRenderPass); + if (!d->m_parameters.removeOne(parameter)) + return; d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueRemoved); - d->m_parameters.removeOne(parameter); // Remove bookkeeping connection d->unregisterDestructionHelper(parameter); } diff --git a/src/render/materialsystem/qtechnique.cpp b/src/render/materialsystem/qtechnique.cpp index a9b7ca82b..0e1787938 100644 --- a/src/render/materialsystem/qtechnique.cpp +++ b/src/render/materialsystem/qtechnique.cpp @@ -269,8 +269,9 @@ void QTechnique::removeFilterKey(QFilterKey *filterKey) { Q_ASSERT(filterKey); Q_D(QTechnique); + if (!d->m_filterKeys.removeOne(filterKey)) + return; d->updateNode(filterKey, "filterKeys", Qt3DCore::PropertyValueRemoved); - d->m_filterKeys.removeOne(filterKey); // Remove bookkeeping connection d->unregisterDestructionHelper(filterKey); } @@ -316,8 +317,9 @@ void QTechnique::removeParameter(QParameter *parameter) { Q_ASSERT(parameter); Q_D(QTechnique); + if (!d->m_parameters.removeOne(parameter)) + return; d->updateNode(parameter, "parameter", Qt3DCore::PropertyValueRemoved); - d->m_parameters.removeOne(parameter); // Remove bookkeeping connection d->unregisterDestructionHelper(parameter); } @@ -353,8 +355,9 @@ void QTechnique::removeRenderPass(QRenderPass *pass) { Q_ASSERT(pass); Q_D(QTechnique); + if (!d->m_renderPasses.removeOne(pass)) + return; d->updateNode(pass, "pass", Qt3DCore::PropertyValueAdded); - d->m_renderPasses.removeOne(pass); // Remove bookkeeping connection d->unregisterDestructionHelper(pass); } diff --git a/src/render/materialsystem/shaderbuilder.cpp b/src/render/materialsystem/shaderbuilder.cpp index b902e3d8c..c0bf21f44 100644 --- a/src/render/materialsystem/shaderbuilder.cpp +++ b/src/render/materialsystem/shaderbuilder.cpp @@ -278,7 +278,7 @@ void ShaderBuilder::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) markDirty(AbstractRenderer::ShadersDirty); } - static const QVector<std::pair<QShaderProgram::ShaderType, QUrl (QShaderProgramBuilder::*)() const>> shaderTypesToGetters = { + static const QVarLengthArray<std::pair<QShaderProgram::ShaderType, QUrl (QShaderProgramBuilder::*)() const>, 6> shaderTypesToGetters { {QShaderProgram::Vertex, &QShaderProgramBuilder::vertexShaderGraph}, {QShaderProgram::TessellationControl, &QShaderProgramBuilder::tessellationControlShaderGraph}, {QShaderProgram::TessellationEvaluation, &QShaderProgramBuilder::tessellationEvaluationShaderGraph}, diff --git a/src/render/picking/qabstractraycaster.cpp b/src/render/picking/qabstractraycaster.cpp index f26c67e99..42c7bc1e5 100644 --- a/src/render/picking/qabstractraycaster.cpp +++ b/src/render/picking/qabstractraycaster.cpp @@ -348,8 +348,9 @@ void QAbstractRayCaster::removeLayer(QLayer *layer) { Q_ASSERT(layer); Q_D(QAbstractRayCaster); + if (!d->m_layers.removeOne(layer)) + return; d->updateNode(layer, "layer", Qt3DCore::PropertyValueRemoved); - d->m_layers.removeOne(layer); // Remove bookkeeping connection d->unregisterDestructionHelper(layer); } diff --git a/src/render/texture/qabstracttexture.cpp b/src/render/texture/qabstracttexture.cpp index 2e7fd0f63..2a955c5d8 100644 --- a/src/render/texture/qabstracttexture.cpp +++ b/src/render/texture/qabstracttexture.cpp @@ -791,8 +791,9 @@ void QAbstractTexture::removeTextureImage(QAbstractTextureImage *textureImage) { Q_ASSERT(textureImage); Q_D(QAbstractTexture); + if (!d->m_textureImages.removeOne(textureImage)) + return; d->updateNode(textureImage, "textureImage", PropertyValueRemoved); - d->m_textureImages.removeOne(textureImage); // Remove bookkeeping connection d->unregisterDestructionHelper(textureImage); } |