summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@qt.io>2017-11-20 13:48:26 +0100
committerOswald Buddenhagen <oswald.buddenhagen@qt.io>2017-11-20 13:48:26 +0100
commita2c7dbba0ad60cf17997f77372004339d4580a52 (patch)
treec0f7f03107438b85031808a9581bf9adecc138ba
parent2e26894fdd2d4593bee6ab9062f64a1f4210d619 (diff)
parent5e94e34c5b9567980929e677357467806aacaf1a (diff)
Merge 5.10 into 5.10.0
-rw-r--r--examples/qt3d/controls/Logo.qml16
-rw-r--r--examples/qt3d/phong-cubes/main.qml25
-rw-r--r--src/animation/backend/channelmapping.cpp13
-rw-r--r--src/animation/backend/handler.cpp31
-rw-r--r--src/animation/backend/handler_p.h1
-rw-r--r--src/animation/backend/loadanimationclipjob.cpp1
-rw-r--r--src/animation/frontend/frontend.pri7
-rw-r--r--src/animation/frontend/qanimationcallback.h1
-rw-r--r--src/animation/frontend/qcallbackmapping.cpp168
-rw-r--r--src/animation/frontend/qcallbackmapping.h82
-rw-r--r--src/animation/frontend/qcallbackmapping_p.h85
-rw-r--r--src/animation/frontend/qchannelmapping.cpp60
-rw-r--r--src/animation/frontend/qchannelmapping.h3
-rw-r--r--src/animation/frontend/qchannelmapping_p.h4
-rw-r--r--src/animation/frontend/qclipanimator.cpp3
-rw-r--r--src/core/resources/qhandle_p.h89
-rw-r--r--src/core/resources/qresourcemanager_p.h177
-rw-r--r--src/extras/defaults/defaults.pri3
-rw-r--r--src/extras/defaults/qdiffusemapmaterial.cpp3
-rw-r--r--src/extras/defaults/qdiffusespecularmapmaterial.cpp3
-rw-r--r--src/extras/defaults/qdiffusespecularmaterial.cpp496
-rw-r--r--src/extras/defaults/qdiffusespecularmaterial.h102
-rw-r--r--src/extras/defaults/qdiffusespecularmaterial_p.h120
-rw-r--r--src/extras/defaults/qnormaldiffusemapalphamaterial.cpp3
-rw-r--r--src/extras/defaults/qnormaldiffusemapmaterial.cpp3
-rw-r--r--src/extras/defaults/qnormaldiffusespecularmapmaterial.cpp3
-rw-r--r--src/extras/defaults/qphongalphamaterial.cpp3
-rw-r--r--src/extras/defaults/qphongmaterial.cpp3
-rw-r--r--src/plugins/geometryloaders/default/objgeometryloader.cpp4
-rw-r--r--src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp2
-rw-r--r--src/render/backend/abstractrenderer_p.h1
-rw-r--r--src/render/backend/attachmentpack.cpp2
-rw-r--r--src/render/backend/layer.cpp4
-rw-r--r--src/render/backend/layer_p.h2
-rw-r--r--src/render/backend/render-backend.pri3
-rw-r--r--src/render/backend/renderer.cpp43
-rw-r--r--src/render/backend/renderer_p.h4
-rw-r--r--src/render/backend/renderercache_p.h86
-rw-r--r--src/render/backend/renderview.cpp2
-rw-r--r--src/render/backend/renderviewbuilder.cpp224
-rw-r--r--src/render/backend/renderviewbuilder_p.h8
-rw-r--r--src/render/framegraph/layerfilternode.cpp3
-rw-r--r--src/render/geometry/buffermanager.cpp4
-rw-r--r--src/render/graphicshelpers/graphicshelperes2.cpp3
-rw-r--r--src/render/graphicshelpers/graphicshelpergl2.cpp3
-rw-r--r--src/render/graphicshelpers/graphicshelpergl3_2.cpp3
-rw-r--r--src/render/graphicshelpers/graphicshelpergl3_3.cpp3
-rw-r--r--src/render/graphicshelpers/graphicshelpergl4.cpp3
-rw-r--r--src/render/jobs/job_common_p.h3
-rw-r--r--src/render/materialsystem/parameter.cpp5
-rw-r--r--src/render/materialsystem/prototypes/default.json2
-rw-r--r--tests/auto/animation/animation.pro3
-rw-r--r--tests/auto/animation/channelmapping/tst_channelmapping.cpp4
-rw-r--r--tests/auto/animation/findrunningclipanimatorsjob/tst_findrunningclipanimatorsjob.cpp1
-rw-r--r--tests/auto/animation/qcallbackmapping/qcallbackmapping.pro12
-rw-r--r--tests/auto/animation/qcallbackmapping/tst_qcallbackmapping.cpp223
-rw-r--r--tests/auto/core/handle/tst_handle.cpp96
-rw-r--r--tests/auto/core/qresourcemanager/tst_qresourcemanager.cpp25
-rw-r--r--tests/auto/render/filtercompatibletechniquejob/BLACKLIST7
-rw-r--r--tests/auto/render/geometryloaders/cube2.obj26
-rw-r--r--tests/auto/render/geometryloaders/geometryloaders.qrc1
-rw-r--r--tests/auto/render/geometryloaders/tst_geometryloaders.cpp10
-rw-r--r--tests/auto/render/renderer/tst_renderer.cpp2
-rw-r--r--tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp354
-rw-r--r--tests/benchmarks/core/qresourcesmanager/qresourcesmanager/tst_bench_qresourcesmanager.cpp7
-rw-r--r--tests/manual/layerfilter-qml/main.qml4
66 files changed, 2162 insertions, 538 deletions
diff --git a/examples/qt3d/controls/Logo.qml b/examples/qt3d/controls/Logo.qml
index 2eb9abd1a..62742246f 100644
--- a/examples/qt3d/controls/Logo.qml
+++ b/examples/qt3d/controls/Logo.qml
@@ -91,8 +91,8 @@ Entity {
PhongMaterial {
id: material
- ambient: Qt.rgba( color_r.value/255, color_g.value/255, color_b.value/255, 1.0 )
- diffuse: Qt.rgba( 0.1, 0.1, 0.1, 0.5 )
+ diffuse: Qt.rgba( color_r.value/255, color_g.value/255, color_b.value/255, 1.0 )
+ ambient: Qt.rgba( 0.1, 0.1, 0.1, 1.0 )
shininess: shining.value
}
@@ -110,4 +110,16 @@ Entity {
id: logoEntity
components: [ logoMesh, material, logoTransform ]
}
+
+ Entity {
+ components: [
+ PointLight {
+ color: "white"
+ intensity: 0.6
+ },
+ Transform {
+ translation: Qt.vector3d(0, 0, 10)
+ }
+ ]
+ }
}
diff --git a/examples/qt3d/phong-cubes/main.qml b/examples/qt3d/phong-cubes/main.qml
index 0e067fdad..311e65a63 100644
--- a/examples/qt3d/phong-cubes/main.qml
+++ b/examples/qt3d/phong-cubes/main.qml
@@ -51,7 +51,8 @@
import Qt3D.Core 2.0
import Qt3D.Render 2.0
import Qt3D.Input 2.0
-import Qt3D.Extras 2.0
+import Qt3D.Extras 2.10
+import QtQuick 2.0
Entity {
components: [
@@ -84,19 +85,19 @@ Entity {
CubeEntity {
position: Qt.vector3d(-1, 1, 0)
- material: PhongMaterial {}
+ material: DiffuseSpecularMaterial {}
}
CubeEntity {
position: Qt.vector3d(0, 1, 0)
- material: DiffuseMapMaterial {
+ material: DiffuseSpecularMaterial {
diffuse: TextureLoader { source: "qrc:/assets/textures/pattern_09/diffuse.webp" }
}
}
CubeEntity {
position: Qt.vector3d(1, 1, 0)
- material: DiffuseSpecularMapMaterial {
+ material: DiffuseSpecularMaterial {
diffuse: TextureLoader { source: "qrc:/assets/textures/pattern_09/diffuse.webp" }
specular: TextureLoader { source: "qrc:/assets/textures/pattern_09/specular.webp" }
}
@@ -104,12 +105,15 @@ Entity {
CubeEntity {
position: Qt.vector3d(-1, 0, 0)
- material: PhongAlphaMaterial {}
+ material: DiffuseSpecularMaterial {
+ alphaBlending: true
+ diffuse: Qt.rgba(0.7, 0.7, 0.7, 0.5)
+ }
}
CubeEntity {
position: Qt.vector3d(0, 0, 0)
- material: NormalDiffuseMapMaterial {
+ material: DiffuseSpecularMaterial {
normal: TextureLoader { source: "qrc:/assets/textures/pattern_09/normal.webp" }
diffuse: TextureLoader { source: "qrc:/assets/textures/pattern_09/diffuse.webp" }
}
@@ -117,7 +121,8 @@ Entity {
CubeEntity {
position: Qt.vector3d(1, 0, 0)
- material: NormalDiffuseMapAlphaMaterial {
+ material: DiffuseSpecularMaterial {
+ alphaBlending: true
normal: TextureLoader { source: "qrc:/assets/textures/pattern_09/normal.webp" }
diffuse: TextureLoader { source: "qrc:/assets/textures/pattern_09/diffuse.webp" }
}
@@ -125,7 +130,7 @@ Entity {
CubeEntity {
position: Qt.vector3d(-1, -1, 0)
- material: NormalDiffuseSpecularMapMaterial {
+ material: DiffuseSpecularMaterial {
normal: TextureLoader { source: "qrc:/assets/textures/pattern_09/normal.webp" }
diffuse: TextureLoader { source: "qrc:/assets/textures/pattern_09/diffuse.webp" }
specular: TextureLoader { source: "qrc:/assets/textures/pattern_09/specular.webp" }
@@ -134,7 +139,7 @@ Entity {
CubeEntity {
position: Qt.vector3d(0, -1, 0)
- material: NormalDiffuseSpecularMapMaterial {
+ material: DiffuseSpecularMaterial {
normal: TextureLoader { source: "qrc:/assets/textures/pattern_09/normal.webp" }
diffuse: TextureLoader { source: "qrc:/assets/textures/pattern_09/diffuse.webp" }
specular: TextureLoader { source: "qrc:/assets/textures/pattern_09/specular.webp" }
@@ -143,7 +148,7 @@ Entity {
CubeEntity {
position: Qt.vector3d(1, -1, 0)
- material: NormalDiffuseSpecularMapMaterial {
+ material: DiffuseSpecularMaterial {
normal: TextureLoader { source: "qrc:/assets/textures/pattern_09/normal.webp" }
diffuse: TextureLoader { source: "qrc:/assets/textures/pattern_09/diffuse.webp" }
specular: TextureLoader { source: "qrc:/assets/textures/pattern_09/specular.webp" }
diff --git a/src/animation/backend/channelmapping.cpp b/src/animation/backend/channelmapping.cpp
index 4c263edba..ecae8bbae 100644
--- a/src/animation/backend/channelmapping.cpp
+++ b/src/animation/backend/channelmapping.cpp
@@ -36,6 +36,7 @@
#include "channelmapping_p.h"
#include <Qt3DAnimation/qchannelmapping.h>
+#include <Qt3DAnimation/private/qcallbackmapping_p.h>
#include <Qt3DAnimation/private/qchannelmapping_p.h>
#include <Qt3DAnimation/private/qskeletonmapping_p.h>
#include <Qt3DAnimation/private/animationlogging_p.h>
@@ -58,6 +59,7 @@ ChannelMapping::ChannelMapping()
, m_callback(nullptr)
, m_callbackFlags(0)
, m_skeletonId()
+ , m_mappingType(MappingType::ChannelMappingType)
{
}
@@ -73,8 +75,6 @@ void ChannelMapping::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePt
m_property = data.property;
m_type = data.type;
m_propertyName = data.propertyName;
- m_callback = data.callback;
- m_callbackFlags = data.callbackFlags;
m_mappingType = ChannelMappingType;
break;
}
@@ -88,8 +88,13 @@ void ChannelMapping::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePt
}
case QChannelMappingCreatedChangeBase::CallbackMapping: {
- // TODO: Refactor callback support out of QChannelMapping and into its own type
- m_mappingType = CallbackMappingType;
+ const auto typedChange = qSharedPointerCast<QChannelMappingCreatedChange<QCallbackMappingData>>(change);
+ const auto &data = typedChange->data;
+ m_channelName = data.channelName;
+ m_type = data.type;
+ m_callback = data.callback;
+ m_callbackFlags = data.callbackFlags;
+ m_mappingType = ChannelMappingType;
break;
}
}
diff --git a/src/animation/backend/handler.cpp b/src/animation/backend/handler.cpp
index 071343791..ed48d281f 100644
--- a/src/animation/backend/handler.cpp
+++ b/src/animation/backend/handler.cpp
@@ -149,6 +149,16 @@ void Handler::setBlendedClipAnimatorRunning(const HBlendedClipAnimator &handle,
// The vectors may get outdated when the application removes/deletes an
// animator component in the meantime. Recognize this. This should be
// relatively infrequent so in most cases the vectors will not change at all.
+void Handler::cleanupHandleList(QVector<HAnimationClip> *clips)
+{
+ for (auto it = clips->begin(); it != clips->end(); ) {
+ if (!m_animationClipLoaderManager->data(*it))
+ clips->erase(it);
+ else
+ ++it;
+ }
+}
+
void Handler::cleanupHandleList(QVector<HClipAnimator> *animators)
{
for (auto it = animators->begin(); it != animators->end(); ) {
@@ -182,8 +192,10 @@ QVector<Qt3DCore::QAspectJobPtr> Handler::jobsToExecute(qint64 time)
// If there are any dirty animation clips that need loading,
// queue up a job for them
- if (!m_dirtyAnimationClips.isEmpty()) {
+ const bool hasLoadAnimationClipJob = !m_dirtyAnimationClips.isEmpty();
+ if (hasLoadAnimationClipJob) {
qCDebug(HandlerLogic) << "Added LoadAnimationClipJob";
+ cleanupHandleList(&m_dirtyAnimationClips);
m_loadAnimationClipJob->addDirtyAnimationClips(m_dirtyAnimationClips);
jobs.push_back(m_loadAnimationClipJob);
m_dirtyAnimationClips.clear();
@@ -192,19 +204,22 @@ QVector<Qt3DCore::QAspectJobPtr> Handler::jobsToExecute(qint64 time)
// If there are dirty clip animators, find the set that are able to
// run. I.e. are marked as running and have animation clips and
// channel mappings
- if (!m_dirtyClipAnimators.isEmpty()) {
+
+ const bool hasFindRunningClipAnimatorsJob = !m_dirtyClipAnimators.isEmpty();
+ if (hasFindRunningClipAnimatorsJob) {
qCDebug(HandlerLogic) << "Added FindRunningClipAnimatorsJob";
m_findRunningClipAnimatorsJob->removeDependency(QWeakPointer<Qt3DCore::QAspectJob>());
cleanupHandleList(&m_dirtyClipAnimators);
m_findRunningClipAnimatorsJob->setDirtyClipAnimators(m_dirtyClipAnimators);
jobs.push_back(m_findRunningClipAnimatorsJob);
- if (jobs.contains(m_loadAnimationClipJob))
+ if (hasLoadAnimationClipJob)
m_findRunningClipAnimatorsJob->addDependency(m_loadAnimationClipJob);
m_dirtyClipAnimators.clear();
}
// Rebuild blending trees if a blend tree is dirty
- if (!m_dirtyBlendedAnimators.isEmpty()) {
+ const bool hasBuildBlendTreesJob = !m_dirtyBlendedAnimators.isEmpty();
+ if (hasBuildBlendTreesJob) {
const QVector<HBlendedClipAnimator> dirtyBlendedAnimators = std::move(m_dirtyBlendedAnimators);
m_buildBlendTreesJob->setBlendedClipAnimators(dirtyBlendedAnimators);
jobs.push_back(m_buildBlendTreesJob);
@@ -233,9 +248,9 @@ QVector<Qt3DCore::QAspectJobPtr> Handler::jobsToExecute(qint64 time)
for (int i = 0; i < newSize; ++i) {
m_evaluateClipAnimatorJobs[i]->setClipAnimator(m_runningClipAnimators[i]);
m_evaluateClipAnimatorJobs[i]->removeDependency(QWeakPointer<Qt3DCore::QAspectJob>());
- if (jobs.contains(m_loadAnimationClipJob))
+ if (hasLoadAnimationClipJob)
m_evaluateClipAnimatorJobs[i]->addDependency(m_loadAnimationClipJob);
- if (jobs.contains(m_findRunningClipAnimatorsJob))
+ if (hasFindRunningClipAnimatorsJob)
m_evaluateClipAnimatorJobs[i]->addDependency(m_findRunningClipAnimatorsJob);
jobs.push_back(m_evaluateClipAnimatorJobs[i]);
}
@@ -259,9 +274,9 @@ QVector<Qt3DCore::QAspectJobPtr> Handler::jobsToExecute(qint64 time)
for (int i = 0; i < newSize; ++i) {
m_evaluateBlendClipAnimatorJobs[i]->setBlendClipAnimator(m_runningBlendedClipAnimators[i]);
m_evaluateBlendClipAnimatorJobs[i]->removeDependency(QWeakPointer<Qt3DCore::QAspectJob>());
- if (jobs.contains(m_loadAnimationClipJob))
+ if (hasLoadAnimationClipJob)
m_evaluateBlendClipAnimatorJobs[i]->addDependency(m_loadAnimationClipJob);
- if (jobs.contains(m_buildBlendTreesJob))
+ if (hasBuildBlendTreesJob)
m_evaluateBlendClipAnimatorJobs[i]->addDependency(m_buildBlendTreesJob);
jobs.push_back(m_evaluateBlendClipAnimatorJobs[i]);
}
diff --git a/src/animation/backend/handler_p.h b/src/animation/backend/handler_p.h
index d35d5a132..99e2ae1f6 100644
--- a/src/animation/backend/handler_p.h
+++ b/src/animation/backend/handler_p.h
@@ -121,6 +121,7 @@ public:
QVector<Qt3DCore::QAspectJobPtr> jobsToExecute(qint64 time);
+ void cleanupHandleList(QVector<HAnimationClip> *clips);
void cleanupHandleList(QVector<HClipAnimator> *animators);
void cleanupHandleList(QVector<HBlendedClipAnimator> *animators);
diff --git a/src/animation/backend/loadanimationclipjob.cpp b/src/animation/backend/loadanimationclipjob.cpp
index c0201e0e9..4584449bc 100644
--- a/src/animation/backend/loadanimationclipjob.cpp
+++ b/src/animation/backend/loadanimationclipjob.cpp
@@ -72,6 +72,7 @@ void LoadAnimationClipJob::run()
AnimationClipLoaderManager *animationClipManager = m_handler->animationClipLoaderManager();
for (const auto animationClipHandle : qAsConst(m_animationClipHandles)) {
AnimationClip *animationClip = animationClipManager->data(animationClipHandle);
+ Q_ASSERT(animationClip);
animationClip->loadAnimation();
}
diff --git a/src/animation/frontend/frontend.pri b/src/animation/frontend/frontend.pri
index 48b1cb6b1..baff81dd0 100644
--- a/src/animation/frontend/frontend.pri
+++ b/src/animation/frontend/frontend.pri
@@ -54,7 +54,9 @@ HEADERS += \
$$PWD/qchannelmappingcreatedchange_p.h \
$$PWD/qchannelmappingcreatedchange_p_p.h \
$$PWD/qskeletonmapping.h \
- $$PWD/qskeletonmapping_p.h
+ $$PWD/qskeletonmapping_p.h \
+ $$PWD/qcallbackmapping.h \
+ $$PWD/qcallbackmapping_p.h
SOURCES += \
$$PWD/qanimationaspect.cpp \
@@ -86,6 +88,7 @@ SOURCES += \
$$PWD/qclock.cpp \
$$PWD/qabstractchannelmapping.cpp \
$$PWD/qchannelmappingcreatedchange.cpp \
- $$PWD/qskeletonmapping.cpp
+ $$PWD/qskeletonmapping.cpp \
+ $$PWD/qcallbackmapping.cpp
INCLUDEPATH += $$PWD
diff --git a/src/animation/frontend/qanimationcallback.h b/src/animation/frontend/qanimationcallback.h
index 63e094918..1fcbd657c 100644
--- a/src/animation/frontend/qanimationcallback.h
+++ b/src/animation/frontend/qanimationcallback.h
@@ -48,6 +48,7 @@ class QT3DANIMATIONSHARED_EXPORT QAnimationCallback
{
public:
enum Flag {
+ OnOwningThread = 0x0,
OnThreadPool = 0x01
};
Q_DECLARE_FLAGS(Flags, Flag)
diff --git a/src/animation/frontend/qcallbackmapping.cpp b/src/animation/frontend/qcallbackmapping.cpp
new file mode 100644
index 000000000..3fcc7cf5e
--- /dev/null
+++ b/src/animation/frontend/qcallbackmapping.cpp
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcallbackmapping.h"
+#include "qcallbackmapping_p.h"
+
+#include <Qt3DAnimation/private/qchannelmappingcreatedchange_p.h>
+#include <Qt3DCore/qpropertyupdatedchange.h>
+
+#include <QtCore/qmetaobject.h>
+#include <QtCore/QMetaProperty>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+
+QCallbackMappingPrivate::QCallbackMappingPrivate()
+ : QAbstractChannelMappingPrivate()
+ , m_channelName()
+ , m_type(static_cast<int>(QVariant::Invalid))
+ , m_callback(nullptr)
+ , m_callbackFlags(0)
+{
+ m_mappingType = QChannelMappingCreatedChangeBase::CallbackMapping;
+}
+
+/*!
+ \class QCallbackMapping
+ \inherits Qt3DCore::QAbstractChannelMapping
+ \inmodule Qt3DAnimation
+ \brief Allows to map the channels within the clip onto an invocation
+ of a callback object.
+*/
+
+QCallbackMapping::QCallbackMapping(Qt3DCore::QNode *parent)
+ : QAbstractChannelMapping(*new QCallbackMappingPrivate, parent)
+{
+}
+
+QCallbackMapping::QCallbackMapping(QCallbackMappingPrivate &dd, Qt3DCore::QNode *parent)
+ : QAbstractChannelMapping(dd, parent)
+{
+}
+
+QCallbackMapping::~QCallbackMapping()
+{
+}
+
+QString QCallbackMapping::channelName() const
+{
+ Q_D(const QCallbackMapping);
+ return d->m_channelName;
+}
+
+QAnimationCallback *QCallbackMapping::callback() const
+{
+ Q_D(const QCallbackMapping);
+ return d->m_callback;
+}
+
+void QCallbackMapping::setChannelName(const QString &channelName)
+{
+ Q_D(QCallbackMapping);
+ if (d->m_channelName == channelName)
+ return;
+
+ d->m_channelName = channelName;
+ emit channelNameChanged(channelName);
+}
+
+/*!
+ Associates a \a callback object with this channel mapping.
+
+ Such mappings do not have to have a target object and property name. When
+ the \a callback object is set, every change in the animated value will lead
+ to invoking the callback's
+ \l{QAnimationCallback::onValueChanged()}{onValueChanged()} function either
+ on the gui/main thread, or directly on one of the thread pool's worker
+ thread. This is controlled by \a flags.
+
+ \a type specifies the type (for example, QVariant::Vector3D,
+ QVariant::Color, or QMetaType::Float) of the animated value. When animating
+ node properties this does not need to be provided separately, however it
+ becomes important to supply this when there is only a callback.
+
+ \note A mapping can be associated both with a node property and a
+ callback. It is important however that \a type matches the type of the
+ property in this case. Note also that for properties of type QVariant (for
+ example, QParameter::value), the \a type is the type of the value stored in
+ the QVariant.
+
+ \note The \a callback pointer is expected to stay valid while any
+ associated animators are running.
+ */
+void QCallbackMapping::setCallback(int type, QAnimationCallback *callback, QAnimationCallback::Flags flags)
+{
+ Q_D(QCallbackMapping);
+ if (d->m_type != type) {
+ d->m_type = type;
+ auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(id());
+ e->setPropertyName("type");
+ e->setValue(QVariant(d->m_type));
+ notifyObservers(e);
+ }
+ if (d->m_callback != callback) {
+ d->m_callback = callback;
+ auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(id());
+ e->setPropertyName("callback");
+ e->setValue(QVariant::fromValue(static_cast<void *>(d->m_callback)));
+ notifyObservers(e);
+ }
+ if (d->m_callbackFlags != flags) {
+ d->m_callbackFlags = flags;
+ auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(id());
+ e->setPropertyName("callbackFlags");
+ e->setValue(QVariant::fromValue(int(d->m_callbackFlags)));
+ notifyObservers(e);
+ }
+}
+
+Qt3DCore::QNodeCreatedChangeBasePtr QCallbackMapping::createNodeCreationChange() const
+{
+ auto creationChange = QChannelMappingCreatedChangePtr<QCallbackMappingData>::create(this);
+ auto &data = creationChange->data;
+ Q_D(const QCallbackMapping);
+ data.channelName = d->m_channelName;
+ data.type = d->m_type;
+ data.callback = d->m_callback;
+ data.callbackFlags = d->m_callbackFlags;
+ return creationChange;
+}
+
+} // namespace Qt3DAnimation
+
+QT_END_NAMESPACE
diff --git a/src/animation/frontend/qcallbackmapping.h b/src/animation/frontend/qcallbackmapping.h
new file mode 100644
index 000000000..c52e284ff
--- /dev/null
+++ b/src/animation/frontend/qcallbackmapping.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DANIMATION_QCALLBACKMAPPING_H
+#define QT3DANIMATION_QCALLBACKMAPPING_H
+
+#include <Qt3DAnimation/qt3danimation_global.h>
+#include <Qt3DAnimation/qanimationcallback.h>
+#include <Qt3DAnimation/qabstractchannelmapping.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+
+class QCallbackMappingPrivate;
+
+class QT3DANIMATIONSHARED_EXPORT QCallbackMapping : public QAbstractChannelMapping
+{
+ Q_OBJECT
+ Q_PROPERTY(QString channelName READ channelName WRITE setChannelName NOTIFY channelNameChanged)
+
+public:
+ explicit QCallbackMapping(Qt3DCore::QNode *parent = nullptr);
+ ~QCallbackMapping();
+
+ QString channelName() const;
+ QAnimationCallback *callback() const;
+
+ void setCallback(int type, QAnimationCallback *callback, QAnimationCallback::Flags flags = QAnimationCallback::OnOwningThread);
+
+public Q_SLOTS:
+ void setChannelName(const QString &channelName);
+
+Q_SIGNALS:
+ void channelNameChanged(QString channelName);
+
+protected:
+ explicit QCallbackMapping(QCallbackMappingPrivate &dd, Qt3DCore::QNode *parent = nullptr);
+
+private:
+ Q_DECLARE_PRIVATE(QCallbackMapping)
+ Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const Q_DECL_OVERRIDE;
+};
+
+} // namespace Qt3DAnimation
+
+QT_END_NAMESPACE
+
+#endif // QT3DANIMATION_QCALLBACKMAPPING_H
diff --git a/src/animation/frontend/qcallbackmapping_p.h b/src/animation/frontend/qcallbackmapping_p.h
new file mode 100644
index 000000000..c966ca552
--- /dev/null
+++ b/src/animation/frontend/qcallbackmapping_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DANIMATION_QCALLBACKMAPPING_P_H
+#define QT3DANIMATION_QCALLBACKMAPPING_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DAnimation/private/qabstractchannelmapping_p.h>
+#include <Qt3DAnimation/qanimationcallback.h>
+#include <Qt3DAnimation/qcallbackmapping.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DAnimation {
+
+class QCallbackMappingPrivate : public QAbstractChannelMappingPrivate
+{
+public:
+ QCallbackMappingPrivate();
+
+ Q_DECLARE_PUBLIC(QCallbackMapping)
+
+ QString m_channelName;
+ int m_type;
+ QAnimationCallback *m_callback;
+ QAnimationCallback::Flags m_callbackFlags;
+};
+
+struct QCallbackMappingData
+{
+ QString channelName;
+ int type;
+ QAnimationCallback *callback;
+ QAnimationCallback::Flags callbackFlags;
+};
+
+} // namespace Qt3DAnimation
+
+
+QT_END_NAMESPACE
+
+#endif // QT3DANIMATION_QCALLBACKMAPPING_P_H
diff --git a/src/animation/frontend/qchannelmapping.cpp b/src/animation/frontend/qchannelmapping.cpp
index cb7b0739f..722ce24b0 100644
--- a/src/animation/frontend/qchannelmapping.cpp
+++ b/src/animation/frontend/qchannelmapping.cpp
@@ -54,8 +54,6 @@ QChannelMappingPrivate::QChannelMappingPrivate()
, m_property()
, m_propertyName(nullptr)
, m_type(static_cast<int>(QVariant::Invalid))
- , m_callback(nullptr)
- , m_callbackFlags(0)
{
m_mappingType = QChannelMappingCreatedChangeBase::ChannelMapping;
}
@@ -152,12 +150,6 @@ QString QChannelMapping::property() const
return d->m_property;
}
-QAnimationCallback *QChannelMapping::callback() const
-{
- Q_D(const QChannelMapping);
- return d->m_callback;
-}
-
void QChannelMapping::setChannelName(const QString &channelName)
{
Q_D(QChannelMapping);
@@ -200,56 +192,6 @@ void QChannelMapping::setProperty(const QString &property)
d->updatePropertyNameAndType();
}
-/*!
- Associates a \a callback object with this channel mapping.
-
- Such mappings do not have to have a target object and property name. When
- the \a callback object is set, every change in the animated value will lead
- to invoking the callback's
- \l{QAnimationCallback::onValueChanged()}{onValueChanged()} function either
- on the gui/main thread, or directly on one of the thread pool's worker
- thread. This is controlled by \a flags.
-
- \a type specifies the type (for example, QVariant::Vector3D,
- QVariant::Color, or QMetaType::Float) of the animated value. When animating
- node properties this does not need to be provided separately, however it
- becomes important to supply this when there is only a callback.
-
- \note A mapping can be associated both with a node property and a
- callback. It is important however that \a type matches the type of the
- property in this case. Note also that for properties of type QVariant (for
- example, QParameter::value), the \a type is the type of the value stored in
- the QVariant.
-
- \note The \a callback pointer is expected to stay valid while any
- associated animators are running.
- */
-void QChannelMapping::setCallback(int type, QAnimationCallback *callback, QAnimationCallback::Flags flags)
-{
- Q_D(QChannelMapping);
- if (d->m_type != type) {
- d->m_type = type;
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(id());
- e->setPropertyName("type");
- e->setValue(QVariant(d->m_type));
- notifyObservers(e);
- }
- if (d->m_callback != callback) {
- d->m_callback = callback;
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(id());
- e->setPropertyName("callback");
- e->setValue(QVariant::fromValue(static_cast<void *>(d->m_callback)));
- notifyObservers(e);
- }
- if (d->m_callbackFlags != flags) {
- d->m_callbackFlags = flags;
- auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(id());
- e->setPropertyName("callbackFlags");
- e->setValue(QVariant::fromValue(int(d->m_callbackFlags)));
- notifyObservers(e);
- }
-}
-
Qt3DCore::QNodeCreatedChangeBasePtr QChannelMapping::createNodeCreationChange() const
{
auto creationChange = QChannelMappingCreatedChangePtr<QChannelMappingData>::create(this);
@@ -260,8 +202,6 @@ Qt3DCore::QNodeCreatedChangeBasePtr QChannelMapping::createNodeCreationChange()
data.property = d->m_property;
data.type = d->m_type;
data.propertyName = d->m_propertyName;
- data.callback = d->m_callback;
- data.callbackFlags = d->m_callbackFlags;
return creationChange;
}
diff --git a/src/animation/frontend/qchannelmapping.h b/src/animation/frontend/qchannelmapping.h
index 08bda13aa..893b98e86 100644
--- a/src/animation/frontend/qchannelmapping.h
+++ b/src/animation/frontend/qchannelmapping.h
@@ -61,9 +61,6 @@ public:
QString channelName() const;
Qt3DCore::QNode *target() const;
QString property() const;
- QAnimationCallback *callback() const;
-
- void setCallback(int type, QAnimationCallback *callback, QAnimationCallback::Flags flags);
public Q_SLOTS:
void setChannelName(const QString &channelName);
diff --git a/src/animation/frontend/qchannelmapping_p.h b/src/animation/frontend/qchannelmapping_p.h
index b9f1f950c..b7de3b821 100644
--- a/src/animation/frontend/qchannelmapping_p.h
+++ b/src/animation/frontend/qchannelmapping_p.h
@@ -69,8 +69,6 @@ public:
QString m_property;
const char *m_propertyName;
int m_type;
- QAnimationCallback *m_callback;
- QAnimationCallback::Flags m_callbackFlags;
};
struct QChannelMappingData
@@ -80,8 +78,6 @@ struct QChannelMappingData
QString property;
int type;
const char *propertyName;
- QAnimationCallback *callback;
- QAnimationCallback::Flags callbackFlags;
};
} // namespace Qt3DAnimation
diff --git a/src/animation/frontend/qclipanimator.cpp b/src/animation/frontend/qclipanimator.cpp
index 79125a76e..6b503e87f 100644
--- a/src/animation/frontend/qclipanimator.cpp
+++ b/src/animation/frontend/qclipanimator.cpp
@@ -174,8 +174,9 @@ void QClipAnimator::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change)
QAnimationCallbackTriggerPtr callbackTrigger = qSharedPointerCast<Qt3DAnimation::QAnimationCallbackTrigger>(change);
if (callbackTrigger->callback())
callbackTrigger->callback()->valueChanged(callbackTrigger->value());
+ } else if (change->type() == Qt3DCore::PropertyUpdated) {
+ QAbstractClipAnimator::sceneChangeEvent(change);
}
- QAbstractClipAnimator::sceneChangeEvent(change);
}
} // namespace Qt3DAnimation
diff --git a/src/core/resources/qhandle_p.h b/src/core/resources/qhandle_p.h
index c4b53ec21..95483d197 100644
--- a/src/core/resources/qhandle_p.h
+++ b/src/core/resources/qhandle_p.h
@@ -53,9 +53,7 @@
#include <Qt3DCore/qt3dcore_global.h>
#include <QtCore/QDebug>
-#include <limits.h>
-
-class tst_Handle; // needed for friend class declaration below
+#include <QtCore/qhashfunctions.h>
QT_BEGIN_NAMESPACE
@@ -65,69 +63,72 @@ template <typename T, uint INDEXBITS = 16>
class QHandle
{
public:
+ struct Data {
+ union {
+ quintptr counter;
+ Data *nextFree;
+ };
+ };
QHandle()
- : m_handle(0)
+ : d(nullptr),
+ counter(0)
{}
-
-
- quint32 index() const { return d.m_index; }
- quint32 counter() const { return d.m_counter; }
- quint32 handle() const { return m_handle; }
- bool isNull() const { return !m_handle; }
-
- operator quint32() const { return m_handle; }
-
- static quint32 maxIndex() { return MaxIndex; }
- static quint32 maxCounter() { return MaxCounter; }
-
- QHandle(quint32 i, quint32 count)
+ QHandle(Data *d)
+ : d(d),
+ counter(d->counter)
+ {
+ }
+ QHandle(const QHandle &other)
+ : d(other.d),
+ counter(other.counter)
+ {
+ }
+ QHandle &operator=(const QHandle &other)
{
- d.m_index = i;
- d.m_counter = count;
- d.m_unused = 0;
- Q_ASSERT(i < MaxIndex);
- Q_ASSERT(count < MaxCounter);
+ d = other.d;
+ counter = other.counter;
+ return *this;
}
- enum {
- // Sizes to use for bit fields
- IndexBits = INDEXBITS,
- CounterBits = 32 - INDEXBITS - 2, // We use 2 bits for book-keeping in QHandleManager
+ inline T *operator->() const;
+ T *data() const;
- // Sizes to compare against for asserting dereferences
- MaxIndex = (1 << IndexBits) - 1,
- MaxCounter = ((1 << CounterBits) - 1 > SHRT_MAX) ? SHRT_MAX - 1 : (1 << CounterBits) - 1
- };
+ quintptr handle() const { return reinterpret_cast<quintptr>(d); }
+ bool isNull() const { return !d; }
+
+ Data *data_ptr() const { return d; }
+ bool operator==(const QHandle &other) const { return d == other.d && counter == other.counter; }
+ bool operator!=(const QHandle &other) const { return !operator==(other); }
private:
- struct Data {
- quint32 m_index : IndexBits;
- quint32 m_counter : CounterBits;
- quint32 m_unused : 2;
- };
- union {
- Data d;
- quint32 m_handle;
- };
+ Data *d;
+ quintptr counter;
};
+
template <typename T, uint INDEXBITS>
QDebug operator<<(QDebug dbg, const QHandle<T, INDEXBITS> &h)
{
QDebugStateSaver saver(dbg);
QString binNumber = QString::number(h.handle(), 2).rightJustified(32, QChar::fromLatin1('0'));
- dbg.nospace() << "index = " << h.index()
- << " magic/counter = " << h.counter()
- << " m_handle = " << h.handle()
+ dbg.nospace() << " m_handle = " << h.handle()
<< " = " << binNumber;
return dbg;
}
+template <typename T, uint INDEXBITS = 16>
+uint qHash(const QHandle<T, INDEXBITS> &h, uint seed)
+{
+ using QT_PREPEND_NAMESPACE(qHash);
+ return qHash(h.handle(), seed);
+}
+
} // Qt3DCore
+// simpler than fighting the Q_DECLARE_TYPEINFO macro, use QString as a dummy to get movable semantics
template <typename T, uint I>
-class QTypeInfo<Qt3DCore::QHandle<T,I> > // simpler than fighting the Q_DECLARE_TYPEINFO macro
- : public QTypeInfoMerger<Qt3DCore::QHandle<T,I>, quint32> {};
+class QTypeInfo<Qt3DCore::QHandle<T,I> >
+ : public QTypeInfoMerger<Qt3DCore::QHandle<T,I>, QString> {};
QT_END_NAMESPACE
diff --git a/src/core/resources/qresourcemanager_p.h b/src/core/resources/qresourcemanager_p.h
index 4cb2a38af..8f0440498 100644
--- a/src/core/resources/qresourcemanager_p.h
+++ b/src/core/resources/qresourcemanager_p.h
@@ -220,119 +220,114 @@ struct Int2Type
};
};
+template<typename T, uint INDEXBITS = 16>
+class QHandleData : public QHandle<T, INDEXBITS>::Data
+{
+public:
+ T data;
+};
+
+template<typename T, uint INDEXBITS>
+inline T *QHandle<T, INDEXBITS>::operator->() const { return (d && counter == d->counter) ? &static_cast<QHandleData<T, INDEXBITS> *>(d)->data : nullptr; }
+template<typename T, uint INDEXBITS>
+inline T *QHandle<T, INDEXBITS>::data() const { return (d && counter == d->counter) ? &static_cast<QHandleData<T, INDEXBITS> *>(d)->data : nullptr; }
+
template <typename T, uint INDEXBITS = 16>
class ArrayAllocatingPolicy
{
public:
+ typedef QHandleData<T, INDEXBITS> HandleData;
typedef QHandle<T, INDEXBITS> Handle;
ArrayAllocatingPolicy()
{
- m_freeList.resize(MaxSize);
- for (int i = 0; i < MaxSize; i++)
- m_freeList[i] = MaxSize - (i + 1);
}
~ArrayAllocatingPolicy()
{
+ m_activeHandles.clear();
deallocateBuckets();
}
Handle allocateResource()
{
- Q_ASSERT(!m_freeList.isEmpty());
- int idx = m_freeList.takeLast();
- int bucketIdx = idx / BucketSize;
- int localIdx = idx % BucketSize;
- Q_ASSERT(bucketIdx <= m_numBuckets);
- if (bucketIdx == m_numBuckets) {
- m_bucketDataPtrs[bucketIdx] = static_cast<T*>(malloc(sizeof(T) * BucketSize));
- m_counters[bucketIdx] = static_cast<short *>(malloc(sizeof(short) * BucketSize));
- // ### memset is only needed as long as we also use this for primitive types (see FrameGraphManager)
- // ### remove once this is fixed, add a static_assert on T instead
- memset((void *)m_bucketDataPtrs[bucketIdx], 0, sizeof(T) * BucketSize);
- memset(m_counters[bucketIdx], 0, sizeof(short) * BucketSize);
- ++m_numBuckets;
- }
-
- Q_ASSERT(idx <= m_numConstructed);
- if (idx == m_numConstructed) {
- new (m_bucketDataPtrs[bucketIdx] + localIdx) T;
- ++m_numConstructed;
- }
- Q_STATIC_ASSERT(Handle::MaxCounter < USHRT_MAX);
- Q_ASSERT(m_counters[bucketIdx][localIdx] <= 0);
- m_counters[bucketIdx][localIdx] *= -1;
- ++m_counters[bucketIdx][localIdx];
- if (m_counters[bucketIdx][localIdx] >= Handle::MaxCounter)
- m_counters[bucketIdx][localIdx] = 1;
-
- return Handle(idx, m_counters[bucketIdx][localIdx]);
+ if (!freeList)
+ allocateBucket();
+ typename Handle::Data *d = freeList;
+ freeList = freeList->nextFree;
+ d->counter = allocCounter;
+ allocCounter += 2; // ensure this will never clash with a pointer in nextFree by keeping the lowest bit set
+ Handle handle(d);
+ m_activeHandles.push_back(handle);
+ return handle;
}
- void releaseResource(Handle h)
+ void releaseResource(const Handle &handle)
{
- int idx = h.index();
- int bucketIdx = idx / BucketSize;
- int localIdx = idx % BucketSize;
-
- Q_ASSERT(h.counter() == static_cast<quint32>(m_counters[bucketIdx][localIdx]));
- T *r = m_bucketDataPtrs[bucketIdx] + localIdx;
-
- m_freeList.append(idx);
- m_counters[bucketIdx][localIdx] *= -1;
- performCleanup(r, Int2Type<QResourceInfo<T>::needsCleanup>());
+ m_activeHandles.removeOne(handle);
+ typename Handle::Data *d = handle.data_ptr();
+ d->nextFree = freeList;
+ freeList = d;
+ performCleanup(&static_cast<QHandleData<T, INDEXBITS> *>(d)->data, Int2Type<QResourceInfo<T>::needsCleanup>());
}
- T *data(Handle h/*, bool *ok = 0*/) {
- int bucketIdx = h.index() / BucketSize;
- int localIdx = h.index() % BucketSize;
-
- if (h.counter() != static_cast<quint32>(m_counters[bucketIdx][localIdx])) {
- return nullptr;
- }
- return m_bucketDataPtrs[bucketIdx] + localIdx;
+ T *data(Handle h) {
+ return h.operator->();
}
void for_each(std::function<void(T*)> f) {
- for (int idx = 0; idx < m_numConstructed; ++idx) {
- int bucketIdx = idx / BucketSize;
- int localIdx = idx % BucketSize;
- T * t = m_bucketDataPtrs[bucketIdx] + localIdx;
- f(t);
+ Bucket *b = firstBucket;
+ while (b) {
+ for (int idx = 0; idx < Bucket::NumEntries; ++idx) {
+ T *t = &b->data[idx].data;
+ f(t);
+ }
+ b = b->header.next;
}
}
+ int count() const { return m_activeHandles.size(); }
+ QVector<Handle> activeHandles() const { return m_activeHandles; }
+
private:
Q_DISABLE_COPY(ArrayAllocatingPolicy)
-
- enum {
- MaxSize = (1 << INDEXBITS),
- // use at most 1024 items per bucket, or put all items into a single
- // bucket if MaxSize is small enough
- BucketSize = (1 << (INDEXBITS < 10 ? INDEXBITS : 10))
+ struct Bucket {
+ struct Header {
+ Bucket *next;
+ } header;
+ enum {
+ Size = 4096,
+ NumEntries = (Size - sizeof(Header))/sizeof(HandleData)
+ };
+ HandleData data[NumEntries];
};
- void deallocateBuckets()
- {
- while (m_numConstructed > 0) {
- --m_numConstructed;
- int bucketIdx = m_numConstructed / BucketSize;
- int localIdx = m_numConstructed % BucketSize;
- (m_bucketDataPtrs[bucketIdx] + localIdx)->~T();
- }
+ Bucket *firstBucket = 0;
+ QVector<Handle > m_activeHandles;
+ typename Handle::Data *freeList = 0;
+ int allocCounter = 1;
+
+ void allocateBucket() {
+ // no free handle, allocate a new
+ Bucket *b = new Bucket;
- while (m_numBuckets > 0) {
- --m_numBuckets;
- free(m_bucketDataPtrs[m_numBuckets]);
- free(m_counters[m_numBuckets]);
+ b->header.next = firstBucket;
+ firstBucket = b;
+ for (int i = 0; i < Bucket::NumEntries - 1; ++i) {
+ b->data[i].nextFree = &b->data[i + 1];
}
+ b->data[Bucket::NumEntries - 1].nextFree = nullptr;
+ freeList = &b->data[0];
}
- T* m_bucketDataPtrs[MaxSize / BucketSize];
- short *m_counters[MaxSize / BucketSize];
- QVector<int> m_freeList;
- int m_numBuckets = 0;
- int m_numConstructed = 0;
+ void deallocateBuckets()
+ {
+ Bucket *b = firstBucket;
+ while (b) {
+ Bucket *n = b->header.next;
+ delete b;
+ b = n;
+ }
+ }
void performCleanup(T *r, Int2Type<true>)
{
@@ -379,21 +374,18 @@ public:
Handle acquire()
{
typename LockingPolicy<QResourceManager>::WriteLocker lock(this);
- Handle handle = Allocator::allocateResource();
- m_activeHandles.push_back(handle);
- return handle;
+ return Allocator::allocateResource();
}
ValueType* data(const Handle &handle)
{
- typename LockingPolicy<QResourceManager>::ReadLocker lock(this);
- return Allocator::data(handle);
+ return handle.operator->();
}
void release(const Handle &handle)
{
typename LockingPolicy<QResourceManager>::WriteLocker lock(this);
- releaseLocked(handle);
+ Allocator::releaseResource(handle);
}
bool contains(const KeyType &id) const
@@ -413,7 +405,6 @@ public:
Handle &handleToSet = m_keyToHandleMap[id];
if (handleToSet.isNull()) {
handleToSet = Allocator::allocateResource();
- m_activeHandles.push_back(handleToSet);
}
return handleToSet;
}
@@ -441,8 +432,7 @@ public:
ValueType *getOrCreateResource(const KeyType &id)
{
const Handle handle = getOrAcquireHandle(id);
- typename LockingPolicy<QResourceManager>::ReadLocker lock(this);
- return Allocator::data(handle);
+ return handle.operator->();
}
void releaseResource(const KeyType &id)
@@ -450,27 +440,16 @@ public:
typename LockingPolicy<QResourceManager>::WriteLocker lock(this);
Handle handle = m_keyToHandleMap.take(id);
if (!handle.isNull())
- releaseLocked(handle);
+ Allocator::releaseResource(handle);
}
int maximumSize() const { return m_maxSize; }
- int count() const Q_DECL_NOEXCEPT { return m_activeHandles.size(); }
-
- inline QVector<Handle > activeHandles() const Q_DECL_NOEXCEPT { return m_activeHandles; }
-
protected:
QHash<KeyType, Handle > m_keyToHandleMap;
- QVector<Handle > m_activeHandles;
const int m_maxSize;
private:
- void releaseLocked(const Handle &handle)
- {
- m_activeHandles.removeOne(handle);
- Allocator::releaseResource(handle);
- }
-
friend QDebug operator<< <>(QDebug dbg, const QResourceManager<ValueType, KeyType, INDEXBITS, LockingPolicy> &manager);
};
diff --git a/src/extras/defaults/defaults.pri b/src/extras/defaults/defaults.pri
index 4fe79e0d9..db4db24db 100644
--- a/src/extras/defaults/defaults.pri
+++ b/src/extras/defaults/defaults.pri
@@ -1,6 +1,8 @@
INCLUDEPATH += $$PWD
HEADERS += \
+ $$PWD/qdiffusespecularmaterial.h \
+ $$PWD/qdiffusespecularmaterial_p.h \
$$PWD/qphongmaterial.h \
$$PWD/qphongmaterial_p.h \
$$PWD/qdiffusemapmaterial_p.h \
@@ -47,6 +49,7 @@ HEADERS += \
$$PWD/qmorphphongmaterial_p.h
SOURCES += \
+ $$PWD/qdiffusespecularmaterial.cpp \
$$PWD/qphongmaterial.cpp \
$$PWD/qdiffusemapmaterial.cpp \
$$PWD/qnormaldiffusespecularmapmaterial.cpp \
diff --git a/src/extras/defaults/qdiffusemapmaterial.cpp b/src/extras/defaults/qdiffusemapmaterial.cpp
index 29e8586e3..26fb99c2c 100644
--- a/src/extras/defaults/qdiffusemapmaterial.cpp
+++ b/src/extras/defaults/qdiffusemapmaterial.cpp
@@ -201,6 +201,9 @@ void QDiffuseMapMaterialPrivate::handleTextureScaleChanged(const QVariant &var)
\since 5.7
\inherits Qt3DRender::QMaterial
+ \deprecated
+ \see Qt3DExtras::QDiffuseSpecularMaterial
+
The specular lighting effect is based on the combination of 3 lighting components ambient,
diffuse and specular. The relative strengths of these components are controlled by means of
their reflectivity coefficients which are modelled as RGB triplets:
diff --git a/src/extras/defaults/qdiffusespecularmapmaterial.cpp b/src/extras/defaults/qdiffusespecularmapmaterial.cpp
index cc5facd8c..727eaed27 100644
--- a/src/extras/defaults/qdiffusespecularmapmaterial.cpp
+++ b/src/extras/defaults/qdiffusespecularmapmaterial.cpp
@@ -208,6 +208,9 @@ void QDiffuseSpecularMapMaterialPrivate::handleTextureScaleChanged(const QVarian
\since 5.7
\inherits Qt3DRender::QMaterial
+ \deprecated
+ \see Qt3DExtras::QDiffuseSpecularMaterial
+
The specular lighting effect is based on the combination of 3 lighting components ambient,
diffuse and specular. The relative strengths of these components are controlled by means of
their reflectivity coefficients which are modelled as RGB triplets:
diff --git a/src/extras/defaults/qdiffusespecularmaterial.cpp b/src/extras/defaults/qdiffusespecularmaterial.cpp
new file mode 100644
index 000000000..83bba9e41
--- /dev/null
+++ b/src/extras/defaults/qdiffusespecularmaterial.cpp
@@ -0,0 +1,496 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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 "qdiffusespecularmaterial.h"
+#include "qdiffusespecularmaterial_p.h"
+
+#include <Qt3DRender/qfilterkey.h>
+#include <Qt3DRender/qmaterial.h>
+#include <Qt3DRender/qeffect.h>
+#include <Qt3DRender/qtechnique.h>
+#include <Qt3DRender/qtexture.h>
+#include <Qt3DRender/qshaderprogram.h>
+#include <Qt3DRender/qshaderprogrambuilder.h>
+#include <Qt3DRender/qparameter.h>
+#include <Qt3DRender/qrenderpass.h>
+#include <Qt3DRender/qgraphicsapifilter.h>
+#include <Qt3DRender/qblendequation.h>
+#include <Qt3DRender/qblendequationarguments.h>
+#include <Qt3DRender/qnodepthmask.h>
+#include <QtCore/QUrl>
+#include <QtGui/QVector3D>
+#include <QtGui/QVector4D>
+
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt3DRender;
+
+namespace Qt3DExtras {
+
+QDiffuseSpecularMaterialPrivate::QDiffuseSpecularMaterialPrivate()
+ : QMaterialPrivate()
+ , m_effect(new QEffect())
+ , m_ambientParameter(new QParameter(QStringLiteral("ka"), QColor::fromRgbF(0.05f, 0.05f, 0.05f, 1.0f)))
+ , m_diffuseParameter(new QParameter(QStringLiteral("kd"), QColor::fromRgbF(0.7f, 0.7f, 0.7f, 1.0f)))
+ , m_specularParameter(new QParameter(QStringLiteral("ks"), QColor::fromRgbF(0.01f, 0.01f, 0.01f, 1.0f)))
+ , m_diffuseTextureParameter(new QParameter(QStringLiteral("diffuseTexture"), QVariant()))
+ , m_specularTextureParameter(new QParameter(QStringLiteral("specularTexture"), QVariant()))
+ , m_shininessParameter(new QParameter(QStringLiteral("shininess"), 150.0f))
+ , m_normalTextureParameter(new QParameter(QStringLiteral("normalTexture"), QVariant()))
+ , m_textureScaleParameter(new QParameter(QStringLiteral("texCoordScale"), 1.0f))
+ , m_gl3Technique(new QTechnique())
+ , m_gl2Technique(new QTechnique())
+ , m_es2Technique(new QTechnique())
+ , m_gl3RenderPass(new QRenderPass())
+ , m_gl2RenderPass(new QRenderPass())
+ , m_es2RenderPass(new QRenderPass())
+ , m_gl3Shader(new QShaderProgram())
+ , m_gl3ShaderBuilder(new QShaderProgramBuilder())
+ , m_gl2es2Shader(new QShaderProgram())
+ , m_gl2es2ShaderBuilder(new QShaderProgramBuilder())
+ , m_noDepthMask(new QNoDepthMask())
+ , m_blendState(new QBlendEquationArguments())
+ , m_blendEquation(new QBlendEquation())
+ , m_filterKey(new QFilterKey)
+{
+}
+
+void QDiffuseSpecularMaterialPrivate::init()
+{
+ Q_Q(QDiffuseSpecularMaterial);
+
+ connect(m_ambientParameter, &Qt3DRender::QParameter::valueChanged,
+ this, &QDiffuseSpecularMaterialPrivate::handleAmbientChanged);
+ QObject::connect(m_diffuseParameter, &Qt3DRender::QParameter::valueChanged,
+ q, &QDiffuseSpecularMaterial::diffuseChanged);
+ QObject::connect(m_specularParameter, &Qt3DRender::QParameter::valueChanged,
+ q, &QDiffuseSpecularMaterial::specularChanged);
+ connect(m_shininessParameter, &Qt3DRender::QParameter::valueChanged,
+ this, &QDiffuseSpecularMaterialPrivate::handleShininessChanged);
+ QObject::connect(m_normalTextureParameter, &Qt3DRender::QParameter::valueChanged,
+ q, &QDiffuseSpecularMaterial::normalChanged);
+ connect(m_textureScaleParameter, &Qt3DRender::QParameter::valueChanged,
+ this, &QDiffuseSpecularMaterialPrivate::handleTextureScaleChanged);
+ QObject::connect(m_noDepthMask, &QNoDepthMask::enabledChanged,
+ q, &QDiffuseSpecularMaterial::alphaBlendingEnabledChanged);
+
+ m_gl3Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/default.vert"))));
+ m_gl3ShaderBuilder->setParent(q);
+ m_gl3ShaderBuilder->setShaderProgram(m_gl3Shader);
+ m_gl3ShaderBuilder->setFragmentShaderGraph(QUrl(QStringLiteral("qrc:/shaders/graphs/phong.frag.json")));
+ m_gl3ShaderBuilder->setEnabledLayers({QStringLiteral("diffuse"),
+ QStringLiteral("specular"),
+ QStringLiteral("normal")});
+
+ m_gl2es2Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/es2/default.vert"))));
+ m_gl2es2ShaderBuilder->setParent(q);
+ m_gl2es2ShaderBuilder->setShaderProgram(m_gl2es2Shader);
+ m_gl2es2ShaderBuilder->setFragmentShaderGraph(QUrl(QStringLiteral("qrc:/shaders/graphs/phong.frag.json")));
+ m_gl2es2ShaderBuilder->setEnabledLayers({QStringLiteral("diffuse"),
+ QStringLiteral("specular"),
+ QStringLiteral("normal")});
+
+
+ m_gl3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL);
+ m_gl3Technique->graphicsApiFilter()->setMajorVersion(3);
+ m_gl3Technique->graphicsApiFilter()->setMinorVersion(1);
+ m_gl3Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::CoreProfile);
+
+ m_gl2Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL);
+ m_gl2Technique->graphicsApiFilter()->setMajorVersion(2);
+ m_gl2Technique->graphicsApiFilter()->setMinorVersion(0);
+ m_gl2Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::NoProfile);
+
+ m_es2Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGLES);
+ m_es2Technique->graphicsApiFilter()->setMajorVersion(2);
+ m_es2Technique->graphicsApiFilter()->setMinorVersion(0);
+ m_es2Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::NoProfile);
+
+ m_noDepthMask->setEnabled(false);
+ m_blendState->setEnabled(false);
+ m_blendState->setSourceRgb(QBlendEquationArguments::SourceAlpha);
+ m_blendState->setDestinationRgb(QBlendEquationArguments::OneMinusSourceAlpha);
+ m_blendEquation->setEnabled(false);
+ m_blendEquation->setBlendFunction(QBlendEquation::Add);
+
+ m_gl3RenderPass->setShaderProgram(m_gl3Shader);
+ m_gl2RenderPass->setShaderProgram(m_gl2es2Shader);
+ m_es2RenderPass->setShaderProgram(m_gl2es2Shader);
+
+ m_gl3RenderPass->addRenderState(m_noDepthMask);
+ m_gl3RenderPass->addRenderState(m_blendState);
+ m_gl3RenderPass->addRenderState(m_blendEquation);
+
+ m_gl2RenderPass->addRenderState(m_noDepthMask);
+ m_gl2RenderPass->addRenderState(m_blendState);
+ m_gl2RenderPass->addRenderState(m_blendEquation);
+
+ m_es2RenderPass->addRenderState(m_noDepthMask);
+ m_es2RenderPass->addRenderState(m_blendState);
+ m_es2RenderPass->addRenderState(m_blendEquation);
+
+ m_gl3Technique->addRenderPass(m_gl3RenderPass);
+ m_gl2Technique->addRenderPass(m_gl2RenderPass);
+ m_es2Technique->addRenderPass(m_es2RenderPass);
+
+ m_filterKey->setParent(q);
+ m_filterKey->setName(QStringLiteral("renderingStyle"));
+ m_filterKey->setValue(QStringLiteral("forward"));
+
+ m_gl3Technique->addFilterKey(m_filterKey);
+ m_gl2Technique->addFilterKey(m_filterKey);
+ m_es2Technique->addFilterKey(m_filterKey);
+
+ m_effect->addTechnique(m_gl3Technique);
+ m_effect->addTechnique(m_gl2Technique);
+ m_effect->addTechnique(m_es2Technique);
+
+ m_effect->addParameter(m_ambientParameter);
+ m_effect->addParameter(m_diffuseParameter);
+ m_effect->addParameter(m_specularParameter);
+ m_effect->addParameter(m_shininessParameter);
+ m_effect->addParameter(m_textureScaleParameter);
+
+ q->setEffect(m_effect);
+}
+
+void QDiffuseSpecularMaterialPrivate::handleAmbientChanged(const QVariant &var)
+{
+ Q_Q(QDiffuseSpecularMaterial);
+ emit q->ambientChanged(var.value<QColor>());
+}
+
+void QDiffuseSpecularMaterialPrivate::handleShininessChanged(const QVariant &var)
+{
+ Q_Q(QDiffuseSpecularMaterial);
+ emit q->shininessChanged(var.toFloat());
+}
+
+void QDiffuseSpecularMaterialPrivate::handleTextureScaleChanged(const QVariant &var)
+{
+ Q_Q(QDiffuseSpecularMaterial);
+ emit q->textureScaleChanged(var.toFloat());
+}
+
+/*!
+ \class Qt3DExtras::QDiffuseSpecularMaterial
+ \brief The QDiffuseSpecularMaterial class provides a default implementation
+ of the phong lighting effect.
+ \inmodule Qt3DExtras
+ \since 5.10
+ \inherits Qt3DRender::QMaterial
+
+ The phong lighting effect is based on the combination of 3 lighting
+ components ambient, diffuse and specular. The relative strengths of these
+ components are controlled by means of their reflectivity coefficients which
+ are modelled as RGB triplets:
+
+ \list
+ \li Ambient is the color that is emitted by an object without any other
+ light source.
+ \li Diffuse is the color that is emitted for rought surface reflections
+ with the lights.
+ \li Specular is the color emitted for shiny surface reflections with the
+ lights.
+ \li The shininess of a surface is controlled by a float property.
+ \endlist
+
+ This material uses an effect with a single render pass approach and
+ performs per fragment lighting. Techniques are provided for OpenGL 2,
+ OpenGL 3 or above as well as OpenGL ES 2.
+*/
+/*!
+ \qmltype DiffuseSpecularMaterial
+ \brief The DiffuseSpecularMaterial class provides a default implementation
+ of the phong lighting effect.
+ \since 5.10
+ \inqmlmodule Qt3D.Extras
+ \instantiates Qt3DExtras::QDiffuseSpecularMaterial
+
+ The phong lighting effect is based on the combination of 3 lighting
+ components ambient, diffuse and specular. The relative strengths of these
+ components are controlled by means of their reflectivity coefficients which
+ are modelled as RGB triplets:
+
+ \list
+ \li Ambient is the color that is emitted by an object without any other
+ light source.
+ \li Diffuse is the color that is emitted for rought surface reflections
+ with the lights.
+ \li Specular is the color emitted for shiny surface reflections with the
+ lights.
+ \li The shininess of a surface is controlled by a float property.
+ \endlist
+
+ This material uses an effect with a single render pass approach and
+ performs per fragment lighting. Techniques are provided for OpenGL 2,
+ OpenGL 3 or above as well as OpenGL ES 2.
+ */
+
+/*!
+ Constructs a new QDiffuseSpecularMaterial instance with parent object \a parent.
+*/
+QDiffuseSpecularMaterial::QDiffuseSpecularMaterial(QNode *parent)
+ : QMaterial(*new QDiffuseSpecularMaterialPrivate, parent)
+{
+ Q_D(QDiffuseSpecularMaterial);
+ d->init();
+}
+
+/*!
+ Destroys the QDiffuseSpecularMaterial.
+*/
+QDiffuseSpecularMaterial::~QDiffuseSpecularMaterial()
+{
+}
+
+/*!
+ \property QDiffuseSpecularMaterial::ambient
+
+ Holds the ambient color.
+*/
+/*!
+ \qmlproperty color DiffuseSpecularMaterial::ambient
+
+ Holds the ambient color.
+*/
+QColor QDiffuseSpecularMaterial::ambient() const
+{
+ Q_D(const QDiffuseSpecularMaterial);
+ return d->m_ambientParameter->value().value<QColor>();
+}
+
+/*!
+ \property QDiffuseSpecularMaterial::diffuse
+
+ Holds the diffuse color of the material. This can be either a plain color
+ value or a texture.
+*/
+/*!
+ \qmlproperty var DiffuseSpecularMaterial::diffuse
+
+ Holds the diffuse color of the material. This can be either a plain color
+ value or a texture.
+*/
+QVariant QDiffuseSpecularMaterial::diffuse() const
+{
+ Q_D(const QDiffuseSpecularMaterial);
+ return d->m_diffuseParameter->value();
+}
+
+/*!
+ \property QDiffuseSpecularMaterial::specular
+
+ Holds the specular color of the material. This can be either a plain color
+ value or a texture.
+*/
+/*!
+ \qmlproperty var DiffuseSpecularMaterial::specular
+
+ Holds the specular color of the material. This can be either a plain color
+ value or a texture.
+*/
+QVariant QDiffuseSpecularMaterial::specular() const
+{
+ Q_D(const QDiffuseSpecularMaterial);
+ return d->m_specularParameter->value();
+}
+
+/*!
+ \property QDiffuseSpecularMaterial::shininess
+
+ Holds the shininess exponent.
+*/
+/*!
+ \qmlproperty real DiffuseSpecularMaterial::shininess
+
+ Holds the shininess exponent.
+*/
+float QDiffuseSpecularMaterial::shininess() const
+{
+ Q_D(const QDiffuseSpecularMaterial);
+ return d->m_shininessParameter->value().toFloat();
+}
+
+/*!
+ \property QDiffuseSpecularMaterial::normal
+
+ Holds the current normal map texture of the material. This can only be a
+ texture, otherwise it is ignored. By default this map is not set.
+*/
+/*!
+ \qmlproperty var DiffuseSpecularMaterial::normal
+
+ Holds the current normal map texture of the material. This can only be a
+ texture, otherwise it is ignored. By default this map is not set.
+*/
+QVariant QDiffuseSpecularMaterial::normal() const
+{
+ Q_D(const QDiffuseSpecularMaterial);
+ return d->m_normalTextureParameter->value();
+}
+
+/*!
+ \property QDiffuseSpecularMaterial::textureScale
+
+ Holds the current texture scale. It is applied as a multiplier to texture
+ coordinates at render time. Defaults to 1.0.
+*/
+/*!
+ \qmlproperty real DiffuseSpecularMaterial::textureScale
+
+ Holds the current texture scale. It is applied as a multiplier to texture
+ coordinates at render time. Defaults to 1.0.
+*/
+float QDiffuseSpecularMaterial::textureScale() const
+{
+ Q_D(const QDiffuseSpecularMaterial);
+ return d->m_textureScaleParameter->value().toFloat();
+}
+
+/*!
+ \property QDiffuseSpecularMaterial::alphaBlending
+
+ Indicates if the alpha information coming from the diffuse property will
+ be taken into account during rendering. Defaults to false.
+*/
+/*!
+ \qmlproperty bool DiffuseSpecularMaterial::alphaBlending
+
+ Indicates if the alpha information coming from the diffuse property will
+ be taken into account during rendering. Defaults to false.
+*/
+bool QDiffuseSpecularMaterial::isAlphaBlendingEnabled() const
+{
+ Q_D(const QDiffuseSpecularMaterial);
+ return d->m_noDepthMask->isEnabled();
+}
+
+void QDiffuseSpecularMaterial::setAmbient(const QColor &ambient)
+{
+ Q_D(QDiffuseSpecularMaterial);
+ d->m_ambientParameter->setValue(ambient);
+}
+
+void QDiffuseSpecularMaterial::setDiffuse(const QVariant &diffuse)
+{
+ Q_D(QDiffuseSpecularMaterial);
+ d->m_diffuseParameter->setValue(diffuse);
+ d->m_diffuseTextureParameter->setValue(diffuse);
+
+ auto layers = d->m_gl3ShaderBuilder->enabledLayers();
+ if (diffuse.value<QAbstractTexture *>()) {
+ layers.removeAll(QStringLiteral("diffuse"));
+ layers.append(QStringLiteral("diffuseTexture"));
+ d->m_effect->addParameter(d->m_diffuseTextureParameter);
+ d->m_effect->removeParameter(d->m_diffuseParameter);
+ } else {
+ layers.removeAll(QStringLiteral("diffuseTexture"));
+ layers.append(QStringLiteral("diffuse"));
+ d->m_effect->removeParameter(d->m_diffuseTextureParameter);
+ d->m_effect->addParameter(d->m_diffuseParameter);
+ }
+ d->m_gl3ShaderBuilder->setEnabledLayers(layers);
+ d->m_gl2es2ShaderBuilder->setEnabledLayers(layers);
+}
+
+void QDiffuseSpecularMaterial::setSpecular(const QVariant &specular)
+{
+ Q_D(QDiffuseSpecularMaterial);
+ d->m_specularParameter->setValue(specular);
+ d->m_specularTextureParameter->setValue(specular);
+
+ auto layers = d->m_gl3ShaderBuilder->enabledLayers();
+ if (specular.value<QAbstractTexture *>()) {
+ layers.removeAll(QStringLiteral("specular"));
+ layers.append(QStringLiteral("specularTexture"));
+ d->m_effect->addParameter(d->m_specularTextureParameter);
+ d->m_effect->removeParameter(d->m_specularParameter);
+ } else {
+ layers.removeAll(QStringLiteral("specularTexture"));
+ layers.append(QStringLiteral("specular"));
+ d->m_effect->removeParameter(d->m_specularTextureParameter);
+ d->m_effect->addParameter(d->m_specularParameter);
+ }
+ d->m_gl3ShaderBuilder->setEnabledLayers(layers);
+ d->m_gl2es2ShaderBuilder->setEnabledLayers(layers);
+}
+
+void QDiffuseSpecularMaterial::setShininess(float shininess)
+{
+ Q_D(QDiffuseSpecularMaterial);
+ d->m_shininessParameter->setValue(shininess);
+}
+
+void QDiffuseSpecularMaterial::setNormal(const QVariant &normal)
+{
+ Q_D(QDiffuseSpecularMaterial);
+ d->m_normalTextureParameter->setValue(normal);
+
+ auto layers = d->m_gl3ShaderBuilder->enabledLayers();
+ if (normal.value<QAbstractTexture *>()) {
+ layers.removeAll(QStringLiteral("normal"));
+ layers.append(QStringLiteral("normalTexture"));
+ d->m_effect->addParameter(d->m_normalTextureParameter);
+ } else {
+ layers.removeAll(QStringLiteral("normalTexture"));
+ layers.append(QStringLiteral("normal"));
+ d->m_effect->removeParameter(d->m_normalTextureParameter);
+ }
+ d->m_gl3ShaderBuilder->setEnabledLayers(layers);
+}
+
+void QDiffuseSpecularMaterial::setTextureScale(float textureScale)
+{
+ Q_D(QDiffuseSpecularMaterial);
+ d->m_textureScaleParameter->setValue(textureScale);
+}
+
+void QDiffuseSpecularMaterial::setAlphaBlendingEnabled(bool enabled)
+{
+ Q_D(QDiffuseSpecularMaterial);
+ d->m_noDepthMask->setEnabled(enabled);
+ d->m_blendState->setEnabled(enabled);
+ d->m_blendEquation->setEnabled(enabled);
+}
+
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
diff --git a/src/extras/defaults/qdiffusespecularmaterial.h b/src/extras/defaults/qdiffusespecularmaterial.h
new file mode 100644
index 000000000..5f21da093
--- /dev/null
+++ b/src/extras/defaults/qdiffusespecularmaterial.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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 QT3DEXTRAS_QDIFFUSESPECULARMATERIAL_H
+#define QT3DEXTRAS_QDIFFUSESPECULARMATERIAL_H
+
+#include <Qt3DExtras/qt3dextras_global.h>
+#include <Qt3DRender/qmaterial.h>
+#include <QtGui/QColor>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DExtras {
+
+class QDiffuseSpecularMaterialPrivate;
+
+class QT3DEXTRASSHARED_EXPORT QDiffuseSpecularMaterial : public Qt3DRender::QMaterial
+{
+ Q_OBJECT
+ Q_PROPERTY(QColor ambient READ ambient WRITE setAmbient NOTIFY ambientChanged)
+ Q_PROPERTY(QVariant diffuse READ diffuse WRITE setDiffuse NOTIFY diffuseChanged)
+ Q_PROPERTY(QVariant specular READ specular WRITE setSpecular NOTIFY specularChanged)
+ Q_PROPERTY(float shininess READ shininess WRITE setShininess NOTIFY shininessChanged)
+ Q_PROPERTY(QVariant normal READ normal WRITE setNormal NOTIFY normalChanged)
+ Q_PROPERTY(float textureScale READ textureScale WRITE setTextureScale NOTIFY textureScaleChanged)
+ Q_PROPERTY(bool alphaBlending READ isAlphaBlendingEnabled WRITE setAlphaBlendingEnabled NOTIFY alphaBlendingEnabledChanged)
+
+public:
+ explicit QDiffuseSpecularMaterial(Qt3DCore::QNode *parent = nullptr);
+ ~QDiffuseSpecularMaterial();
+
+ QColor ambient() const;
+ QVariant diffuse() const;
+ QVariant specular() const;
+ float shininess() const;
+ QVariant normal() const;
+ float textureScale() const;
+ bool isAlphaBlendingEnabled() const;
+
+public Q_SLOTS:
+ void setAmbient(const QColor &ambient);
+ void setDiffuse(const QVariant &diffuse);
+ void setSpecular(const QVariant &specular);
+ void setShininess(float shininess);
+ void setNormal(const QVariant &normal);
+ void setTextureScale(float textureScale);
+ void setAlphaBlendingEnabled(bool enabled);
+
+Q_SIGNALS:
+ void ambientChanged(const QColor &ambient);
+ void diffuseChanged(const QVariant &diffuse);
+ void specularChanged(const QVariant &specular);
+ void shininessChanged(float shininess);
+ void normalChanged(const QVariant &normal);
+ void textureScaleChanged(float textureScale);
+ void alphaBlendingEnabledChanged(bool enabled);
+
+private:
+ Q_DECLARE_PRIVATE(QDiffuseSpecularMaterial)
+};
+
+} // namespace Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QDIFFUSESPECULARMATERIAL_H
diff --git a/src/extras/defaults/qdiffusespecularmaterial_p.h b/src/extras/defaults/qdiffusespecularmaterial_p.h
new file mode 100644
index 000000000..2b0b2184f
--- /dev/null
+++ b/src/extras/defaults/qdiffusespecularmaterial_p.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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 QT3DEXTRAS_QDIFFUSESPECULARMATERIAL_P_H
+#define QT3DEXTRAS_QDIFFUSESPECULARMATERIAL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DRender/private/qmaterial_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+class QFilterKey;
+class QEffect;
+class QTechnique;
+class QParameter;
+class QShaderProgram;
+class QShaderProgramBuilder;
+class QRenderPass;
+class QNoDepthMask;
+class QBlendEquationArguments;
+class QBlendEquation;
+
+} // namespace Qt3DRender
+
+namespace Qt3DExtras {
+
+class QDiffuseSpecularMaterial;
+
+class QDiffuseSpecularMaterialPrivate : public Qt3DRender::QMaterialPrivate
+{
+public:
+ QDiffuseSpecularMaterialPrivate();
+
+ void init();
+
+ void handleAmbientChanged(const QVariant &var);
+ void handleShininessChanged(const QVariant &var);
+ void handleTextureScaleChanged(const QVariant &var);
+
+ Qt3DRender::QEffect *m_effect;
+ Qt3DRender::QParameter *m_ambientParameter;
+ Qt3DRender::QParameter *m_diffuseParameter;
+ Qt3DRender::QParameter *m_specularParameter;
+ Qt3DRender::QParameter *m_diffuseTextureParameter;
+ Qt3DRender::QParameter *m_specularTextureParameter;
+ Qt3DRender::QParameter *m_shininessParameter;
+ Qt3DRender::QParameter *m_normalTextureParameter;
+ Qt3DRender::QParameter *m_textureScaleParameter;
+ Qt3DRender::QTechnique *m_gl3Technique;
+ Qt3DRender::QTechnique *m_gl2Technique;
+ Qt3DRender::QTechnique *m_es2Technique;
+ Qt3DRender::QRenderPass *m_gl3RenderPass;
+ Qt3DRender::QRenderPass *m_gl2RenderPass;
+ Qt3DRender::QRenderPass *m_es2RenderPass;
+ Qt3DRender::QShaderProgram *m_gl3Shader;
+ Qt3DRender::QShaderProgramBuilder *m_gl3ShaderBuilder;
+ Qt3DRender::QShaderProgram *m_gl2es2Shader;
+ Qt3DRender::QShaderProgramBuilder *m_gl2es2ShaderBuilder;
+ Qt3DRender::QNoDepthMask *m_noDepthMask;
+ Qt3DRender::QBlendEquationArguments *m_blendState;
+ Qt3DRender::QBlendEquation *m_blendEquation;
+ Qt3DRender::QFilterKey *m_filterKey;
+
+ Q_DECLARE_PUBLIC(QDiffuseSpecularMaterial)
+};
+
+} // Qt3DExtras
+
+QT_END_NAMESPACE
+
+#endif // QT3DEXTRAS_QDIFFUSESPECULARMATERIAL_P_H
+
diff --git a/src/extras/defaults/qnormaldiffusemapalphamaterial.cpp b/src/extras/defaults/qnormaldiffusemapalphamaterial.cpp
index c276c9717..9b2a64520 100644
--- a/src/extras/defaults/qnormaldiffusemapalphamaterial.cpp
+++ b/src/extras/defaults/qnormaldiffusemapalphamaterial.cpp
@@ -165,6 +165,9 @@ void QNormalDiffuseMapAlphaMaterialPrivate::init()
\since 5.7
\inherits Qt3DExtras::QNormalDiffuseMapMaterial
+ \deprecated
+ \see Qt3DExtras::QDiffuseSpecularMaterial
+
The specular lighting effect is based on the combination of 3 lighting components ambient,
diffuse and specular. The relative strengths of these components are controlled by means of
their reflectivity coefficients which are modelled as RGB triplets:
diff --git a/src/extras/defaults/qnormaldiffusemapmaterial.cpp b/src/extras/defaults/qnormaldiffusemapmaterial.cpp
index 687e59751..beed4085e 100644
--- a/src/extras/defaults/qnormaldiffusemapmaterial.cpp
+++ b/src/extras/defaults/qnormaldiffusemapmaterial.cpp
@@ -218,6 +218,9 @@ void QNormalDiffuseMapMaterialPrivate::handleTextureScaleChanged(const QVariant
\since 5.7
\inherits Qt3DRender::QMaterial
+ \deprecated
+ \see Qt3DExtras::QDiffuseSpecularMaterial
+
The specular lighting effect is based on the combination of 3 lighting components ambient,
diffuse and specular. The relative strengths of these components are controlled by means of
their reflectivity coefficients which are modelled as RGB triplets:
diff --git a/src/extras/defaults/qnormaldiffusespecularmapmaterial.cpp b/src/extras/defaults/qnormaldiffusespecularmapmaterial.cpp
index 7665c07a7..028fd14e7 100644
--- a/src/extras/defaults/qnormaldiffusespecularmapmaterial.cpp
+++ b/src/extras/defaults/qnormaldiffusespecularmapmaterial.cpp
@@ -226,6 +226,9 @@ void QNormalDiffuseSpecularMapMaterialPrivate::handleTextureScaleChanged(const Q
\since 5.7
\inherits Qt3DRender::QMaterial
+ \deprecated
+ \see Qt3DExtras::QDiffuseSpecularMaterial
+
The specular lighting effect is based on the combination of 3 lighting components ambient,
diffuse and specular. The relative strengths of these components are controlled by means of
their reflectivity coefficients which are modelled as RGB triplets:
diff --git a/src/extras/defaults/qphongalphamaterial.cpp b/src/extras/defaults/qphongalphamaterial.cpp
index fb0871ee4..24cff94e9 100644
--- a/src/extras/defaults/qphongalphamaterial.cpp
+++ b/src/extras/defaults/qphongalphamaterial.cpp
@@ -209,6 +209,9 @@ void QPhongAlphaMaterialPrivate::handleShininessChanged(const QVariant &var)
\since 5.7
\inherits Qt3DRender::QMaterial
+ \deprecated
+ \see Qt3DExtras::QDiffuseSpecularMaterial
+
The phong lighting effect is based on the combination of 3 lighting components ambient, diffuse
and specular. The relative strengths of these components are controlled by means of their
reflectivity coefficients which are modelled as RGB triplets:
diff --git a/src/extras/defaults/qphongmaterial.cpp b/src/extras/defaults/qphongmaterial.cpp
index c76e3a6ef..17d837568 100644
--- a/src/extras/defaults/qphongmaterial.cpp
+++ b/src/extras/defaults/qphongmaterial.cpp
@@ -184,6 +184,9 @@ void QPhongMaterialPrivate::handleShininessChanged(const QVariant &var)
\since 5.7
\inherits Qt3DRender::QMaterial
+ \deprecated
+ \see Qt3DExtras::QDiffuseSpecularMaterial
+
The phong lighting effect is based on the combination of 3 lighting components ambient, diffuse
and specular. The relative strengths of these components are controlled by means of their
reflectivity coefficients which are modelled as RGB triplets:
diff --git a/src/plugins/geometryloaders/default/objgeometryloader.cpp b/src/plugins/geometryloaders/default/objgeometryloader.cpp
index 7184e2f69..6ebe91a09 100644
--- a/src/plugins/geometryloaders/default/objgeometryloader.cpp
+++ b/src/plugins/geometryloaders/default/objgeometryloader.cpp
@@ -102,6 +102,10 @@ bool ObjGeometryLoader::doLoad(QIODevice *ioDev, const QString &subMesh)
if (lineSize > 0 && line[0] != '#') {
if (line[lineSize - 1] == '\n')
--lineSize; // chop newline
+ if (line[lineSize - 1] == '\r')
+ --lineSize; // chop newline also for CRLF format
+ while (line[lineSize - 1] == ' ' || line[lineSize - 1] == '\t')
+ --lineSize; // chop trailing spaces
const ByteArraySplitter tokens(line, line + lineSize, ' ', QString::SkipEmptyParts);
diff --git a/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp b/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp
index 61d27444a..e893696ec 100644
--- a/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp
+++ b/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp
@@ -53,6 +53,7 @@
#include <Qt3DExtras/qforwardrenderer.h>
#include <Qt3DExtras/qgoochmaterial.h>
#include <Qt3DExtras/qmetalroughmaterial.h>
+#include <Qt3DExtras/qdiffusespecularmaterial.h>
#include <Qt3DExtras/qmorphphongmaterial.h>
#include <Qt3DExtras/qnormaldiffusemapalphamaterial.h>
#include <Qt3DExtras/qnormaldiffusemapmaterial.h>
@@ -108,6 +109,7 @@ void Qt3DQuick3DExtrasPlugin::registerTypes(const char *uri)
qmlRegisterType<Qt3DExtras::QGoochMaterial>(uri, 2, 0, "GoochMaterial");
qmlRegisterType<Qt3DExtras::QTextureMaterial>(uri, 2, 0, "TextureMaterial");
qmlRegisterRevision<Qt3DExtras::QTextureMaterial, 10>(uri, 2, 10);
+ qmlRegisterType<Qt3DExtras::QDiffuseSpecularMaterial>(uri, 2, 10, "DiffuseSpecularMaterial");
qmlRegisterType<Qt3DExtras::QMetalRoughMaterial>(uri, 2, 9, "MetalRoughMaterial");
qmlRegisterRevision<Qt3DExtras::QMetalRoughMaterial, 10>(uri, 2, 10);
qmlRegisterType<Qt3DExtras::QTexturedMetalRoughMaterial>(uri, 2, 9, "TexturedMetalRoughMaterial");
diff --git a/src/render/backend/abstractrenderer_p.h b/src/render/backend/abstractrenderer_p.h
index c1c1f7032..4d80ec87d 100644
--- a/src/render/backend/abstractrenderer_p.h
+++ b/src/render/backend/abstractrenderer_p.h
@@ -107,6 +107,7 @@ public:
ShadersDirty = 1 << 9,
SkeletonDataDirty = 1 << 10,
JointDirty = 1 << 11,
+ LayersDirty = 1 << 12,
AllDirty = 0xffffff
};
Q_DECLARE_FLAGS(BackendNodeDirtySet, BackendNodeDirtyFlag)
diff --git a/src/render/backend/attachmentpack.cpp b/src/render/backend/attachmentpack.cpp
index 6dee7587b..9a08fdde4 100644
--- a/src/render/backend/attachmentpack.cpp
+++ b/src/render/backend/attachmentpack.cpp
@@ -67,11 +67,13 @@ AttachmentPack::AttachmentPack(const RenderTargetSelector *selector, const Rende
// If nothing is specified, use all the attachments as draw buffers
if (selectedAttachmentPoints.isEmpty()) {
+ m_drawBuffers.reserve(m_attachments.size());
for (const Attachment &attachment : qAsConst(m_attachments))
// only consider Color Attachments
if (attachment.m_point <= QRenderTargetOutput::Color15)
m_drawBuffers.push_back((int) attachment.m_point);
} else {
+ m_drawBuffers.reserve(selectedAttachmentPoints.size());
for (QRenderTargetOutput::AttachmentPoint drawBuffer : selectedAttachmentPoints)
if (drawBuffer <= QRenderTargetOutput::Color15)
m_drawBuffers.push_back((int) drawBuffer);
diff --git a/src/render/backend/layer.cpp b/src/render/backend/layer.cpp
index 6f50d071d..976c35fd5 100644
--- a/src/render/backend/layer.cpp
+++ b/src/render/backend/layer.cpp
@@ -74,8 +74,10 @@ void Layer::sceneChangeEvent(const QSceneChangePtr &e)
QByteArray propertyName = propertyChange->propertyName();
if (propertyName == QByteArrayLiteral("recursive")) {
m_recursive = propertyChange->value().toBool();
+ markDirty(AbstractRenderer::LayersDirty);
}
- markDirty(AbstractRenderer::AllDirty);
+ if (propertyName == QByteArrayLiteral("enabled"))
+ markDirty(AbstractRenderer::LayersDirty);
}
BackendNode::sceneChangeEvent(e);
}
diff --git a/src/render/backend/layer_p.h b/src/render/backend/layer_p.h
index 2ba3532d2..d01d190e9 100644
--- a/src/render/backend/layer_p.h
+++ b/src/render/backend/layer_p.h
@@ -77,7 +77,7 @@ public:
void setRecursive(bool recursive);
protected:
- void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e);
+ void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
private:
void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change);
diff --git a/src/render/backend/render-backend.pri b/src/render/backend/render-backend.pri
index 1d18c8efe..f7f30b5c9 100644
--- a/src/render/backend/render-backend.pri
+++ b/src/render/backend/render-backend.pri
@@ -44,7 +44,8 @@ HEADERS += \
$$PWD/commandthread_p.h \
$$PWD/visitorutils_p.h \
$$PWD/segmentsvisitor_p.h \
- $$PWD/pointsvisitor_p.h
+ $$PWD/pointsvisitor_p.h \
+ $$PWD/renderercache_p.h
SOURCES += \
$$PWD/renderthread.cpp \
diff --git a/src/render/backend/renderer.cpp b/src/render/backend/renderer.cpp
index eb64677c1..7830faaa9 100644
--- a/src/render/backend/renderer.cpp
+++ b/src/render/backend/renderer.cpp
@@ -1484,25 +1484,28 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs()
m_updateLevelOfDetailJob->setFrameGraphRoot(frameGraphRoot());
+ BackendNodeDirtySet changesToUnset = dirtyBits();
+
// Add jobs
- if (dirtyBits() & AbstractRenderer::EntityEnabledDirty) {
+ const bool entitiesEnabledDirty = changesToUnset & AbstractRenderer::EntityEnabledDirty;
+ if (entitiesEnabledDirty) {
renderBinJobs.push_back(m_updateTreeEnabledJob);
m_calculateBoundingVolumeJob->addDependency(m_updateTreeEnabledJob);
}
- if (dirtyBits() & AbstractRenderer::TransformDirty) {
+ if (changesToUnset & AbstractRenderer::TransformDirty) {
renderBinJobs.push_back(m_worldTransformJob);
renderBinJobs.push_back(m_updateWorldBoundingVolumeJob);
renderBinJobs.push_back(m_updateShaderDataTransformJob);
}
- if (dirtyBits() & AbstractRenderer::GeometryDirty) {
+ if (changesToUnset & AbstractRenderer::GeometryDirty) {
renderBinJobs.push_back(m_calculateBoundingVolumeJob);
renderBinJobs.push_back(m_updateMeshTriangleListJob);
}
- if (dirtyBits() & AbstractRenderer::GeometryDirty ||
- dirtyBits() & AbstractRenderer::TransformDirty) {
+ if (changesToUnset & AbstractRenderer::GeometryDirty ||
+ changesToUnset & AbstractRenderer::TransformDirty) {
renderBinJobs.push_back(m_expandBoundingVolumeJob);
}
@@ -1518,17 +1521,24 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs()
// Jobs to prepare GL Resource upload
renderBinJobs.push_back(m_vaoGathererJob);
- if (dirtyBits() & AbstractRenderer::BuffersDirty)
+ if (changesToUnset & AbstractRenderer::BuffersDirty)
renderBinJobs.push_back(m_bufferGathererJob);
- if (dirtyBits() & AbstractRenderer::ShadersDirty)
+ if (changesToUnset & AbstractRenderer::ShadersDirty)
renderBinJobs.push_back(m_shaderGathererJob);
- if (dirtyBits() & AbstractRenderer::TexturesDirty) {
+ if (changesToUnset & AbstractRenderer::TexturesDirty) {
renderBinJobs.push_back(m_syncTextureLoadingJob);
renderBinJobs.push_back(m_textureGathererJob);
}
+
+ // Layer cache is dependent on layers, layer filters and the enabled flag
+ // on entities
+ const bool layersDirty = changesToUnset & AbstractRenderer::LayersDirty;
+ const bool layersCacheNeedsToBeRebuilt = layersDirty || entitiesEnabledDirty;
+ bool layersCacheRebuilt = false;
+
QMutexLocker lock(m_renderQueue->mutex());
if (m_renderQueue->wasReset()) { // Have we rendered yet? (Scene3D case)
// Traverse the current framegraph. For each leaf node create a
@@ -1539,18 +1549,33 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs()
FrameGraphVisitor visitor(m_nodesManager->frameGraphManager());
const QVector<FrameGraphNode *> fgLeaves = visitor.traverse(frameGraphRoot());
+ // Remove leaf nodes that no longer exist from cache
+ const QList<FrameGraphNode *> keys = m_cache.leafNodeCache.keys();
+ for (FrameGraphNode *leafNode : keys) {
+ if (!fgLeaves.contains(leafNode))
+ m_cache.leafNodeCache.remove(leafNode);
+ }
+
const int fgBranchCount = fgLeaves.size();
for (int i = 0; i < fgBranchCount; ++i) {
RenderViewBuilder builder(fgLeaves.at(i), i, this);
+ builder.setLayerCacheNeedsToBeRebuilt(layersCacheNeedsToBeRebuilt);
+ builder.prepareJobs();
renderBinJobs.append(builder.buildJobHierachy());
}
+ layersCacheRebuilt = true;
// Set target number of RenderViews
m_renderQueue->setTargetRenderViewCount(fgBranchCount);
}
+ // Only reset LayersDirty flag once we have really rebuilt the caches
+ if (layersDirty && !layersCacheRebuilt)
+ changesToUnset.setFlag(AbstractRenderer::LayersDirty, false);
+ if (entitiesEnabledDirty && !layersCacheRebuilt)
+ changesToUnset.setFlag(AbstractRenderer::EntityEnabledDirty, false);
+
// Clear dirty bits
- BackendNodeDirtySet changesToUnset = dirtyBits();
// TO DO: When secondary GL thread is integrated, the following line can be removed
changesToUnset.setFlag(AbstractRenderer::ShadersDirty, false);
diff --git a/src/render/backend/renderer_p.h b/src/render/backend/renderer_p.h
index 3cf99ec81..28e8711a8 100644
--- a/src/render/backend/renderer_p.h
+++ b/src/render/backend/renderer_p.h
@@ -76,6 +76,7 @@
#include <Qt3DRender/private/updatemeshtrianglelistjob_p.h>
#include <Qt3DRender/private/filtercompatibletechniquejob_p.h>
#include <Qt3DRender/private/updateskinningpalettejob_p.h>
+#include <Qt3DRender/private/renderercache_p.h>
#include <QHash>
#include <QMatrix4x4>
@@ -266,6 +267,8 @@ public:
ViewSubmissionResultData submitRenderViews(const QVector<Render::RenderView *> &renderViews);
+ RendererCache *cache() { return &m_cache; }
+
#ifdef QT3D_RENDER_UNIT_TESTS
public:
#else
@@ -368,6 +371,7 @@ private:
#endif
QMetaObject::Connection m_contextConnection;
+ RendererCache m_cache;
};
} // namespace Render
diff --git a/src/render/backend/renderercache_p.h b/src/render/backend/renderercache_p.h
new file mode 100644
index 000000000..f14b965ee
--- /dev/null
+++ b/src/render/backend/renderercache_p.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** 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_RENDER_RENDERERCACHE_P_H
+#define QT3DRENDER_RENDER_RENDERERCACHE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <Qt3DRender/QFrameGraphNode>
+
+#include <Qt3DRender/private/entity_p.h>
+#include <Qt3DRender/private/renderviewjobutils_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Render {
+
+struct RendererCache
+{
+ struct LeafNodeData
+ {
+ QVector<Entity *> filterEntitiesByLayer;
+ };
+
+ QHash<FrameGraphNode *, LeafNodeData> leafNodeCache;
+
+ QMutex *mutex() { return &m_mutex; }
+
+private:
+ QMutex m_mutex;
+};
+
+} // namespace Render
+
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_RENDER_RENDERERCACHE_P_H
diff --git a/src/render/backend/renderview.cpp b/src/render/backend/renderview.cpp
index 572cda229..dbb6ead21 100644
--- a/src/render/backend/renderview.cpp
+++ b/src/render/backend/renderview.cpp
@@ -394,7 +394,7 @@ void sortByMaterial(QVector<RenderCommand *> &commands, int begin, const int end
while (begin != end) {
if (begin + 1 < rangeEnd) {
std::stable_sort(commands.begin() + begin + 1, commands.begin() + rangeEnd, [] (RenderCommand *a, RenderCommand *b){
- return a->m_material < b->m_material;
+ return a->m_material.handle() < b->m_material.handle();
});
}
begin = rangeEnd;
diff --git a/src/render/backend/renderviewbuilder.cpp b/src/render/backend/renderviewbuilder.cpp
index 2237802d8..769eee29f 100644
--- a/src/render/backend/renderviewbuilder.cpp
+++ b/src/render/backend/renderviewbuilder.cpp
@@ -139,7 +139,8 @@ public:
RenderView *rv = m_renderViewJob->renderView();
// Layer filtering
- m_filterEntityByLayerJob->setLayerFilters(rv->layerFilters());
+ if (!m_filterEntityByLayerJob.isNull())
+ m_filterEntityByLayerJob->setLayerFilters(rv->layerFilters());
// Proximity filtering
m_filterProximityJob->setProximityFilterIds(rv->proximityFilterIds());
@@ -172,22 +173,24 @@ class SyncRenderCommandBuilding
public:
explicit SyncRenderCommandBuilding(const RenderViewInitializerJobPtr &renderViewJob,
const FrustumCullingJobPtr &frustumCullingJob,
- const FilterLayerEntityJobPtr &filterEntityByLayerJob,
const FilterProximityDistanceJobPtr &filterProximityJob,
const LightGathererPtr &lightGathererJob,
const RenderableEntityFilterPtr &renderableEntityFilterJob,
const ComputableEntityFilterPtr &computableEntityFilterJob,
const QVector<MaterialParameterGathererJobPtr> &materialGathererJobs,
- const QVector<RenderViewBuilderJobPtr> &renderViewBuilderJobs)
+ const QVector<RenderViewBuilderJobPtr> &renderViewBuilderJobs,
+ Renderer *renderer,
+ FrameGraphNode *leafNode)
: m_renderViewJob(renderViewJob)
, m_frustumCullingJob(frustumCullingJob)
- , m_filterEntityByLayerJob(filterEntityByLayerJob)
, m_filterProximityJob(filterProximityJob)
, m_lightGathererJob(lightGathererJob)
, m_renderableEntityFilterJob(renderableEntityFilterJob)
, m_computableEntityFilterJob(computableEntityFilterJob)
, m_materialGathererJobs(materialGathererJobs)
, m_renderViewBuilderJobs(renderViewBuilderJobs)
+ , m_renderer(renderer)
+ , m_leafNode(leafNode)
{}
void operator()()
@@ -211,8 +214,10 @@ public:
// Filter out entities that weren't selected by the layer filters
std::sort(renderableEntities.begin(), renderableEntities.end());
+ QMutexLocker lock(m_renderer->cache()->mutex());
+ const QVector<Entity *> filteredEntities = m_renderer->cache()->leafNodeCache.value(m_leafNode).filterEntitiesByLayer;
+ lock.unlock();
// Remove all entities from the compute and renderable vectors that aren't in the filtered layer vector
- const QVector<Entity *> filteredEntities = m_filterEntityByLayerJob->filteredEntities();
RenderViewBuilder::removeEntitiesNotInSubset(renderableEntities, filteredEntities);
// Set the light sources, with layer filters applied.
@@ -254,13 +259,14 @@ public:
private:
RenderViewInitializerJobPtr m_renderViewJob;
FrustumCullingJobPtr m_frustumCullingJob;
- FilterLayerEntityJobPtr m_filterEntityByLayerJob;
FilterProximityDistanceJobPtr m_filterProximityJob;
LightGathererPtr m_lightGathererJob;
RenderableEntityFilterPtr m_renderableEntityFilterJob;
ComputableEntityFilterPtr m_computableEntityFilterJob;
QVector<MaterialParameterGathererJobPtr> m_materialGathererJobs;
QVector<RenderViewBuilderJobPtr> m_renderViewBuilderJobs;
+ Renderer *m_renderer;
+ FrameGraphNode *m_leafNode;
};
class SetClearDrawBufferIndex
@@ -284,82 +290,51 @@ private:
RenderViewInitializerJobPtr m_renderViewJob;
};
+class SyncFilterEntityByLayer
+{
+public:
+ explicit SyncFilterEntityByLayer(const FilterLayerEntityJobPtr &filterEntityByLayerJob,
+ Renderer *renderer,
+ FrameGraphNode *leafNode)
+ : m_filterEntityByLayerJob(filterEntityByLayerJob)
+ , m_renderer(renderer)
+ , m_leafNode(leafNode)
+ {
+ }
+
+ void operator()()
+ {
+ QMutexLocker lock(m_renderer->cache()->mutex());
+ // Save the filtered by layer subset into the cache
+ const QVector<Entity *> filteredEntities = m_filterEntityByLayerJob->filteredEntities();
+ RendererCache::LeafNodeData &dataCacheForLeaf = m_renderer->cache()->leafNodeCache[m_leafNode];
+ dataCacheForLeaf.filterEntitiesByLayer = filteredEntities;
+ }
+
+private:
+ FilterLayerEntityJobPtr m_filterEntityByLayerJob;
+ Renderer *m_renderer;
+ FrameGraphNode *m_leafNode;
+};
+
} // anonymous
RenderViewBuilder::RenderViewBuilder(Render::FrameGraphNode *leafNode, int renderViewIndex, Renderer *renderer)
- : m_renderViewIndex(renderViewIndex)
+ : m_leafNode(leafNode)
+ , m_renderViewIndex(renderViewIndex)
, m_renderer(renderer)
+ , m_layerCacheNeedsToBeRebuilt(false)
, m_renderViewJob(RenderViewInitializerJobPtr::create())
- , m_filterEntityByLayerJob(Render::FilterLayerEntityJobPtr::create())
+ , m_filterEntityByLayerJob()
, m_lightGathererJob(Render::LightGathererPtr::create())
, m_renderableEntityFilterJob(RenderableEntityFilterPtr::create())
, m_computableEntityFilterJob(ComputableEntityFilterPtr::create())
, m_frustumCullingJob(Render::FrustumCullingJobPtr::create())
, m_syncFrustumCullingJob(SynchronizerJobPtr::create(SyncFrustumCulling(m_renderViewJob, m_frustumCullingJob), JobTypes::SyncFrustumCulling))
, m_setClearDrawBufferIndexJob(SynchronizerJobPtr::create(SetClearDrawBufferIndex(m_renderViewJob), JobTypes::ClearBufferDrawIndex))
+ , m_syncFilterEntityByLayerJob()
, m_filterProximityJob(Render::FilterProximityDistanceJobPtr::create())
{
- // Init what we can here
- EntityManager *entityManager = m_renderer->nodeManagers()->renderNodesManager();
- m_filterEntityByLayerJob->setManager(m_renderer->nodeManagers());
- m_filterProximityJob->setManager(m_renderer->nodeManagers());
- m_renderableEntityFilterJob->setManager(entityManager);
- m_computableEntityFilterJob->setManager(entityManager);
- m_frustumCullingJob->setRoot(m_renderer->sceneRoot());
- m_lightGathererJob->setManager(entityManager);
- m_renderViewJob->setRenderer(m_renderer);
- m_renderViewJob->setFrameGraphLeafNode(leafNode);
- m_renderViewJob->setSubmitOrderIndex(m_renderViewIndex);
-
- // RenderCommand building is the most consuming task -> split it
- // Estimate the number of jobs to create based on the number of entities
- m_renderViewBuilderJobs.reserve(RenderViewBuilder::m_optimalParallelJobCount);
- for (auto i = 0; i < RenderViewBuilder::m_optimalParallelJobCount; ++i) {
- auto renderViewCommandBuilder = Render::RenderViewBuilderJobPtr::create();
- renderViewCommandBuilder->setIndex(m_renderViewIndex);
- renderViewCommandBuilder->setRenderer(m_renderer);
- m_renderViewBuilderJobs.push_back(renderViewCommandBuilder);
- }
-
- // Since Material gathering is an heavy task, we split it
- const QVector<HMaterial> materialHandles = m_renderer->nodeManagers()->materialManager()->activeHandles();
- const int elementsPerJob = materialHandles.size() / RenderViewBuilder::m_optimalParallelJobCount;
- const int lastRemaingElements = materialHandles.size() % RenderViewBuilder::m_optimalParallelJobCount;
- m_materialGathererJobs.reserve(RenderViewBuilder::m_optimalParallelJobCount);
- for (auto i = 0; i < RenderViewBuilder::m_optimalParallelJobCount; ++i) {
- auto materialGatherer = Render::MaterialParameterGathererJobPtr::create();
- materialGatherer->setNodeManagers(m_renderer->nodeManagers());
- materialGatherer->setRenderer(m_renderer);
- if (i == RenderViewBuilder::m_optimalParallelJobCount - 1)
- materialGatherer->setHandles(materialHandles.mid(i * elementsPerJob, elementsPerJob + lastRemaingElements));
- else
- materialGatherer->setHandles(materialHandles.mid(i * elementsPerJob, elementsPerJob));
- m_materialGathererJobs.push_back(materialGatherer);
- }
-
- m_syncRenderViewInitializationJob = SynchronizerJobPtr::create(SyncRenderViewInitialization(m_renderViewJob,
- m_frustumCullingJob,
- m_filterEntityByLayerJob,
- m_filterProximityJob,
- m_materialGathererJobs,
- m_renderViewBuilderJobs),
- JobTypes::SyncRenderViewInitialization);
-
- m_syncRenderCommandBuildingJob = SynchronizerJobPtr::create(SyncRenderCommandBuilding(m_renderViewJob,
- m_frustumCullingJob,
- m_filterEntityByLayerJob,
- m_filterProximityJob,
- m_lightGathererJob,
- m_renderableEntityFilterJob,
- m_computableEntityFilterJob,
- m_materialGathererJobs,
- m_renderViewBuilderJobs),
- JobTypes::SyncRenderViewCommandBuilding);
-
- m_syncRenderViewCommandBuildersJob = SynchronizerJobPtr::create(SyncRenderViewCommandBuilders(m_renderViewJob,
- m_renderViewBuilderJobs,
- m_renderer),
- JobTypes::SyncRenderViewCommandBuilder);
}
RenderViewInitializerJobPtr RenderViewBuilder::renderViewJob() const
@@ -427,11 +402,91 @@ SynchronizerJobPtr RenderViewBuilder::setClearDrawBufferIndexJob() const
return m_setClearDrawBufferIndexJob;
}
+SynchronizerJobPtr RenderViewBuilder::syncFilterEntityByLayerJob() const
+{
+ return m_syncFilterEntityByLayerJob;
+}
+
FilterProximityDistanceJobPtr RenderViewBuilder::filterProximityJob() const
{
return m_filterProximityJob;
}
+void RenderViewBuilder::prepareJobs()
+{
+ // Init what we can here
+ EntityManager *entityManager = m_renderer->nodeManagers()->renderNodesManager();
+ m_filterProximityJob->setManager(m_renderer->nodeManagers());
+ m_renderableEntityFilterJob->setManager(entityManager);
+ m_computableEntityFilterJob->setManager(entityManager);
+ m_frustumCullingJob->setRoot(m_renderer->sceneRoot());
+ m_lightGathererJob->setManager(entityManager);
+ m_renderViewJob->setRenderer(m_renderer);
+ m_renderViewJob->setFrameGraphLeafNode(m_leafNode);
+ m_renderViewJob->setSubmitOrderIndex(m_renderViewIndex);
+
+ // RenderCommand building is the most consuming task -> split it
+ // Estimate the number of jobs to create based on the number of entities
+ m_renderViewBuilderJobs.reserve(RenderViewBuilder::m_optimalParallelJobCount);
+ for (auto i = 0; i < RenderViewBuilder::m_optimalParallelJobCount; ++i) {
+ auto renderViewCommandBuilder = Render::RenderViewBuilderJobPtr::create();
+ renderViewCommandBuilder->setIndex(m_renderViewIndex);
+ renderViewCommandBuilder->setRenderer(m_renderer);
+ m_renderViewBuilderJobs.push_back(renderViewCommandBuilder);
+ }
+
+ // Since Material gathering is an heavy task, we split it
+ const QVector<HMaterial> materialHandles = m_renderer->nodeManagers()->materialManager()->activeHandles();
+ const int elementsPerJob = materialHandles.size() / RenderViewBuilder::m_optimalParallelJobCount;
+ const int lastRemaingElements = materialHandles.size() % RenderViewBuilder::m_optimalParallelJobCount;
+ m_materialGathererJobs.reserve(RenderViewBuilder::m_optimalParallelJobCount);
+ for (auto i = 0; i < RenderViewBuilder::m_optimalParallelJobCount; ++i) {
+ auto materialGatherer = Render::MaterialParameterGathererJobPtr::create();
+ materialGatherer->setNodeManagers(m_renderer->nodeManagers());
+ materialGatherer->setRenderer(m_renderer);
+ if (i == RenderViewBuilder::m_optimalParallelJobCount - 1)
+ materialGatherer->setHandles(materialHandles.mid(i * elementsPerJob, elementsPerJob + lastRemaingElements));
+ else
+ materialGatherer->setHandles(materialHandles.mid(i * elementsPerJob, elementsPerJob));
+ m_materialGathererJobs.push_back(materialGatherer);
+ }
+
+ if (m_layerCacheNeedsToBeRebuilt) {
+ m_filterEntityByLayerJob = Render::FilterLayerEntityJobPtr::create();
+ m_filterEntityByLayerJob->setManager(m_renderer->nodeManagers());
+ m_syncFilterEntityByLayerJob = SynchronizerJobPtr::create(SyncFilterEntityByLayer(m_filterEntityByLayerJob,
+ m_renderer,
+ m_leafNode),
+ JobTypes::SyncFilterEntityByLayer);
+ }
+
+ m_syncRenderCommandBuildingJob = SynchronizerJobPtr::create(SyncRenderCommandBuilding(m_renderViewJob,
+ m_frustumCullingJob,
+ m_filterProximityJob,
+ m_lightGathererJob,
+ m_renderableEntityFilterJob,
+ m_computableEntityFilterJob,
+ m_materialGathererJobs,
+ m_renderViewBuilderJobs,
+ m_renderer,
+ m_leafNode),
+ JobTypes::SyncRenderViewCommandBuilding);
+
+ m_syncRenderViewCommandBuildersJob = SynchronizerJobPtr::create(SyncRenderViewCommandBuilders(m_renderViewJob,
+ m_renderViewBuilderJobs,
+ m_renderer),
+ JobTypes::SyncRenderViewCommandBuilder);
+
+ m_syncRenderViewInitializationJob = SynchronizerJobPtr::create(SyncRenderViewInitialization(m_renderViewJob,
+ m_frustumCullingJob,
+ m_filterEntityByLayerJob,
+ m_filterProximityJob,
+ m_materialGathererJobs,
+ m_renderViewBuilderJobs),
+ JobTypes::SyncRenderViewInitialization);
+
+}
+
QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const
{
QVector<Qt3DCore::QAspectJobPtr> jobs;
@@ -455,9 +510,6 @@ QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const
m_syncRenderViewInitializationJob->addDependency(m_renderViewJob);
- m_filterEntityByLayerJob->addDependency(m_syncRenderViewInitializationJob);
- m_filterEntityByLayerJob->addDependency(m_renderer->updateTreeEnabledJob());
-
m_filterProximityJob->addDependency(m_renderer->expandBoundingVolumeJob());
m_filterProximityJob->addDependency(m_syncRenderViewInitializationJob);
@@ -469,7 +521,6 @@ QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const
}
m_syncRenderCommandBuildingJob->addDependency(m_renderableEntityFilterJob);
m_syncRenderCommandBuildingJob->addDependency(m_computableEntityFilterJob);
- m_syncRenderCommandBuildingJob->addDependency(m_filterEntityByLayerJob);
m_syncRenderCommandBuildingJob->addDependency(m_filterProximityJob);
m_syncRenderCommandBuildingJob->addDependency(m_lightGathererJob);
m_syncRenderCommandBuildingJob->addDependency(m_frustumCullingJob);
@@ -492,8 +543,17 @@ QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const
jobs.push_back(m_syncRenderViewInitializationJob); // Step 2
+ if (m_layerCacheNeedsToBeRebuilt) {
+ m_filterEntityByLayerJob->addDependency(m_syncRenderViewInitializationJob);
+ m_filterEntityByLayerJob->addDependency(m_renderer->updateTreeEnabledJob());
+
+ m_syncFilterEntityByLayerJob->addDependency(m_filterEntityByLayerJob);
+ m_syncRenderCommandBuildingJob->addDependency(m_syncFilterEntityByLayerJob);
+
+ jobs.push_back(m_filterEntityByLayerJob); // Step 3
+ jobs.push_back(m_syncFilterEntityByLayerJob); // Step 4
+ }
jobs.push_back(m_syncFrustumCullingJob); // Step 3
- jobs.push_back(m_filterEntityByLayerJob); // Step 3
jobs.push_back(m_filterProximityJob); // Step 3
jobs.push_back(m_setClearDrawBufferIndexJob); // Step 3
@@ -501,12 +561,12 @@ QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const
jobs.push_back(materialGatherer);
jobs.push_back(m_frustumCullingJob); // Step 4
- jobs.push_back(m_syncRenderCommandBuildingJob); // Step 4
+ jobs.push_back(m_syncRenderCommandBuildingJob); // Step 5
- for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs)) // Step 5
+ for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs)) // Step 6
jobs.push_back(renderViewCommandBuilder);
- jobs.push_back(m_syncRenderViewCommandBuildersJob); // Step 6
+ jobs.push_back(m_syncRenderViewCommandBuildersJob); // Step 7
return jobs;
}
@@ -521,6 +581,16 @@ int RenderViewBuilder::renderViewIndex() const
return m_renderViewIndex;
}
+void RenderViewBuilder::setLayerCacheNeedsToBeRebuilt(bool needsToBeRebuilt)
+{
+ m_layerCacheNeedsToBeRebuilt = needsToBeRebuilt;
+}
+
+bool RenderViewBuilder::layerCacheNeedsToBeRebuilt() const
+{
+ return m_layerCacheNeedsToBeRebuilt;
+}
+
int RenderViewBuilder::optimalJobCount()
{
return RenderViewBuilder::m_optimalParallelJobCount;
diff --git a/src/render/backend/renderviewbuilder_p.h b/src/render/backend/renderviewbuilder_p.h
index 0aa2e035a..a1fb4eb8b 100644
--- a/src/render/backend/renderviewbuilder_p.h
+++ b/src/render/backend/renderviewbuilder_p.h
@@ -94,19 +94,26 @@ public:
SynchronizerJobPtr syncRenderCommandBuildingJob() const;
SynchronizerJobPtr syncRenderViewCommandBuildersJob() const;
SynchronizerJobPtr setClearDrawBufferIndexJob() const;
+ SynchronizerJobPtr syncFilterEntityByLayerJob() const;
FilterProximityDistanceJobPtr filterProximityJob() const;
+ void prepareJobs();
QVector<Qt3DCore::QAspectJobPtr> buildJobHierachy() const;
Renderer *renderer() const;
int renderViewIndex() const;
+ void setLayerCacheNeedsToBeRebuilt(bool needsToBeRebuilt);
+ bool layerCacheNeedsToBeRebuilt() const;
+
static int optimalJobCount();
static void removeEntitiesNotInSubset(QVector<Entity *> &entities, QVector<Entity *> subset);
private:
+ Render::FrameGraphNode *m_leafNode;
const int m_renderViewIndex;
Renderer *m_renderer;
+ bool m_layerCacheNeedsToBeRebuilt;
RenderViewInitializerJobPtr m_renderViewJob;
FilterLayerEntityJobPtr m_filterEntityByLayerJob;
@@ -122,6 +129,7 @@ private:
SynchronizerJobPtr m_syncRenderCommandBuildingJob;
SynchronizerJobPtr m_syncRenderViewCommandBuildersJob;
SynchronizerJobPtr m_setClearDrawBufferIndexJob;
+ SynchronizerJobPtr m_syncFilterEntityByLayerJob;
FilterProximityDistanceJobPtr m_filterProximityJob;
static const int m_optimalParallelJobCount;
diff --git a/src/render/framegraph/layerfilternode.cpp b/src/render/framegraph/layerfilternode.cpp
index b8fa5c075..4b6842015 100644
--- a/src/render/framegraph/layerfilternode.cpp
+++ b/src/render/framegraph/layerfilternode.cpp
@@ -73,6 +73,7 @@ void LayerFilterNode::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e);
if (change->propertyName() == QByteArrayLiteral("layer"))
m_layerIds.append(change->addedNodeId());
+ markDirty(AbstractRenderer::LayersDirty);
break;
}
@@ -80,6 +81,7 @@ void LayerFilterNode::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
const auto change = qSharedPointerCast<QPropertyNodeRemovedChange>(e);
if (change->propertyName() == QByteArrayLiteral("layer"))
m_layerIds.removeOne(change->removedNodeId());
+ markDirty(AbstractRenderer::LayersDirty);
break;
}
@@ -94,7 +96,6 @@ void LayerFilterNode::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
default:
break;
}
- markDirty(AbstractRenderer::AllDirty);
FrameGraphNode::sceneChangeEvent(e);
}
diff --git a/src/render/geometry/buffermanager.cpp b/src/render/geometry/buffermanager.cpp
index 5bd44f80f..25f95189e 100644
--- a/src/render/geometry/buffermanager.cpp
+++ b/src/render/geometry/buffermanager.cpp
@@ -60,9 +60,7 @@ void BufferManager::addDirtyBuffer(Qt3DCore::QNodeId bufferId)
QVector<Qt3DCore::QNodeId> BufferManager::dirtyBuffers()
{
- QVector<Qt3DCore::QNodeId> vector(m_dirtyBuffers);
- m_dirtyBuffers.clear();
- return vector;
+ return qMove(m_dirtyBuffers);
}
// Called in QAspectThread::syncChanges
diff --git a/src/render/graphicshelpers/graphicshelperes2.cpp b/src/render/graphicshelpers/graphicshelperes2.cpp
index a22d8752a..676363b73 100644
--- a/src/render/graphicshelpers/graphicshelperes2.cpp
+++ b/src/render/graphicshelpers/graphicshelperes2.cpp
@@ -209,6 +209,9 @@ QVector<ShaderUniform> GraphicsHelperES2::programUniformsAndLocations(GLuint pro
uniformName[sizeof(uniformName) - 1] = '\0';
uniform.m_location = m_funcs->glGetUniformLocation(programId, uniformName);
uniform.m_name = QString::fromUtf8(uniformName, uniformNameLength);
+ // Work around for uniform array names that aren't returned with [0] by some drivers
+ if (uniform.m_size > 1 && !uniform.m_name.endsWith(QLatin1String("[0]")))
+ uniform.m_name.append(QLatin1String("[0]"));
uniforms.append(uniform);
}
return uniforms;
diff --git a/src/render/graphicshelpers/graphicshelpergl2.cpp b/src/render/graphicshelpers/graphicshelpergl2.cpp
index 60d3b49ba..6da8a9b6f 100644
--- a/src/render/graphicshelpers/graphicshelpergl2.cpp
+++ b/src/render/graphicshelpers/graphicshelpergl2.cpp
@@ -178,6 +178,9 @@ QVector<ShaderUniform> GraphicsHelperGL2::programUniformsAndLocations(GLuint pro
uniformName[sizeof(uniformName) - 1] = '\0';
uniform.m_location = m_funcs->glGetUniformLocation(programId, uniformName);
uniform.m_name = QString::fromUtf8(uniformName, uniformNameLength);
+ // Work around for uniform array names that aren't returned with [0] by some drivers
+ if (uniform.m_size > 1 && !uniform.m_name.endsWith(QLatin1String("[0]")))
+ uniform.m_name.append(QLatin1String("[0]"));
uniform.m_rawByteSize = uniformByteSize(uniform);
uniforms.append(uniform);
}
diff --git a/src/render/graphicshelpers/graphicshelpergl3_2.cpp b/src/render/graphicshelpers/graphicshelpergl3_2.cpp
index 289ae18be..a35c4e37f 100644
--- a/src/render/graphicshelpers/graphicshelpergl3_2.cpp
+++ b/src/render/graphicshelpers/graphicshelpergl3_2.cpp
@@ -207,6 +207,9 @@ QVector<ShaderUniform> GraphicsHelperGL3_2::programUniformsAndLocations(GLuint p
uniformName[sizeof(uniformName) - 1] = '\0';
uniform.m_location = m_funcs->glGetUniformLocation(programId, uniformName);
uniform.m_name = QString::fromUtf8(uniformName, uniformNameLength);
+ // Work around for uniform array names that aren't returned with [0] by some drivers
+ if (uniform.m_size > 1 && !uniform.m_name.endsWith(QLatin1String("[0]")))
+ uniform.m_name.append(QLatin1String("[0]"));
m_funcs->glGetActiveUniformsiv(programId, 1, (GLuint*)&i, GL_UNIFORM_BLOCK_INDEX, &uniform.m_blockIndex);
m_funcs->glGetActiveUniformsiv(programId, 1, (GLuint*)&i, GL_UNIFORM_OFFSET, &uniform.m_offset);
m_funcs->glGetActiveUniformsiv(programId, 1, (GLuint*)&i, GL_UNIFORM_ARRAY_STRIDE, &uniform.m_arrayStride);
diff --git a/src/render/graphicshelpers/graphicshelpergl3_3.cpp b/src/render/graphicshelpers/graphicshelpergl3_3.cpp
index 40f8076bb..40c2bafeb 100644
--- a/src/render/graphicshelpers/graphicshelpergl3_3.cpp
+++ b/src/render/graphicshelpers/graphicshelpergl3_3.cpp
@@ -206,6 +206,9 @@ QVector<ShaderUniform> GraphicsHelperGL3_3::programUniformsAndLocations(GLuint p
uniformName[sizeof(uniformName) - 1] = '\0';
uniform.m_location = m_funcs->glGetUniformLocation(programId, uniformName);
uniform.m_name = QString::fromUtf8(uniformName, uniformNameLength);
+ // Work around for uniform array names that aren't returned with [0] by some drivers
+ if (uniform.m_size > 1 && !uniform.m_name.endsWith(QLatin1String("[0]")))
+ uniform.m_name.append(QLatin1String("[0]"));
m_funcs->glGetActiveUniformsiv(programId, 1, (GLuint*)&i, GL_UNIFORM_BLOCK_INDEX, &uniform.m_blockIndex);
m_funcs->glGetActiveUniformsiv(programId, 1, (GLuint*)&i, GL_UNIFORM_OFFSET, &uniform.m_offset);
m_funcs->glGetActiveUniformsiv(programId, 1, (GLuint*)&i, GL_UNIFORM_ARRAY_STRIDE, &uniform.m_arrayStride);
diff --git a/src/render/graphicshelpers/graphicshelpergl4.cpp b/src/render/graphicshelpers/graphicshelpergl4.cpp
index 284970873..ce1b8ac2b 100644
--- a/src/render/graphicshelpers/graphicshelpergl4.cpp
+++ b/src/render/graphicshelpers/graphicshelpergl4.cpp
@@ -249,6 +249,9 @@ QVector<ShaderUniform> GraphicsHelperGL4::programUniformsAndLocations(GLuint pro
uniformName[sizeof(uniformName) - 1] = '\0';
uniform.m_location = m_funcs->glGetUniformLocation(programId, uniformName);
uniform.m_name = QString::fromUtf8(uniformName, uniformNameLength);
+ // Work around for uniform array names that aren't returned with [0] by some drivers
+ if (uniform.m_size > 1 && !uniform.m_name.endsWith(QLatin1String("[0]")))
+ uniform.m_name.append(QLatin1String("[0]"));
m_funcs->glGetActiveUniformsiv(programId, 1, (GLuint*)&i, GL_UNIFORM_BLOCK_INDEX, &uniform.m_blockIndex);
m_funcs->glGetActiveUniformsiv(programId, 1, (GLuint*)&i, GL_UNIFORM_OFFSET, &uniform.m_offset);
m_funcs->glGetActiveUniformsiv(programId, 1, (GLuint*)&i, GL_UNIFORM_ARRAY_STRIDE, &uniform.m_arrayStride);
diff --git a/src/render/jobs/job_common_p.h b/src/render/jobs/job_common_p.h
index aa9828193..56c4346ed 100644
--- a/src/render/jobs/job_common_p.h
+++ b/src/render/jobs/job_common_p.h
@@ -102,7 +102,8 @@ namespace JobTypes {
SyncTextureLoading,
LoadSkeleton,
UpdateSkinningPalette,
- ProximityFiltering
+ ProximityFiltering,
+ SyncFilterEntityByLayer
};
} // JobTypes
diff --git a/src/render/materialsystem/parameter.cpp b/src/render/materialsystem/parameter.cpp
index 6671e4943..f00df3c90 100644
--- a/src/render/materialsystem/parameter.cpp
+++ b/src/render/materialsystem/parameter.cpp
@@ -87,10 +87,13 @@ void Parameter::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
if (propertyChange->propertyName() == QByteArrayLiteral("name")) {
m_name = propertyChange->value().toString();
m_nameId = StringToInt::lookupId(m_name);
+ markDirty(AbstractRenderer::MaterialDirty | AbstractRenderer::ParameterDirty);
} else if (propertyChange->propertyName() == QByteArrayLiteral("value")) {
m_uniformValue = UniformValue::fromVariant(propertyChange->value());
+ markDirty(AbstractRenderer::ParameterDirty);
+ } else if (propertyChange->propertyName() == QByteArrayLiteral("enabled")) {
+ markDirty(AbstractRenderer::MaterialDirty | AbstractRenderer::ParameterDirty);
}
- markDirty(AbstractRenderer::AllDirty);
}
BackendNode::sceneChangeEvent(e);
diff --git a/src/render/materialsystem/prototypes/default.json b/src/render/materialsystem/prototypes/default.json
index 9f16b0f53..535f144d7 100644
--- a/src/render/materialsystem/prototypes/default.json
+++ b/src/render/materialsystem/prototypes/default.json
@@ -91,7 +91,7 @@
"major": 3,
"minor": 0
},
- "substitution": "vec4 $color = texture2D($name, $coord);",
+ "substitution": "vec4 $color = texture($name, $coord);",
"headerSnippets": [ "uniform sampler2D $name;" ]
}
]
diff --git a/tests/auto/animation/animation.pro b/tests/auto/animation/animation.pro
index c97b07923..1226f9498 100644
--- a/tests/auto/animation/animation.pro
+++ b/tests/auto/animation/animation.pro
@@ -15,7 +15,8 @@ SUBDIRS += \
qmorphtarget \
qvertexblendanimation \
qclock \
- qskeletonmapping
+ qskeletonmapping \
+ qcallbackmapping
qtConfig(private_tests) {
SUBDIRS += \
diff --git a/tests/auto/animation/channelmapping/tst_channelmapping.cpp b/tests/auto/animation/channelmapping/tst_channelmapping.cpp
index 8f276f0bd..a947d4a2d 100644
--- a/tests/auto/animation/channelmapping/tst_channelmapping.cpp
+++ b/tests/auto/animation/channelmapping/tst_channelmapping.cpp
@@ -68,6 +68,7 @@ private Q_SLOTS:
QCOMPARE(backendMapping.channelName(), mapping.channelName());
QCOMPARE(backendMapping.targetId(), mapping.target()->id());
QCOMPARE(backendMapping.property(), mapping.property());
+ QCOMPARE(backendMapping.mappingType(), Qt3DAnimation::Animation::ChannelMapping::ChannelMappingType);
// GIVEN
Qt3DAnimation::Animation::ChannelMapping backendSkeletonMapping;
@@ -83,6 +84,7 @@ private Q_SLOTS:
QCOMPARE(backendSkeletonMapping.peerId(), skeletonMapping.id());
QCOMPARE(backendSkeletonMapping.isEnabled(), skeletonMapping.isEnabled());
QCOMPARE(backendSkeletonMapping.skeletonId(), skeletonMapping.skeleton()->id());
+ QCOMPARE(backendSkeletonMapping.mappingType(), Qt3DAnimation::Animation::ChannelMapping::SkeletonMappingType);
}
void checkInitialAndCleanedUpState()
@@ -99,6 +101,7 @@ private Q_SLOTS:
QCOMPARE(backendMapping.targetId(), Qt3DCore::QNodeId());
QCOMPARE(backendMapping.property(), QString());
QCOMPARE(backendMapping.skeletonId(), Qt3DCore::QNodeId());
+ QCOMPARE(backendMapping.mappingType(), Qt3DAnimation::Animation::ChannelMapping::ChannelMappingType);
// GIVEN
Qt3DAnimation::QChannelMapping mapping;
@@ -118,6 +121,7 @@ private Q_SLOTS:
QCOMPARE(backendMapping.targetId(), Qt3DCore::QNodeId());
QCOMPARE(backendMapping.property(), QString());
QCOMPARE(backendMapping.skeletonId(), Qt3DCore::QNodeId());
+ QCOMPARE(backendMapping.mappingType(), Qt3DAnimation::Animation::ChannelMapping::ChannelMappingType);
}
void checkPropertyChanges()
diff --git a/tests/auto/animation/findrunningclipanimatorsjob/tst_findrunningclipanimatorsjob.cpp b/tests/auto/animation/findrunningclipanimatorsjob/tst_findrunningclipanimatorsjob.cpp
index 79d18b7cf..ce37ffc76 100644
--- a/tests/auto/animation/findrunningclipanimatorsjob/tst_findrunningclipanimatorsjob.cpp
+++ b/tests/auto/animation/findrunningclipanimatorsjob/tst_findrunningclipanimatorsjob.cpp
@@ -72,6 +72,7 @@ public:
channelMapping->setPropertyName(propertyName);
channelMapping->setChannelName(channelName);
channelMapping->setType(type);
+ channelMapping->setMappingType(ChannelMapping::ChannelMappingType);
return channelMapping;
}
diff --git a/tests/auto/animation/qcallbackmapping/qcallbackmapping.pro b/tests/auto/animation/qcallbackmapping/qcallbackmapping.pro
new file mode 100644
index 000000000..2ec002878
--- /dev/null
+++ b/tests/auto/animation/qcallbackmapping/qcallbackmapping.pro
@@ -0,0 +1,12 @@
+TEMPLATE = app
+
+TARGET = tst_qcallbackmapping
+
+QT += 3dcore 3dcore-private 3danimation 3danimation-private testlib
+
+CONFIG += testcase
+
+SOURCES += \
+ tst_qcallbackmapping.cpp
+
+include(../../core/common/common.pri)
diff --git a/tests/auto/animation/qcallbackmapping/tst_qcallbackmapping.cpp b/tests/auto/animation/qcallbackmapping/tst_qcallbackmapping.cpp
new file mode 100644
index 000000000..6a1c8da8c
--- /dev/null
+++ b/tests/auto/animation/qcallbackmapping/tst_qcallbackmapping.cpp
@@ -0,0 +1,223 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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:GPL-EXCEPT$
+** 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 General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** 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-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QTest>
+#include <Qt3DAnimation/qcallbackmapping.h>
+#include <Qt3DAnimation/private/qcallbackmapping_p.h>
+#include <Qt3DAnimation/private/qchannelmappingcreatedchange_p.h>
+#include <Qt3DCore/qpropertyupdatedchange.h>
+#include <Qt3DCore/qentity.h>
+#include <Qt3DCore/qnodecreatedchange.h>
+#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
+#include <QObject>
+#include <QSignalSpy>
+#include <testpostmanarbiter.h>
+
+class DummyCallback : public Qt3DAnimation::QAnimationCallback
+{
+public:
+ void valueChanged(const QVariant &) override { }
+};
+
+class tst_QCallbackMapping : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void checkDefaultConstruction()
+ {
+ // GIVEN
+ Qt3DAnimation::QCallbackMapping mapping;
+
+ // THEN
+ QCOMPARE(mapping.channelName(), QString());
+ QCOMPARE(mapping.callback(), static_cast<Qt3DAnimation::QAnimationCallback *>(nullptr));
+ }
+
+ void checkPropertyChanges()
+ {
+ // GIVEN
+ Qt3DAnimation::QCallbackMapping mapping;
+
+ {
+ // WHEN
+ QSignalSpy spy(&mapping, SIGNAL(channelNameChanged(QString)));
+ const QString newValue(QStringLiteral("Rotation"));
+ mapping.setChannelName(newValue);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(mapping.channelName(), newValue);
+ QCOMPARE(spy.count(), 1);
+
+ // WHEN
+ spy.clear();
+ mapping.setChannelName(newValue);
+
+ // THEN
+ QCOMPARE(mapping.channelName(), newValue);
+ QCOMPARE(spy.count(), 0);
+ }
+
+ {
+ // WHEN
+ auto newValue = new DummyCallback();
+ mapping.setCallback(QVariant::Quaternion, newValue);
+
+ // THEN - no signals for callback
+ QCOMPARE(mapping.callback(), newValue);
+ }
+ }
+
+ void checkCreationData()
+ {
+ // GIVEN
+ Qt3DAnimation::QCallbackMapping mapping;
+ auto callback = new DummyCallback();
+
+ mapping.setChannelName(QStringLiteral("Location"));
+ mapping.setCallback(QVariant::Vector3D, callback);
+
+ // WHEN
+ QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges;
+
+ {
+ Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&mapping);
+ creationChanges = creationChangeGenerator.creationChanges();
+ }
+
+ // THEN
+ {
+ QCOMPARE(creationChanges.size(), 1);
+
+ const auto creationChangeData = qSharedPointerCast<Qt3DAnimation::QChannelMappingCreatedChange<Qt3DAnimation::QCallbackMappingData>>(creationChanges.first());
+ const Qt3DAnimation::QCallbackMappingData data = creationChangeData->data;
+
+ QCOMPARE(mapping.id(), creationChangeData->subjectId());
+ QCOMPARE(mapping.isEnabled(), true);
+ QCOMPARE(mapping.isEnabled(), creationChangeData->isNodeEnabled());
+ QCOMPARE(mapping.metaObject(), creationChangeData->metaObject());
+ QCOMPARE(creationChangeData->type(), Qt3DAnimation::QChannelMappingCreatedChangeBase::CallbackMapping);
+ QCOMPARE(mapping.channelName(), data.channelName);
+ QCOMPARE(mapping.callback(), data.callback);
+ QCOMPARE(QVariant::Vector3D, data.type);
+ }
+
+ // WHEN
+ mapping.setEnabled(false);
+
+ {
+ Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&mapping);
+ creationChanges = creationChangeGenerator.creationChanges();
+ }
+
+ // THEN
+ {
+ QCOMPARE(creationChanges.size(), 1);
+
+ const auto creationChangeData = qSharedPointerCast<Qt3DAnimation::QChannelMappingCreatedChange<Qt3DAnimation::QCallbackMappingData>>(creationChanges.first());
+ const Qt3DAnimation::QCallbackMappingData data = creationChangeData->data;
+
+ QCOMPARE(mapping.id(), creationChangeData->subjectId());
+ QCOMPARE(mapping.isEnabled(), false);
+ QCOMPARE(mapping.isEnabled(), creationChangeData->isNodeEnabled());
+ QCOMPARE(mapping.metaObject(), creationChangeData->metaObject());
+ QCOMPARE(creationChangeData->type(), Qt3DAnimation::QChannelMappingCreatedChangeBase::CallbackMapping);
+ QCOMPARE(mapping.channelName(), data.channelName);
+ QCOMPARE(mapping.callback(), data.callback);
+ QCOMPARE(QVariant::Vector3D, data.type);
+ }
+ }
+
+ void checkPropertyUpdateChanges()
+ {
+ // GIVEN
+ TestArbiter arbiter;
+ Qt3DAnimation::QCallbackMapping mapping;
+ arbiter.setArbiterOnNode(&mapping);
+
+ {
+ // WHEN
+ mapping.setChannelName(QStringLiteral("Scale"));
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 1);
+ auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>();
+ QCOMPARE(change->propertyName(), "channelName");
+ QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(change->value().toString(), mapping.channelName());
+
+ arbiter.events.clear();
+
+ // WHEN
+ mapping.setChannelName(QStringLiteral("Scale"));
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ }
+
+ {
+ // WHEN
+ auto callback = new DummyCallback();
+ mapping.setCallback(QVariant::Vector3D, callback, Qt3DAnimation::QAnimationCallback::OnThreadPool);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 3);
+ auto change = arbiter.events.at(0).staticCast<Qt3DCore::QPropertyUpdatedChange>();
+ QCOMPARE(change->propertyName(), "type");
+ QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(change->value().toInt(), QVariant::Vector3D);
+
+ change = arbiter.events.at(1).staticCast<Qt3DCore::QPropertyUpdatedChange>();
+ QCOMPARE(change->propertyName(), "callback");
+ QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(reinterpret_cast<DummyCallback *>(change->value().value<void *>()), callback);
+
+ change = arbiter.events.at(2).staticCast<Qt3DCore::QPropertyUpdatedChange>();
+ QCOMPARE(change->propertyName(), "callbackFlags");
+ QCOMPARE(change->type(), Qt3DCore::PropertyUpdated);
+ QCOMPARE(change->value().toInt(), static_cast<int>(Qt3DAnimation::QAnimationCallback::OnThreadPool));
+
+ arbiter.events.clear();
+
+ // WHEN
+ mapping.setCallback(QVariant::Vector3D, callback, Qt3DAnimation::QAnimationCallback::OnThreadPool);
+ QCoreApplication::processEvents();
+
+ // THEN
+ QCOMPARE(arbiter.events.size(), 0);
+ }
+ }
+};
+
+QTEST_MAIN(tst_QCallbackMapping)
+
+#include "tst_qcallbackmapping.moc"
diff --git a/tests/auto/core/handle/tst_handle.cpp b/tests/auto/core/handle/tst_handle.cpp
index 07155844f..4d4ccb645 100644
--- a/tests/auto/core/handle/tst_handle.cpp
+++ b/tests/auto/core/handle/tst_handle.cpp
@@ -28,12 +28,7 @@
#include <QtTest/QtTest>
#include <Qt3DCore/private/qhandle_p.h>
-
-#if Q_BYTE_ORDER == Q_BIG_ENDIAN
-#define GET_EXPECTED_HANDLE(qHandle) ((qHandle.index() << (qHandle.CounterBits + 2)) + (qHandle.counter() << 2))
-#else /* Q_LITTLE_ENDIAN */
-#define GET_EXPECTED_HANDLE(qHandle) (qHandle.index() + (qHandle.counter() << qHandle.IndexBits))
-#endif
+#include <Qt3DCore/private/qresourcemanager_p.h>
class tst_Handle : public QObject
{
@@ -49,8 +44,6 @@ private slots:
void assignment();
void equality();
void inequality();
- void staticLimits();
- void bigHandle();
};
class SimpleResource
@@ -64,107 +57,60 @@ public:
};
typedef Qt3DCore::QHandle<SimpleResource> Handle;
-typedef Qt3DCore::QHandle<SimpleResource, 22> BigHandle;
+typedef Qt3DCore::QHandleData<SimpleResource> HandleData;
void tst_Handle::defaultConstruction()
{
Handle h;
QVERIFY(h.isNull() == true);
- QVERIFY(h.index() == 0);
- QVERIFY(h.counter() == 0);
QVERIFY(h.handle() == 0);
}
void tst_Handle::construction()
{
- Handle h(0, 1);
+ HandleData d;
+ Handle h(&d);
QVERIFY(h.isNull() == false);
- QVERIFY(h.index() == 0);
- QVERIFY(h.counter() == 1);
qDebug() << h;
- QVERIFY(h.handle() == GET_EXPECTED_HANDLE(h));
-
- Handle h2(1, 1);
- QVERIFY(h2.isNull() == false);
- QVERIFY(h2.index() == 1);
- QVERIFY(h2.counter() == 1);
- qDebug() << h2;
- QVERIFY(h2.handle() == GET_EXPECTED_HANDLE(h2));
+ QVERIFY(h.handle() == reinterpret_cast<quintptr>(&d));
}
void tst_Handle::copyConstruction()
{
- Handle h1(0, 1);
- Handle h2(h1);
+ HandleData d;
+ Handle h(&d);
+ Handle h2(h);
QVERIFY(h2.isNull() == false);
- QVERIFY(h2.index() == 0);
- QVERIFY(h2.counter() == 1);
- QVERIFY(h2.handle() == GET_EXPECTED_HANDLE(h2));
+ QVERIFY(h2.handle() == h.handle());
}
void tst_Handle::assignment()
{
- Handle h1(0, 1);
- Handle h2 = h1;
+ HandleData d;
+ Handle h(&d);
+ Handle h2;
+ h2 = h;
QVERIFY(h2.isNull() == false);
- QVERIFY(h2.index() == 0);
- QVERIFY(h2.counter() == 1);
- QVERIFY(h2.handle() == GET_EXPECTED_HANDLE(h2));
+ QVERIFY(h2.handle() == h.handle());
}
void tst_Handle::equality()
{
- Handle h1(2, 1);
- Handle h2(2, 1);
+ HandleData d;
+ Handle h1(&d);
+ Handle h2(&d);
QVERIFY(h1.isNull() == false);
- QVERIFY(h1.index() == 2);
- QVERIFY(h1.counter() == 1);
- QVERIFY(h1.handle() == GET_EXPECTED_HANDLE(h1));
QVERIFY(h1 == h2);
}
void tst_Handle::inequality()
{
- Handle h1(2, 1);
- Handle h2(3, 1);
+ HandleData d1;
+ HandleData d2;
+ Handle h1(&d1);
+ Handle h2(&d2);
QVERIFY(h1.isNull() == false);
- QVERIFY(h1.index() == 2);
- QVERIFY(h1.counter() == 1);
- QVERIFY(h1.handle() == GET_EXPECTED_HANDLE(h1));
QVERIFY(h1 != h2);
-
- Handle h3(2, 2);
- QVERIFY(h1 != h3);
-}
-
-void tst_Handle::staticLimits()
-{
- QVERIFY(Handle::maxIndex() == (1 << 16) - 1);
- QVERIFY(Handle::maxCounter() == (1 << (32 - 16 - 2)) - 1);
-}
-
-void tst_Handle::bigHandle()
-{
- BigHandle h;
- QVERIFY(h.isNull() == true);
- QVERIFY(h.index() == 0);
- QVERIFY(h.counter() == 0);
- QVERIFY(h.handle() == 0);
-
- BigHandle h1(0, 1);
- QVERIFY(h1.isNull() == false);
- QVERIFY(h1.index() == 0);
- QVERIFY(h1.counter() == 1);
- QVERIFY(h1.handle() == GET_EXPECTED_HANDLE(h1));
-
- BigHandle h2(1, 1);
- QVERIFY(h2.isNull() == false);
- QVERIFY(h2.index() == 1);
- QVERIFY(h2.counter() == 1);
- QVERIFY(h2.handle() == GET_EXPECTED_HANDLE(h2));
-
- QVERIFY(BigHandle::maxIndex() == (1 << 22) - 1);
- QVERIFY(BigHandle::maxCounter() == (1 << (32 - 22 - 2)) - 1);
}
QTEST_APPLESS_MAIN(tst_Handle)
diff --git a/tests/auto/core/qresourcemanager/tst_qresourcemanager.cpp b/tests/auto/core/qresourcemanager/tst_qresourcemanager.cpp
index c3238fc8f..b7bd7c28a 100644
--- a/tests/auto/core/qresourcemanager/tst_qresourcemanager.cpp
+++ b/tests/auto/core/qresourcemanager/tst_qresourcemanager.cpp
@@ -97,8 +97,9 @@ void tst_DynamicArrayPolicy::acquireResources()
}
for (uint i = 0; i < 5; i++) {
- QVERIFY(handles.at(i).index() == i);
- QVERIFY(handles.at(i).counter() == 1);
+ QVERIFY(!handles.at(i).isNull());
+ if (i > 0)
+ QVERIFY(handles.at(i) != handles.at(i-1));
}
}
@@ -117,8 +118,6 @@ void tst_DynamicArrayPolicy::getResources()
}
for (uint i = 0; i < 5; i++) {
- QVERIFY(handles.at(i).index() == i);
- QVERIFY(handles.at(i).counter() == 1);
resources << manager.data(handles.at(i));
QVERIFY(resources.at(i) != nullptr);
resources.at(i)->m_value = i;
@@ -153,8 +152,6 @@ void tst_DynamicArrayPolicy::registerResourcesResize()
}
for (int i = 0; i < 7; i++) {
- QVERIFY(handles.at(i).index() == static_cast<uint>(i));
- QVERIFY(handles.at(i).counter() == 1);
if (i < 2)
QVERIFY(manager.data(handles.at(i))->m_value == i + 2);
else
@@ -169,14 +166,16 @@ void tst_DynamicArrayPolicy::removeResource()
{
Qt3DCore::QResourceManager<tst_ArrayResource, int> manager;
- QList<tst_ArrayResource *> resources;
QList<tHandle> handles;
for (int i = 0; i < 32; i++) {
handles << manager.acquire();
- resources << manager.data(handles.at(i));
}
+
+ tst_ArrayResource *resource = handles.at(2).data();
+ QVERIFY(resource != nullptr);
+
manager.release(handles.at(2));
QVERIFY(manager.data(handles.at(2)) == nullptr);
// Triggers QASSERT so commented
@@ -255,7 +254,7 @@ protected:
void run()
{
int i = 0;
- int max = tHandle::maxIndex();
+ int max = 65535;
while (i < max) {
tst_ArrayResource *r = m_manager->getOrCreateResource(i);
i++;
@@ -275,7 +274,7 @@ void tst_DynamicArrayPolicy::heavyDutyMultiThreadedAccess()
QList<tst_Thread *> threads;
int iterations = 8;
- int max = tHandle16::maxIndex();
+ int max = 65535;
for (int i = 0; i < iterations; i++) {
tst_Thread *thread = new tst_Thread();
@@ -326,7 +325,7 @@ protected:
void run()
{
int i = 0;
- int max = tHandle::maxIndex();
+ int max = 65535;
while (i < max) {
tst_ArrayResource *r = m_manager->getOrCreateResource(i);
QVERIFY(r != nullptr);
@@ -349,7 +348,7 @@ void tst_DynamicArrayPolicy::heavyDutyMultiThreadedAccessRelease()
QList<tst_Thread2 *> threads;
int iterations = 8;
- int max = tHandle16::maxIndex();
+ int max = 65535;
for (int u = 0; u < 2; u++) {
@@ -385,8 +384,6 @@ void tst_DynamicArrayPolicy::maximumNumberOfResources()
QList<tst_ArrayResource *> resources;
QList<tHandle16> handles;
- QCOMPARE(tHandle16::maxIndex(), (uint)manager.maximumSize());
-
for (int i = 0; i < manager.maximumSize(); i++) {
handles << manager.acquire();
resources << manager.data(handles.at(i));
diff --git a/tests/auto/render/filtercompatibletechniquejob/BLACKLIST b/tests/auto/render/filtercompatibletechniquejob/BLACKLIST
index c9313fd62..22cb59fab 100644
--- a/tests/auto/render/filtercompatibletechniquejob/BLACKLIST
+++ b/tests/auto/render/filtercompatibletechniquejob/BLACKLIST
@@ -1,4 +1,5 @@
-[checkRunRendererNotRunning]
-windows
-[checkRunRendererRunning]
+#[checkRunRendererNotRunning]
+#windows
+#[checkRunRendererRunning]
+#QTBUG-64271
windows
diff --git a/tests/auto/render/geometryloaders/cube2.obj b/tests/auto/render/geometryloaders/cube2.obj
new file mode 100644
index 000000000..8ea0caf87
--- /dev/null
+++ b/tests/auto/render/geometryloaders/cube2.obj
@@ -0,0 +1,26 @@
+# Blender v2.77 (sub 0) OBJ File: ''
+# www.blender.org
+mtllib cube.mtl
+o Cube
+v 1.000000 -1.000000 -1.000000
+v 1.000000 -1.000000 1.000000
+v -1.000000 -1.000000 1.000000
+v -1.000000 -1.000000 -1.000000
+v 1.000000 1.000000 -0.999999
+v 0.999999 1.000000 1.000001
+v -1.000000 1.000000 1.000000
+v -1.000000 1.000000 -1.000000
+vn 0.0000 -1.0000 0.0000
+vn 0.0000 1.0000 0.0000
+vn 1.0000 0.0000 0.0000
+vn -0.0000 -0.0000 1.0000
+vn -1.0000 -0.0000 -0.0000
+vn 0.0000 0.0000 -1.0000
+usemtl Material
+s off
+f 1//1 2//1 3//1 4//1
+f 5//2 8//2 7//2 6//2
+f 1//3 5//3 6//3 2//3
+f 2//4 6//4 7//4 3//4
+f 3//5 7//5 8//5 4//5
+f 5//6 1//6 4//6 8//6
diff --git a/tests/auto/render/geometryloaders/geometryloaders.qrc b/tests/auto/render/geometryloaders/geometryloaders.qrc
index 730a0c452..8f98f5a14 100644
--- a/tests/auto/render/geometryloaders/geometryloaders.qrc
+++ b/tests/auto/render/geometryloaders/geometryloaders.qrc
@@ -1,6 +1,7 @@
<RCC>
<qresource prefix="/">
<file>cube.obj</file>
+ <file>cube2.obj</file>
<file>cube.ply</file>
<file>cube.stl</file>
<file>cube.gltf</file>
diff --git a/tests/auto/render/geometryloaders/tst_geometryloaders.cpp b/tests/auto/render/geometryloaders/tst_geometryloaders.cpp
index 7b9f09d23..07545403d 100644
--- a/tests/auto/render/geometryloaders/tst_geometryloaders.cpp
+++ b/tests/auto/render/geometryloaders/tst_geometryloaders.cpp
@@ -60,6 +60,7 @@ class tst_geometryloaders : public QObject
Q_OBJECT
private Q_SLOTS:
+ void testOBJLoader_data();
void testOBJLoader();
void testPLYLoader();
void testSTLLoader();
@@ -69,6 +70,12 @@ private Q_SLOTS:
#endif
};
+void tst_geometryloaders::testOBJLoader_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::newRow("nominal case") << QStringLiteral(":/cube.obj");
+ QTest::newRow("trailing space + crlf") << QStringLiteral(":/cube2.obj");
+}
void tst_geometryloaders::testOBJLoader()
{
QScopedPointer<QGeometryLoaderInterface> loader;
@@ -77,7 +84,8 @@ void tst_geometryloaders::testOBJLoader()
if (!loader)
return;
- QFile file(QStringLiteral(":/cube.obj"));
+ QFETCH(QString, fileName);
+ QFile file(fileName);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qDebug("Could not open test file for reading");
return;
diff --git a/tests/auto/render/renderer/tst_renderer.cpp b/tests/auto/render/renderer/tst_renderer.cpp
index 855b07797..85d978926 100644
--- a/tests/auto/render/renderer/tst_renderer.cpp
+++ b/tests/auto/render/renderer/tst_renderer.cpp
@@ -60,7 +60,7 @@ private Q_SLOTS:
renderer.setSettings(&settings);
renderer.initialize();
- const int singleRenderViewJobCount = 12 + 2 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount();
+ const int singleRenderViewJobCount = 11 + 2 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount();
// RenderViewBuilder renderViewJob,
// renderableEntityFilterJob,
// lightGatherJob,
diff --git a/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp b/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp
index b781ff04d..23861f3a9 100644
--- a/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp
+++ b/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp
@@ -179,27 +179,60 @@ private Q_SLOTS:
Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(clearBuffer->id());
QVERIFY(leafNode != nullptr);
- // WHEN
- Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
+ {
+ // WHEN
+ Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
+
+ // THEN
+ QCOMPARE(renderViewBuilder.renderViewIndex(), 0);
+ QCOMPARE(renderViewBuilder.renderer(), testAspect.renderer());
+ QCOMPARE(renderViewBuilder.layerCacheNeedsToBeRebuilt(), false);
+ QVERIFY(!renderViewBuilder.renderViewJob().isNull());
+ QVERIFY(!renderViewBuilder.lightGathererJob().isNull());
+ QVERIFY(!renderViewBuilder.renderableEntityFilterJob().isNull());
+ QVERIFY(!renderViewBuilder.computableEntityFilterJob().isNull());
+ QVERIFY(!renderViewBuilder.frustumCullingJob().isNull());
+ QVERIFY(!renderViewBuilder.syncFrustumCullingJob().isNull());
+ QVERIFY(!renderViewBuilder.setClearDrawBufferIndexJob().isNull());
+
+ QVERIFY(renderViewBuilder.filterEntityByLayerJob().isNull());
+ QVERIFY(renderViewBuilder.syncFilterEntityByLayerJob().isNull());
+ QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob().isNull());
+ QVERIFY(renderViewBuilder.syncRenderViewCommandBuildersJob().isNull());
+ QVERIFY(renderViewBuilder.syncRenderViewInitializationJob().isNull());
+
+ QCOMPARE(renderViewBuilder.renderViewBuilderJobs().size(), 0);
+ QCOMPARE(renderViewBuilder.materialGathererJobs().size(), 0);
+
+ // WHEN
+ renderViewBuilder.prepareJobs();
+
+ // THEN
+ QVERIFY(!renderViewBuilder.syncRenderCommandBuildingJob().isNull());
+ QVERIFY(!renderViewBuilder.syncRenderViewCommandBuildersJob().isNull());
+ QVERIFY(!renderViewBuilder.syncRenderViewInitializationJob().isNull());
+ QVERIFY(renderViewBuilder.filterEntityByLayerJob().isNull());
+ QVERIFY(renderViewBuilder.syncFilterEntityByLayerJob().isNull());
+
+ QCOMPARE(renderViewBuilder.renderViewBuilderJobs().size(), Qt3DRender::Render::RenderViewBuilder::optimalJobCount());
+ QCOMPARE(renderViewBuilder.materialGathererJobs().size(), Qt3DRender::Render::RenderViewBuilder::optimalJobCount());
+ QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 11 + 2 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount());
+ }
- // THEN
- QCOMPARE(renderViewBuilder.renderViewIndex(), 0);
- QCOMPARE(renderViewBuilder.renderer(), testAspect.renderer());
- QVERIFY(!renderViewBuilder.renderViewJob().isNull());
- QVERIFY(!renderViewBuilder.filterEntityByLayerJob().isNull());
- QVERIFY(!renderViewBuilder.lightGathererJob().isNull());
- QVERIFY(!renderViewBuilder.renderableEntityFilterJob().isNull());
- QVERIFY(!renderViewBuilder.computableEntityFilterJob().isNull());
- QVERIFY(!renderViewBuilder.frustumCullingJob().isNull());
- QVERIFY(!renderViewBuilder.syncRenderViewInitializationJob().isNull());
- QVERIFY(!renderViewBuilder.syncFrustumCullingJob().isNull());
- QVERIFY(!renderViewBuilder.syncRenderCommandBuildingJob().isNull());
- QVERIFY(!renderViewBuilder.syncRenderViewCommandBuildersJob().isNull());
- QVERIFY(!renderViewBuilder.setClearDrawBufferIndexJob().isNull());
- QCOMPARE(renderViewBuilder.renderViewBuilderJobs().size(), Qt3DRender::Render::RenderViewBuilder::optimalJobCount());
- QCOMPARE(renderViewBuilder.materialGathererJobs().size(), Qt3DRender::Render::RenderViewBuilder::optimalJobCount());
-
- QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 12 + 2 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount());
+ {
+ // WHEN
+ Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
+ renderViewBuilder.setLayerCacheNeedsToBeRebuilt(true);
+ renderViewBuilder.prepareJobs();
+
+ // THEN
+ QCOMPARE(renderViewBuilder.layerCacheNeedsToBeRebuilt(), true);
+ QVERIFY(!renderViewBuilder.filterEntityByLayerJob().isNull());
+ QVERIFY(!renderViewBuilder.syncFilterEntityByLayerJob().isNull());
+
+ // mark jobs dirty and recheck
+ QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 13 + 2 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount());
+ }
}
void checkCheckJobDependencies()
@@ -213,70 +246,145 @@ private Q_SLOTS:
Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(clearBuffer->id());
QVERIFY(leafNode != nullptr);
- // WHEN
- Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
- renderViewBuilder.buildJobHierachy();
-
- // THEN
- // Step 1
- QCOMPARE(renderViewBuilder.renderViewJob()->dependencies().size(), 1); // Depends upon skinning palette update
- QCOMPARE(renderViewBuilder.lightGathererJob()->dependencies().size(), 0);
- QCOMPARE(renderViewBuilder.renderableEntityFilterJob()->dependencies().size(),0);
- QCOMPARE(renderViewBuilder.computableEntityFilterJob()->dependencies().size(), 0);
-
- // Step 2
- QCOMPARE(renderViewBuilder.syncRenderViewInitializationJob()->dependencies().size(), 1);
- QCOMPARE(renderViewBuilder.syncRenderViewInitializationJob()->dependencies().first().data(), renderViewBuilder.renderViewJob().data());
-
- // Step 3
- QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->dependencies().size(), 2);
- QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob()));
- QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(testAspect.renderer()->updateTreeEnabledJob()));
-
- QCOMPARE(renderViewBuilder.filterProximityJob()->dependencies().size(), 2);
- QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob()));
- QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob()));
-
- QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().size(), 1);
- QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().first().data(), renderViewBuilder.syncRenderViewInitializationJob().data());
-
- QCOMPARE(renderViewBuilder.syncFrustumCullingJob()->dependencies().size(), 3);
- QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob()));
- QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateWorldTransformJob()));
- QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateShaderDataTransformJob()));
-
- for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) {
- QCOMPARE(materialGatherer->dependencies().size(), 2);
- QVERIFY(materialGatherer->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob()));
- QVERIFY(materialGatherer->dependencies().contains(testAspect.renderer()->filterCompatibleTechniqueJob()));
- }
-
- // Step 4
- QCOMPARE(renderViewBuilder.frustumCullingJob()->dependencies().size(), 2);
- QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(renderViewBuilder.syncFrustumCullingJob()));
- QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob()));
-
- QCOMPARE(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().size(), renderViewBuilder.materialGathererJobs().size() + 7);
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob()));
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.renderableEntityFilterJob()));
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.computableEntityFilterJob()));
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.filterEntityByLayerJob()));
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.lightGathererJob()));
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.frustumCullingJob()));
- for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) {
- QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(materialGatherer));
+ {
+ // WHEN
+ Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
+ renderViewBuilder.prepareJobs();
+ renderViewBuilder.buildJobHierachy();
+
+ // THEN
+ // Step 1
+ QCOMPARE(renderViewBuilder.renderViewJob()->dependencies().size(), 1); // Depends upon skinning palette update
+ QCOMPARE(renderViewBuilder.lightGathererJob()->dependencies().size(), 0);
+ QCOMPARE(renderViewBuilder.renderableEntityFilterJob()->dependencies().size(),0);
+ QCOMPARE(renderViewBuilder.computableEntityFilterJob()->dependencies().size(), 0);
+
+ // Step 2
+ QCOMPARE(renderViewBuilder.syncRenderViewInitializationJob()->dependencies().size(), 1);
+ QCOMPARE(renderViewBuilder.syncRenderViewInitializationJob()->dependencies().first().data(), renderViewBuilder.renderViewJob().data());
+
+ // Step 3
+ QVERIFY(renderViewBuilder.filterEntityByLayerJob().isNull());
+ QVERIFY(renderViewBuilder.syncFilterEntityByLayerJob().isNull());
+
+ QCOMPARE(renderViewBuilder.filterProximityJob()->dependencies().size(), 2);
+ QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob()));
+ QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob()));
+
+ QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().size(), 1);
+ QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().first().data(), renderViewBuilder.syncRenderViewInitializationJob().data());
+
+ QCOMPARE(renderViewBuilder.syncFrustumCullingJob()->dependencies().size(), 3);
+ QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob()));
+ QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateWorldTransformJob()));
+ QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateShaderDataTransformJob()));
+
+ for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) {
+ QCOMPARE(materialGatherer->dependencies().size(), 2);
+ QVERIFY(materialGatherer->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob()));
+ QVERIFY(materialGatherer->dependencies().contains(testAspect.renderer()->filterCompatibleTechniqueJob()));
+ }
+
+ // Step 4
+ QCOMPARE(renderViewBuilder.frustumCullingJob()->dependencies().size(), 2);
+ QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(renderViewBuilder.syncFrustumCullingJob()));
+ QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob()));
+
+ QCOMPARE(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().size(), renderViewBuilder.materialGathererJobs().size() + 6);
+ QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob()));
+ QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.renderableEntityFilterJob()));
+ QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.computableEntityFilterJob()));
+ QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.filterProximityJob()));
+ QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.lightGathererJob()));
+ QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.frustumCullingJob()));
+ for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) {
+ QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(materialGatherer));
+ }
+
+ // Step 5
+ for (const auto renderViewBuilderJob : renderViewBuilder.renderViewBuilderJobs()) {
+ QCOMPARE(renderViewBuilderJob->dependencies().size(), 1);
+ QCOMPARE(renderViewBuilderJob->dependencies().first().data(), renderViewBuilder.syncRenderCommandBuildingJob().data());
+ }
+
+ // Step 6
+ QCOMPARE(renderViewBuilder.syncRenderViewCommandBuildersJob()->dependencies().size(), renderViewBuilder.renderViewBuilderJobs().size());
+ for (const auto renderViewBuilderJob : renderViewBuilder.renderViewBuilderJobs()) {
+ QVERIFY(renderViewBuilder.syncRenderViewCommandBuildersJob()->dependencies().contains(renderViewBuilderJob));
+ }
}
-
- // Step 5
- for (const auto renderViewBuilderJob : renderViewBuilder.renderViewBuilderJobs()) {
- QCOMPARE(renderViewBuilderJob->dependencies().size(), 1);
- QCOMPARE(renderViewBuilderJob->dependencies().first().data(), renderViewBuilder.syncRenderCommandBuildingJob().data());
- }
-
- // Step 6
- QCOMPARE(renderViewBuilder.syncRenderViewCommandBuildersJob()->dependencies().size(), renderViewBuilder.renderViewBuilderJobs().size());
- for (const auto renderViewBuilderJob : renderViewBuilder.renderViewBuilderJobs()) {
- QVERIFY(renderViewBuilder.syncRenderViewCommandBuildersJob()->dependencies().contains(renderViewBuilderJob));
+ {
+ // WHEN
+ Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
+ renderViewBuilder.setLayerCacheNeedsToBeRebuilt(true);
+ renderViewBuilder.prepareJobs();
+ renderViewBuilder.buildJobHierachy();
+
+ // THEN
+ // Step 1
+ QCOMPARE(renderViewBuilder.renderViewJob()->dependencies().size(), 1); // Depends upon skinning palette update
+ QCOMPARE(renderViewBuilder.lightGathererJob()->dependencies().size(), 0);
+ QCOMPARE(renderViewBuilder.renderableEntityFilterJob()->dependencies().size(),0);
+ QCOMPARE(renderViewBuilder.computableEntityFilterJob()->dependencies().size(), 0);
+
+ // Step 2
+ QCOMPARE(renderViewBuilder.syncRenderViewInitializationJob()->dependencies().size(), 1);
+ QCOMPARE(renderViewBuilder.syncRenderViewInitializationJob()->dependencies().first().data(), renderViewBuilder.renderViewJob().data());
+
+ // Step 3
+ QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->dependencies().size(), 2);
+ QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob()));
+ QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(testAspect.renderer()->updateTreeEnabledJob()));
+
+ QCOMPARE(renderViewBuilder.syncFilterEntityByLayerJob()->dependencies().size(), 1);
+ QVERIFY(renderViewBuilder.syncFilterEntityByLayerJob()->dependencies().contains(renderViewBuilder.filterEntityByLayerJob()));
+
+ QCOMPARE(renderViewBuilder.filterProximityJob()->dependencies().size(), 2);
+ QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob()));
+ QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob()));
+
+ QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().size(), 1);
+ QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().first().data(), renderViewBuilder.syncRenderViewInitializationJob().data());
+
+ QCOMPARE(renderViewBuilder.syncFrustumCullingJob()->dependencies().size(), 3);
+ QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob()));
+ QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateWorldTransformJob()));
+ QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateShaderDataTransformJob()));
+
+ for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) {
+ QCOMPARE(materialGatherer->dependencies().size(), 2);
+ QVERIFY(materialGatherer->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob()));
+ QVERIFY(materialGatherer->dependencies().contains(testAspect.renderer()->filterCompatibleTechniqueJob()));
+ }
+
+ // Step 4
+ QCOMPARE(renderViewBuilder.frustumCullingJob()->dependencies().size(), 2);
+ QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(renderViewBuilder.syncFrustumCullingJob()));
+ QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob()));
+
+ QCOMPARE(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().size(), renderViewBuilder.materialGathererJobs().size() + 7);
+ QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob()));
+ QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.renderableEntityFilterJob()));
+ QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.computableEntityFilterJob()));
+ QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.syncFilterEntityByLayerJob()));
+ QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.lightGathererJob()));
+ QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.frustumCullingJob()));
+ QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.filterProximityJob()));
+ for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) {
+ QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(materialGatherer));
+ }
+
+ // Step 5
+ for (const auto renderViewBuilderJob : renderViewBuilder.renderViewBuilderJobs()) {
+ QCOMPARE(renderViewBuilderJob->dependencies().size(), 1);
+ QCOMPARE(renderViewBuilderJob->dependencies().first().data(), renderViewBuilder.syncRenderCommandBuildingJob().data());
+ }
+
+ // Step 6
+ QCOMPARE(renderViewBuilder.syncRenderViewCommandBuildersJob()->dependencies().size(), renderViewBuilder.renderViewBuilderJobs().size());
+ for (const auto renderViewBuilderJob : renderViewBuilder.renderViewBuilderJobs()) {
+ QVERIFY(renderViewBuilder.syncRenderViewCommandBuildersJob()->dependencies().contains(renderViewBuilderJob));
+ }
}
}
@@ -293,6 +401,7 @@ private Q_SLOTS:
// WHEN
Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
+ renderViewBuilder.prepareJobs();
renderViewBuilder.buildJobHierachy();
renderViewBuilder.renderViewJob()->run();
@@ -313,6 +422,7 @@ private Q_SLOTS:
// WHEN
Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
+ renderViewBuilder.prepareJobs();
renderViewBuilder.buildJobHierachy();
renderViewBuilder.renderableEntityFilterJob()->run();
@@ -333,6 +443,7 @@ private Q_SLOTS:
// WHEN
Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
+ renderViewBuilder.prepareJobs();
renderViewBuilder.buildJobHierachy();
renderViewBuilder.computableEntityFilterJob()->run();
@@ -358,30 +469,58 @@ private Q_SLOTS:
Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(renderPassFilter->id());
QVERIFY(leafNode != nullptr);
- // WHEN
- Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
- renderViewBuilder.buildJobHierachy();
-
- // THEN
- QCOMPARE(renderViewBuilder.frustumCullingJob()->isActive(), false);
- QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->hasLayerFilter(), false);
- QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->layerFilters().size(), 0);
- for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) {
- QVERIFY(materialGatherer->techniqueFilter() == nullptr);
- QVERIFY(materialGatherer->renderPassFilter() == nullptr);
+ {
+ // WHEN
+ Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
+ renderViewBuilder.prepareJobs();
+ renderViewBuilder.buildJobHierachy();
+
+ // THEN
+ QCOMPARE(renderViewBuilder.frustumCullingJob()->isActive(), false);
+ for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) {
+ QVERIFY(materialGatherer->techniqueFilter() == nullptr);
+ QVERIFY(materialGatherer->renderPassFilter() == nullptr);
+ }
+
+ // WHEN
+ renderViewBuilder.renderViewJob()->run();
+ renderViewBuilder.syncRenderViewInitializationJob()->run();
+
+ // THEN
+ QCOMPARE(renderViewBuilder.frustumCullingJob()->isActive(), true);
+ for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) {
+ QVERIFY(materialGatherer->techniqueFilter() != nullptr);
+ QVERIFY(materialGatherer->renderPassFilter() != nullptr);
+ }
}
-
- // WHEN
- renderViewBuilder.renderViewJob()->run();
- renderViewBuilder.syncRenderViewInitializationJob()->run();
-
- // THEN
- QCOMPARE(renderViewBuilder.frustumCullingJob()->isActive(), true);
- QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->hasLayerFilter(), true);
- QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->layerFilters().size(), 1);
- for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) {
- QVERIFY(materialGatherer->techniqueFilter() != nullptr);
- QVERIFY(materialGatherer->renderPassFilter() != nullptr);
+ {
+ // WHEN
+ Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
+ renderViewBuilder.setLayerCacheNeedsToBeRebuilt(true);
+ renderViewBuilder.prepareJobs();
+ renderViewBuilder.buildJobHierachy();
+
+ // THEN
+ QCOMPARE(renderViewBuilder.frustumCullingJob()->isActive(), false);
+ QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->hasLayerFilter(), false);
+ QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->layerFilters().size(), 0);
+ for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) {
+ QVERIFY(materialGatherer->techniqueFilter() == nullptr);
+ QVERIFY(materialGatherer->renderPassFilter() == nullptr);
+ }
+
+ // WHEN
+ renderViewBuilder.renderViewJob()->run();
+ renderViewBuilder.syncRenderViewInitializationJob()->run();
+
+ // THEN
+ QCOMPARE(renderViewBuilder.frustumCullingJob()->isActive(), true);
+ QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->hasLayerFilter(), true);
+ QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->layerFilters().size(), 1);
+ for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) {
+ QVERIFY(materialGatherer->techniqueFilter() != nullptr);
+ QVERIFY(materialGatherer->renderPassFilter() != nullptr);
+ }
}
}
@@ -403,6 +542,7 @@ private Q_SLOTS:
// WHEN
Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
+ renderViewBuilder.prepareJobs();
renderViewBuilder.buildJobHierachy();
// THEN
@@ -432,6 +572,8 @@ private Q_SLOTS:
// WHEN
Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer());
+ renderViewBuilder.setLayerCacheNeedsToBeRebuilt(true);
+ renderViewBuilder.prepareJobs();
renderViewBuilder.buildJobHierachy();
renderViewBuilder.renderViewJob()->run();
diff --git a/tests/benchmarks/core/qresourcesmanager/qresourcesmanager/tst_bench_qresourcesmanager.cpp b/tests/benchmarks/core/qresourcesmanager/qresourcesmanager/tst_bench_qresourcesmanager.cpp
index 6ddb058a1..51eb2d6fc 100644
--- a/tests/benchmarks/core/qresourcesmanager/qresourcesmanager/tst_bench_qresourcesmanager.cpp
+++ b/tests/benchmarks/core/qresourcesmanager/qresourcesmanager/tst_bench_qresourcesmanager.cpp
@@ -159,9 +159,14 @@ void benchmarkReleaseResources()
QVector<Qt3DCore::QHandle<Resource> > handles(max);
for (int i = 0; i < max; i++)
handles[i] = manager.acquire();
+ for (int i = 0; i < max; i++)
+ manager.release(handles.at(i));
+ handles.clear();
QBENCHMARK_ONCE {
- /*manager.reset()*/;
+ // the release/clear should have left many unused handled in the resourcemanager,
+ // so the next acquire will trigger a collection of all freed resources
+ manager.acquire();
}
}
diff --git a/tests/manual/layerfilter-qml/main.qml b/tests/manual/layerfilter-qml/main.qml
index 8a5977faa..00b1cffa0 100644
--- a/tests/manual/layerfilter-qml/main.qml
+++ b/tests/manual/layerfilter-qml/main.qml
@@ -49,7 +49,7 @@
****************************************************************************/
import Qt3D.Core 2.0
-import Qt3D.Render 2.0
+import Qt3D.Render 2.10
import Qt3D.Input 2.0
import Qt3D.Extras 2.0
@@ -127,7 +127,7 @@ Entity {
layers: [
backgroundLayer,
]
- discard: true
+ filterMode: LayerFilter.DiscardAnyMatchingLayers
CameraSelector {
camera: camera