diff options
author | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2019-10-01 03:00:42 +0200 |
---|---|---|
committer | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2019-10-01 03:00:42 +0200 |
commit | 73bfd21fcbe9f7f647edcbe19b7153ac4cc5c859 (patch) | |
tree | e814e94894d6974d93ac30eca21cbecf105d4ad9 /src | |
parent | 9ba07868d3ddedd2e39f9612118674cefd5fe1bf (diff) | |
parent | 621c19719e51d0b4c94a51f802f8a2128e201b85 (diff) |
Merge remote-tracking branch 'origin/5.14' into 5.15
Change-Id: Ie15f601b175beeb01d00050dadf3cb8952ed580a
Diffstat (limited to 'src')
77 files changed, 1215 insertions, 905 deletions
diff --git a/src/core/nodes/qnode.cpp b/src/core/nodes/qnode.cpp index 5c37e337e..2cea47372 100644 --- a/src/core/nodes/qnode.cpp +++ b/src/core/nodes/qnode.cpp @@ -687,6 +687,9 @@ QNodePrivate *QNodePrivate::get(QNode *q) return q->d_func(); } +/*! + \internal + */ const QNodePrivate *QNodePrivate::get(const QNode *q) { return q->d_func(); diff --git a/src/extras/defaults/qabstractcameracontroller.cpp b/src/extras/defaults/qabstractcameracontroller.cpp index 27df65d7b..c8ebf42f3 100644 --- a/src/extras/defaults/qabstractcameracontroller.cpp +++ b/src/extras/defaults/qabstractcameracontroller.cpp @@ -211,6 +211,10 @@ void QAbstractCameraControllerPrivate::init() m_logicalDevice, &Qt3DInput::QLogicalDevice::setEnabled); QObject::connect(q, &Qt3DCore::QEntity::enabledChanged, m_frameAction, &Qt3DLogic::QFrameAction::setEnabled); + for (auto axis: {m_rxAxis, m_ryAxis, m_txAxis, m_tyAxis, m_tzAxis}) { + QObject::connect(q, &Qt3DCore::QEntity::enabledChanged, + axis, &Qt3DInput::QAxis::setEnabled); + } QObject::connect(m_escapeButtonAction, &Qt3DInput::QAction::activeChanged, q, [this](bool isActive) { diff --git a/src/extras/defaults/qt3dwindow.cpp b/src/extras/defaults/qt3dwindow.cpp index a2b9ba4bb..ace40c3c1 100644 --- a/src/extras/defaults/qt3dwindow.cpp +++ b/src/extras/defaults/qt3dwindow.cpp @@ -61,6 +61,7 @@ #include <Qt3DLogic/qlogicaspect.h> #include <Qt3DRender/qcamera.h> #include <QtGui/qopenglcontext.h> +#include <private/qrendersettings_p.h> #include <QEvent> @@ -248,8 +249,11 @@ bool Qt3DWindow::event(QEvent *e) { Q_D(Qt3DWindow); const bool needsRedraw = (e->type() == QEvent::Expose || e->type() == QEvent::UpdateRequest); - if (needsRedraw && d->m_renderSettings->renderPolicy() == Qt3DRender::QRenderSettings::OnDemand) - d->m_renderSettings->sendCommand(QLatin1String("InvalidateFrame")); + if (needsRedraw && d->m_renderSettings->renderPolicy() == Qt3DRender::QRenderSettings::OnDemand) { + Qt3DRender::QRenderSettingsPrivate *p = static_cast<Qt3DRender::QRenderSettingsPrivate *>( + Qt3DCore::QNodePrivate::get(d->m_renderSettings)); + p->invalidateFrame(); + } return QWindow::event(e); } diff --git a/src/input/backend/axis.cpp b/src/input/backend/axis.cpp index 6ba4e2b34..20c05a49f 100644 --- a/src/input/backend/axis.cpp +++ b/src/input/backend/axis.cpp @@ -42,10 +42,9 @@ #include <Qt3DInput/qaxis.h> #include <Qt3DInput/qabstractaxisinput.h> #include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> #include <Qt3DInput/private/qaxis_p.h> +#include <algorithm> QT_BEGIN_NAMESPACE @@ -54,18 +53,11 @@ namespace Qt3DInput { namespace Input { Axis::Axis() - : Qt3DCore::QBackendNode(ReadWrite) + : BackendNode(ReadWrite) , m_axisValue(0.0f) { } -void Axis::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) -{ - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QAxisData>>(change); - const auto &data = typedChange->data; - m_inputs = data.inputIds; -} - void Axis::cleanup() { QBackendNode::setEnabled(false); @@ -75,11 +67,11 @@ void Axis::cleanup() void Axis::setAxisValue(float axisValue) { - if (isEnabled() && (axisValue != m_axisValue)) { + if (isEnabled() && (!qFuzzyCompare(axisValue, m_axisValue))) { m_axisValue = axisValue; // Send a change to the frontend - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); + auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); // TODOSYNC replace with direct access e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); e->setPropertyName("value"); e->setValue(m_axisValue); @@ -87,26 +79,15 @@ void Axis::setAxisValue(float axisValue) } } -void Axis::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +void Axis::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - switch (e->type()) { - case Qt3DCore::PropertyValueAdded: { - const auto change = qSharedPointerCast<Qt3DCore::QPropertyNodeAddedChange>(e); - if (change->propertyName() == QByteArrayLiteral("input")) - m_inputs.push_back(change->addedNodeId()); - break; - } + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + const Qt3DInput::QAxis *node = qobject_cast<const Qt3DInput::QAxis *>(frontEnd); + if (!node) + return; - case Qt3DCore::PropertyValueRemoved: { - const auto change = qSharedPointerCast<Qt3DCore::QPropertyNodeRemovedChange>(e); - if (change->propertyName() == QByteArrayLiteral("input")) - m_inputs.removeOne(change->removedNodeId()); - } - - default: - break; - } - QBackendNode::sceneChangeEvent(e); + auto ids = Qt3DCore::qIdsForNodes(node->inputs()); + m_inputs = ids; } } // namespace Input diff --git a/src/input/backend/axis_p.h b/src/input/backend/axis_p.h index b83405060..da4ec9ac6 100644 --- a/src/input/backend/axis_p.h +++ b/src/input/backend/axis_p.h @@ -51,7 +51,7 @@ // We mean it. // -#include <Qt3DCore/qbackendnode.h> +#include <Qt3DInput/private/backendnode_p.h> #include <Qt3DCore/qnodeid.h> QT_BEGIN_NAMESPACE @@ -60,7 +60,7 @@ namespace Qt3DInput { namespace Input { -class Q_AUTOTEST_EXPORT Axis : public Qt3DCore::QBackendNode +class Q_AUTOTEST_EXPORT Axis : public BackendNode { public: Axis(); @@ -68,11 +68,9 @@ public: inline QVector<Qt3DCore::QNodeId> inputs() const { return m_inputs; } inline float axisValue() const { return m_axisValue; } void setAxisValue(float axisValue); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - QVector<Qt3DCore::QNodeId> m_inputs; float m_axisValue; }; diff --git a/src/input/backend/backend.pri b/src/input/backend/backend.pri index 71c1a9a1c..e1ddee9c7 100644 --- a/src/input/backend/backend.pri +++ b/src/input/backend/backend.pri @@ -1,4 +1,5 @@ HEADERS += \ + $$PWD/backendnode_p.h \ $$PWD/keyboarddevice_p.h \ $$PWD/keyboardhandler_p.h \ $$PWD/inputhandler_p.h \ @@ -39,6 +40,7 @@ HEADERS += \ $$PWD/axisaccumulatorjob_p.h SOURCES += \ + $$PWD/backendnode.cpp \ $$PWD/keyboarddevice.cpp \ $$PWD/keyboardhandler.cpp \ $$PWD/inputhandler.cpp \ diff --git a/src/input/backend/backendnode.cpp b/src/input/backend/backendnode.cpp new file mode 100644 index 000000000..aa440ed51 --- /dev/null +++ b/src/input/backend/backendnode.cpp @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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 "backendnode_p.h" +#include <Qt3DCore/qnode.h> +#include <Qt3DCore/private/qbackendnode_p.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DInput { +namespace Input { + +BackendNode::BackendNode(Mode mode) + : Qt3DCore::QBackendNode(mode) +{ +} + +BackendNode::BackendNode(Qt3DCore::QBackendNodePrivate &dd) + : Qt3DCore::QBackendNode(dd) +{ + +} + +BackendNode::~BackendNode() +{ +} + +void BackendNode::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) +{ + Q_UNUSED(firstTime) + + d_ptr->setEnabled(frontEnd->isEnabled()); +} + +} // namespace Input +} // namespace Qt3DInput + +QT_END_NAMESPACE diff --git a/src/input/backend/backendnode_p.h b/src/input/backend/backendnode_p.h new file mode 100644 index 000000000..a7749852b --- /dev/null +++ b/src/input/backend/backendnode_p.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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 QT3DINPUT_INPUT_BACKENDNODE_H +#define QT3DINPUT_INPUT_BACKENDNODE_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 <Qt3DInput/private/qt3dinput_global_p.h> +#include <Qt3DCore/qbackendnode.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DInput { +namespace Input { + +class Q_3DINPUTSHARED_PRIVATE_EXPORT BackendNode : public Qt3DCore::QBackendNode +{ +public: + BackendNode(Qt3DCore::QBackendNode::Mode mode = ReadOnly); + ~BackendNode(); + + virtual void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime); + +protected: + explicit BackendNode(Qt3DCore::QBackendNodePrivate &dd); +}; + +} // namespace Input +} // namespace Qt3DInput + +QT_END_NAMESPACE + +#endif // QT3DINPUT_INPUT_BACKENDNODE_H diff --git a/src/input/frontend/qaxis.cpp b/src/input/frontend/qaxis.cpp index 01e28e9cf..082ad4f67 100644 --- a/src/input/frontend/qaxis.cpp +++ b/src/input/frontend/qaxis.cpp @@ -83,6 +83,10 @@ namespace Qt3DInput { QAxis::QAxis(Qt3DCore::QNode *parent) : Qt3DCore::QNode(*new QAxisPrivate(), parent) { + Q_D(QAxis); + connect(this, &QAxis::enabledChanged, [d]() { + d->setValue(0.); + }); } /*! \internal */ @@ -113,12 +117,7 @@ void QAxis::addInput(QAbstractAxisInput *input) // Ensures proper bookkeeping d->registerDestructionHelper(input, &QAxis::removeInput, d->m_inputs); - - if (d->m_changeArbiter != nullptr) { - const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(id(), input); - change->setPropertyName("input"); - d->notifyObservers(change); - } + d->update(); } } @@ -140,11 +139,7 @@ void QAxis::removeInput(QAbstractAxisInput *input) Q_D(QAxis); if (d->m_inputs.contains(input)) { - if (d->m_changeArbiter != nullptr) { - const auto change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(id(), input); - change->setPropertyName("input"); - d->notifyObservers(change); - } + d->update(); d->m_inputs.removeOne(input); diff --git a/src/input/frontend/qinputaspect.cpp b/src/input/frontend/qinputaspect.cpp index e7ff70326..c063f2580 100644 --- a/src/input/frontend/qinputaspect.cpp +++ b/src/input/frontend/qinputaspect.cpp @@ -61,6 +61,7 @@ #include <QtCore/QLibraryInfo> #include <QtCore/QPluginLoader> +#include <Qt3DInput/private/backendnode_p.h> #include <Qt3DInput/private/action_p.h> #include <Qt3DInput/private/actioninput_p.h> #include <Qt3DInput/private/axis_p.h> @@ -109,6 +110,13 @@ QInputAspectPrivate::QInputAspectPrivate() { } +void QInputAspectPrivate::syncDirtyFrontEndNode(QNode *node, QBackendNode *backend, bool firstTime) const +{ + Input::BackendNode *renderBackend = static_cast<Input::BackendNode *>(backend); + renderBackend->syncFromFrontEnd(node, firstTime); +} + + /*! \class Qt3DInput::QInputAspect \inherits Qt3DCore::QAbstractAspect @@ -141,7 +149,7 @@ QInputAspect::QInputAspect(QInputAspectPrivate &dd, QObject *parent) registerBackendType<QKeyboardHandler>(QBackendNodeMapperPtr(new Input::KeyboardHandlerFunctor(d_func()->m_inputHandler.data()))); registerBackendType<QMouseDevice>(QBackendNodeMapperPtr(new Input::MouseDeviceFunctor(this, d_func()->m_inputHandler.data()))); registerBackendType<QMouseHandler>(QBackendNodeMapperPtr(new Input::MouseHandlerFunctor(d_func()->m_inputHandler.data()))); - registerBackendType<QAxis>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::Axis, Input::AxisManager>(d_func()->m_inputHandler->axisManager()))); + registerBackendType<QAxis, true>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::Axis, Input::AxisManager>(d_func()->m_inputHandler->axisManager()))); registerBackendType<QAxisAccumulator>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::AxisAccumulator, Input::AxisAccumulatorManager>(d_func()->m_inputHandler->axisAccumulatorManager()))); registerBackendType<QAnalogAxisInput>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::AnalogAxisInput, Input::AnalogAxisInputManager>(d_func()->m_inputHandler->analogAxisInputManager()))); registerBackendType<QButtonAxisInput>(QBackendNodeMapperPtr(new Input::InputNodeFunctor<Input::ButtonAxisInput, Input::ButtonAxisInputManager>(d_func()->m_inputHandler->buttonAxisInputManager()))); diff --git a/src/input/frontend/qinputaspect_p.h b/src/input/frontend/qinputaspect_p.h index bcdd8d4ed..aee7e7909 100644 --- a/src/input/frontend/qinputaspect_p.h +++ b/src/input/frontend/qinputaspect_p.h @@ -69,6 +69,7 @@ class QInputAspectPrivate : public Qt3DCore::QAbstractAspectPrivate public: QInputAspectPrivate(); void loadInputDevicePlugins(); + void syncDirtyFrontEndNode(Qt3DCore::QNode *node, Qt3DCore::QBackendNode *backend, bool firstTime) const override; Q_DECLARE_PUBLIC(QInputAspect) QScopedPointer<Input::InputHandler> m_inputHandler; diff --git a/src/render/backend/cameralens.cpp b/src/render/backend/cameralens.cpp index f4815a4a9..7a5c1f7e6 100644 --- a/src/render/backend/cameralens.cpp +++ b/src/render/backend/cameralens.cpp @@ -41,7 +41,6 @@ #include <Qt3DRender/qcameralens.h> #include <Qt3DRender/private/nodemanagers_p.h> #include <Qt3DRender/private/managers_p.h> -#include <Qt3DRender/private/qcameralens_p.h> #include <Qt3DRender/private/renderlogging_p.h> #include <Qt3DRender/private/renderer_p.h> #include <Qt3DRender/private/entity_p.h> @@ -119,12 +118,43 @@ Matrix4x4 CameraLens::viewMatrix(const Matrix4x4 &worldTransform) return Matrix4x4(m); } -void CameraLens::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void CameraLens::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QCameraLensData>>(change); - const auto &data = typedChange->data; - m_projection = Matrix4x4(data.projectionMatrix); - m_exposure = data.exposure; + const QCameraLens *node = qobject_cast<const QCameraLens *>(frontEnd); + if (!node) + return; + + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + + const Matrix4x4 projectionMatrix(node->projectionMatrix()); + if (projectionMatrix != m_projection) { + m_projection = projectionMatrix; + markDirty(AbstractRenderer::AllDirty); + } + + if (node->exposure() != m_exposure) { + m_exposure = node->exposure(); + markDirty(AbstractRenderer::AllDirty); + } + + const QCameraLensPrivate *d = static_cast<const QCameraLensPrivate *>(QNodePrivate::get(node)); + if (d->m_pendingViewAllCommand != m_pendingViewAllCommand) { + m_pendingViewAllCommand = d->m_pendingViewAllCommand; + + if (m_pendingViewAllCommand) { + const QVariant v = m_pendingViewAllCommand.data; + const QNodeCommand::CommandId commandId = m_pendingViewAllCommand.commandId; + + if (m_pendingViewAllCommand.name == QLatin1String("QueryRootBoundingVolume")) { + const QNodeId id = v.value<QNodeId>(); + computeSceneBoundingVolume({}, id, commandId); + } else if (m_pendingViewAllCommand.name == QLatin1String("QueryEntityBoundingVolume")) { + const QVector<QNodeId> ids = v.value<QVector<QNodeId>>(); + if (ids.size() == 2) + computeSceneBoundingVolume(ids[0], ids[1], commandId); + } + } + } } void CameraLens::computeSceneBoundingVolume(QNodeId entityId, @@ -152,15 +182,16 @@ void CameraLens::computeSceneBoundingVolume(QNodeId entityId, void CameraLens::notifySceneBoundingVolume(const Sphere &sphere, QNodeCommand::CommandId commandId) { - if (m_pendingViewAllCommand != commandId) + if (!m_pendingViewAllCommand || m_pendingViewAllCommand.commandId != commandId) return; if (sphere.radius() > 0.f) { QVector<float> data = { sphere.center().x(), sphere.center().y(), sphere.center().z(), sphere.radius() }; QVariant v; v.setValue(data); - sendCommand(QLatin1String("ViewAll"), v, m_pendingViewAllCommand); + sendCommand(QLatin1String("ViewAll"), v, m_pendingViewAllCommand.commandId); } + m_pendingViewAllCommand = {}; } void CameraLens::setProjection(const Matrix4x4 &projection) @@ -173,47 +204,6 @@ void CameraLens::setExposure(float exposure) m_exposure = exposure; } -void CameraLens::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - switch (e->type()) { - case PropertyUpdated: { - QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e); - - if (propertyChange->propertyName() == QByteArrayLiteral("projectionMatrix")) { - QMatrix4x4 projectionMatrix = propertyChange->value().value<QMatrix4x4>(); - m_projection = Matrix4x4(projectionMatrix); - } else if (propertyChange->propertyName() == QByteArrayLiteral("exposure")) { - setExposure(propertyChange->value().toFloat()); - } - - markDirty(AbstractRenderer::AllDirty); - } - break; - - case CommandRequested: { - QNodeCommandPtr command = qSharedPointerCast<QNodeCommand>(e); - - if (command->name() == QLatin1String("QueryRootBoundingVolume")) { - m_pendingViewAllCommand = command->commandId(); - QVariant v = command->data(); - QNodeId id = v.value<QNodeId>(); - computeSceneBoundingVolume({}, id, command->commandId()); - } else if (command->name() == QLatin1String("QueryEntityBoundingVolume")) { - m_pendingViewAllCommand = command->commandId(); - QVariant v = command->data(); - QVector<QNodeId> ids = v.value<QVector<QNodeId>>(); - if (ids.size() == 2) - computeSceneBoundingVolume(ids[0], ids[1], command->commandId()); - } - } - break; - - default: - break; - } - BackendNode::sceneChangeEvent(e); -} - bool CameraLens::viewMatrixForCamera(EntityManager* manager, Qt3DCore::QNodeId cameraId, Matrix4x4 &viewMatrix, Matrix4x4 &projectionMatrix) { diff --git a/src/render/backend/cameralens_p.h b/src/render/backend/cameralens_p.h index 80a1715cf..bd721d5e9 100644 --- a/src/render/backend/cameralens_p.h +++ b/src/render/backend/cameralens_p.h @@ -54,6 +54,7 @@ #include <Qt3DRender/private/backendnode_p.h> #include <Qt3DCore/private/qnodecommand_p.h> #include <Qt3DCore/private/matrix4x4_p.h> +#include <Qt3DRender/private/qcameralens_p.h> #include <QRectF> QT_BEGIN_NAMESPACE @@ -96,21 +97,20 @@ public: void setExposure(float exposure); inline float exposure() const { return m_exposure; } + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; void notifySceneBoundingVolume(const Sphere &sphere, Qt3DCore::QNodeCommand::CommandId commandId); static bool viewMatrixForCamera(EntityManager *manager, Qt3DCore::QNodeId cameraId, Matrix4x4 &viewMatrix, Matrix4x4 &projectionMatrix); private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; void computeSceneBoundingVolume(Qt3DCore::QNodeId entityId, Qt3DCore::QNodeId cameraId, Qt3DCore::QNodeCommand::CommandId commandId); QRenderAspect *m_renderAspect; - Qt3DCore::QNodeCommand::CommandId m_pendingViewAllCommand; + CameraLensCommand m_pendingViewAllCommand; Matrix4x4 m_projection; float m_exposure; }; diff --git a/src/render/backend/computecommand.cpp b/src/render/backend/computecommand.cpp index 7079d0308..386c25fec 100644 --- a/src/render/backend/computecommand.cpp +++ b/src/render/backend/computecommand.cpp @@ -73,35 +73,35 @@ void ComputeCommand::cleanup() m_runType = QComputeCommand::Continuous; } -void ComputeCommand::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void ComputeCommand::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QComputeCommandData>>(change); - const auto &data = typedChange->data; - m_workGroups[0] = data.workGroupX; - m_workGroups[1] = data.workGroupY; - m_workGroups[2] = data.workGroupZ; - m_runType = data.runType; - m_frameCount = data.frameCount; - markDirty(AbstractRenderer::ComputeDirty); -} + const QComputeCommand *node = qobject_cast<const QComputeCommand *>(frontEnd); + if (!node) + return; -void ComputeCommand::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e); - if (e->type() == Qt3DCore::PropertyUpdated) { - if (propertyChange->propertyName() == QByteArrayLiteral("workGroupX")) - m_workGroups[0] = propertyChange->value().toInt(); - else if (propertyChange->propertyName() == QByteArrayLiteral("workGroupY")) - m_workGroups[1] = propertyChange->value().toInt(); - else if (propertyChange->propertyName() == QByteArrayLiteral("workGroupZ")) - m_workGroups[2] = propertyChange->value().toInt(); - else if (propertyChange->propertyName() == QByteArrayLiteral("frameCount")) - m_frameCount = propertyChange->value().toInt(); - else if (propertyChange->propertyName() == QByteArrayLiteral("runType")) - m_runType = static_cast<QComputeCommand::RunType>(propertyChange->value().toInt()); + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + + if (m_workGroups[0] != node->workGroupX()) { + m_workGroups[0] = node->workGroupX(); + markDirty(AbstractRenderer::ComputeDirty); + } + if (m_workGroups[1] != node->workGroupY()) { + m_workGroups[1] = node->workGroupY(); + markDirty(AbstractRenderer::ComputeDirty); + } + if (m_workGroups[2] != node->workGroupZ()) { + m_workGroups[2] = node->workGroupZ(); + markDirty(AbstractRenderer::ComputeDirty); + } + if (node->runType() != m_runType) { + m_runType = node->runType(); + markDirty(AbstractRenderer::ComputeDirty); + } + const QComputeCommandPrivate *d = static_cast<const QComputeCommandPrivate *>(Qt3DCore::QNodePrivate::get(node)); + if (d->m_frameCount != m_frameCount) { + m_frameCount = d->m_frameCount; markDirty(AbstractRenderer::ComputeDirty); } - BackendNode::sceneChangeEvent(e); } // Called from buildComputeRenderCommands in a job diff --git a/src/render/backend/computecommand_p.h b/src/render/backend/computecommand_p.h index 10e10fd25..dc2069928 100644 --- a/src/render/backend/computecommand_p.h +++ b/src/render/backend/computecommand_p.h @@ -69,7 +69,7 @@ public: ~ComputeCommand(); void cleanup(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; inline int x() const Q_DECL_NOTHROW { return m_workGroups[0]; } inline int y() const Q_DECL_NOTHROW { return m_workGroups[1]; } @@ -81,7 +81,6 @@ public: void updateFrameCount(); private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) override; int m_workGroups[3]; int m_frameCount; QComputeCommand::RunType m_runType; diff --git a/src/render/backend/layer.cpp b/src/render/backend/layer.cpp index 24ec284fc..f0c844906 100644 --- a/src/render/backend/layer.cpp +++ b/src/render/backend/layer.cpp @@ -67,27 +67,22 @@ void Layer::cleanup() QBackendNode::setEnabled(false); } -void Layer::sceneChangeEvent(const QSceneChangePtr &e) +void Layer::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - if (e->type() == PropertyUpdated) { - QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e); - QByteArray propertyName = propertyChange->propertyName(); - if (propertyName == QByteArrayLiteral("recursive")) { - m_recursive = propertyChange->value().toBool(); - markDirty(AbstractRenderer::LayersDirty); - } - if (propertyName == QByteArrayLiteral("enabled")) - markDirty(AbstractRenderer::LayersDirty); - } - BackendNode::sceneChangeEvent(e); -} + const QLayer *node = qobject_cast<const QLayer *>(frontEnd); + if (!node) + return; -void Layer::initializeFromPeer(const QNodeCreatedChangeBasePtr &change) -{ - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QLayerData>>(change); - const auto &data = typedChange->data; - m_recursive = data.m_recursive; - markDirty(AbstractRenderer::LayersDirty); + const bool oldEnabled = isEnabled(); + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + + if (isEnabled() != oldEnabled || firstTime) + markDirty(AbstractRenderer::LayersDirty); + + if (node->recursive() != m_recursive) { + m_recursive = node->recursive(); + markDirty(AbstractRenderer::LayersDirty); + } } bool Layer::recursive() const diff --git a/src/render/backend/layer_p.h b/src/render/backend/layer_p.h index 1513157f9..8631e2d92 100644 --- a/src/render/backend/layer_p.h +++ b/src/render/backend/layer_p.h @@ -76,11 +76,9 @@ public: bool recursive() const; void setRecursive(bool recursive); -protected: - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) override; bool m_recursive; }; diff --git a/src/render/backend/levelofdetail.cpp b/src/render/backend/levelofdetail.cpp index 157bfc004..08410edf9 100644 --- a/src/render/backend/levelofdetail.cpp +++ b/src/render/backend/levelofdetail.cpp @@ -42,6 +42,7 @@ #include <Qt3DRender/private/qlevelofdetail_p.h> #include <Qt3DRender/private/stringtoint_p.h> #include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DRender/QCamera> #include <QVariant> QT_BEGIN_NAMESPACE @@ -64,41 +65,48 @@ LevelOfDetail::~LevelOfDetail() cleanup(); } -void LevelOfDetail::initializeFromPeer(const QNodeCreatedChangeBasePtr &change) +void LevelOfDetail::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QLevelOfDetailData>>(change); - const auto &data = typedChange->data; - m_camera = data.camera; - m_currentIndex = data.currentIndex; - m_thresholdType = data.thresholdType; - m_thresholds = data.thresholds; - m_volumeOverride = data.volumeOverride; -} + const QLevelOfDetail *node = qobject_cast<const QLevelOfDetail *>(frontEnd); + if (!node) + return; -void LevelOfDetail::cleanup() -{ - QBackendNode::setEnabled(false); -} + const bool oldEnabled = isEnabled(); + BackendNode::syncFromFrontEnd(frontEnd, firstTime); -void LevelOfDetail::sceneChangeEvent(const QSceneChangePtr &e) -{ - if (e->type() == PropertyUpdated) { - const QPropertyUpdatedChangePtr &propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (propertyChange->propertyName() == QByteArrayLiteral("currentIndex")) - m_currentIndex = propertyChange->value().value<int>(); - else if (propertyChange->propertyName() == QByteArrayLiteral("camera")) - m_camera = propertyChange->value().value<Qt3DCore::QNodeId>(); - else if (propertyChange->propertyName() == QByteArrayLiteral("thresholdType")) - m_thresholdType = propertyChange->value().value<QLevelOfDetail::ThresholdType>(); - else if (propertyChange->propertyName() == QByteArrayLiteral("thresholds")) - m_thresholds = propertyChange->value().value<QVector<qreal>>(); - else if (propertyChange->propertyName() == QByteArrayLiteral("volumeOverride")) - m_volumeOverride = propertyChange->value().value<Qt3DRender::QLevelOfDetailBoundingSphere>(); + const Qt3DCore::QNodeId cameraId = Qt3DCore::qIdForNode(node->camera()); + if (cameraId != m_camera) { + m_camera = cameraId; + markDirty(AbstractRenderer::GeometryDirty); + } + + if (node->currentIndex() != m_currentIndex) { + m_currentIndex = node->currentIndex(); + markDirty(AbstractRenderer::GeometryDirty); + } + + if (node->thresholdType() != m_thresholdType) { + m_thresholdType = node->thresholdType(); + markDirty(AbstractRenderer::GeometryDirty); } - markDirty(AbstractRenderer::GeometryDirty); + if (node->thresholds() != m_thresholds) { + m_thresholds = node->thresholds(); + markDirty(AbstractRenderer::GeometryDirty); + } - BackendNode::sceneChangeEvent(e); + if (node->volumeOverride() != m_volumeOverride) { + m_volumeOverride = node->volumeOverride(); + markDirty(AbstractRenderer::GeometryDirty); + } + + if (isEnabled() != oldEnabled || firstTime) + markDirty(AbstractRenderer::LayersDirty); +} + +void LevelOfDetail::cleanup() +{ + QBackendNode::setEnabled(false); } void LevelOfDetail::setCurrentIndex(int currentIndex) diff --git a/src/render/backend/levelofdetail_p.h b/src/render/backend/levelofdetail_p.h index 4cf835d9b..8399e19b7 100644 --- a/src/render/backend/levelofdetail_p.h +++ b/src/render/backend/levelofdetail_p.h @@ -73,7 +73,7 @@ public: LevelOfDetail(); ~LevelOfDetail(); void cleanup(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) final; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; Qt3DCore::QNodeId camera() const { return m_camera; } int currentIndex() const { return m_currentIndex; } @@ -86,7 +86,6 @@ public: void setCurrentIndex(int currentIndex); private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; Qt3DCore::QNodeId m_camera; int m_currentIndex; QLevelOfDetail::ThresholdType m_thresholdType; diff --git a/src/render/backend/rendersettings.cpp b/src/render/backend/rendersettings.cpp index 2b8067ce8..702be9c60 100644 --- a/src/render/backend/rendersettings.cpp +++ b/src/render/backend/rendersettings.cpp @@ -63,42 +63,42 @@ RenderSettings::RenderSettings() { } -void RenderSettings::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void RenderSettings::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QRenderSettingsData>>(change); - const auto &data = typedChange->data; - m_activeFrameGraph = data.activeFrameGraphId; - m_renderPolicy = data.renderPolicy; - m_pickMethod = data.pickMethod; - m_pickResultMode = data.pickResultMode; - m_pickWorldSpaceTolerance = data.pickWorldSpaceTolerance; - m_faceOrientationPickingMode = data.faceOrientationPickingMode; -} + const QRenderSettings *node = qobject_cast<const QRenderSettings *>(frontEnd); + if (!node) + return; -void RenderSettings::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - if (e->type() == PropertyUpdated) { - QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (propertyChange->propertyName() == QByteArrayLiteral("pickMethod")) - m_pickMethod = propertyChange->value().value<QPickingSettings::PickMethod>(); - else if (propertyChange->propertyName() == QByteArrayLiteral("pickResult")) - m_pickResultMode = propertyChange->value().value<QPickingSettings::PickResultMode>(); - else if (propertyChange->propertyName() == QByteArrayLiteral("faceOrientationPickingMode")) - m_faceOrientationPickingMode = propertyChange->value().value<QPickingSettings::FaceOrientationPickingMode>(); - else if (propertyChange->propertyName() == QByteArrayLiteral("pickWorldSpaceTolerance")) - m_pickWorldSpaceTolerance = propertyChange->value().toFloat(); - else if (propertyChange->propertyName() == QByteArrayLiteral("activeFrameGraph")) - m_activeFrameGraph = propertyChange->value().value<QNodeId>(); - else if (propertyChange->propertyName() == QByteArrayLiteral("renderPolicy")) - m_renderPolicy = propertyChange->value().value<QRenderSettings::RenderPolicy>(); - markDirty(AbstractRenderer::AllDirty); - } else if (e->type() == CommandRequested) { - QNodeCommandPtr command = qSharedPointerCast<QNodeCommand>(e); - if (command->name() == QLatin1String("InvalidateFrame")) - markDirty(AbstractRenderer::AllDirty); + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + + const Qt3DCore::QNodeId activeFGId = Qt3DCore::qIdForNode(node->activeFrameGraph()); + if (activeFGId != m_activeFrameGraph) { + m_activeFrameGraph = activeFGId; + } + + if (node->renderPolicy() != m_renderPolicy) { + m_renderPolicy = node->renderPolicy(); + } + + if (node->pickingSettings()->pickMethod() != m_pickMethod) { + m_pickMethod = node->pickingSettings()->pickMethod(); + } + + if (node->pickingSettings()->pickResultMode() != m_pickResultMode) { + m_pickResultMode = node->pickingSettings()->pickResultMode(); + } + + if (node->pickingSettings()->worldSpaceTolerance() != m_pickWorldSpaceTolerance) { + m_pickWorldSpaceTolerance = node->pickingSettings()->worldSpaceTolerance(); + } + + if (node->pickingSettings()->faceOrientationPickingMode() != m_faceOrientationPickingMode) { + m_faceOrientationPickingMode = node->pickingSettings()->faceOrientationPickingMode(); } - BackendNode::sceneChangeEvent(e); + // Either because something above as changed or if QRenderSettingsPrivate::invalidFrame() + // was called + markDirty(AbstractRenderer::AllDirty); } RenderSettingsFunctor::RenderSettingsFunctor(AbstractRenderer *renderer) diff --git a/src/render/backend/rendersettings_p.h b/src/render/backend/rendersettings_p.h index d2880c134..1c8c0ca72 100644 --- a/src/render/backend/rendersettings_p.h +++ b/src/render/backend/rendersettings_p.h @@ -67,7 +67,7 @@ class Q_AUTOTEST_EXPORT RenderSettings : public BackendNode public: RenderSettings(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; Qt3DCore::QNodeId activeFrameGraphID() const { return m_activeFrameGraph; } QRenderSettings::RenderPolicy renderPolicy() const { return m_renderPolicy; } @@ -80,8 +80,6 @@ public: void setActiveFrameGraphId(Qt3DCore::QNodeId frameGraphNodeId) { m_activeFrameGraph = frameGraphNodeId; } private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - QRenderSettings::RenderPolicy m_renderPolicy; QPickingSettings::PickMethod m_pickMethod; QPickingSettings::PickResultMode m_pickResultMode; diff --git a/src/render/backend/rendertarget.cpp b/src/render/backend/rendertarget.cpp index b0565a26b..206f64e4e 100644 --- a/src/render/backend/rendertarget.cpp +++ b/src/render/backend/rendertarget.cpp @@ -58,11 +58,21 @@ RenderTarget::RenderTarget() { } -void RenderTarget::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void RenderTarget::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QRenderTargetData>>(change); - const auto &data = typedChange->data; - m_renderOutputs = data.outputIds; + const QRenderTarget *node = qobject_cast<const QRenderTarget *>(frontEnd); + if (!node) + return; + + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + + auto outputIds = qIdsForNodes(node->outputs()); + std::sort(std::begin(outputIds), std::end(outputIds)); + + if (m_renderOutputs != outputIds) { + m_renderOutputs = outputIds; + markDirty(AbstractRenderer::AllDirty); + } } void RenderTarget::cleanup() @@ -87,33 +97,6 @@ QVector<Qt3DCore::QNodeId> RenderTarget::renderOutputs() const return m_renderOutputs; } -void RenderTarget::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - switch (e->type()) { - case Qt3DCore::PropertyValueAdded: { - const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e); - if (change->propertyName() == QByteArrayLiteral("output")) { - appendRenderOutput(change->addedNodeId()); - markDirty(AbstractRenderer::AllDirty); - } - break; - } - - case Qt3DCore::PropertyValueRemoved: { - const auto change = qSharedPointerCast<QPropertyNodeRemovedChange>(e); - if (change->propertyName() == QByteArrayLiteral("output")) { - removeRenderOutput(change->removedNodeId()); - markDirty(AbstractRenderer::AllDirty); - } - break; - } - - default: - break; - } - BackendNode::sceneChangeEvent(e); -} - } // namespace Render } // namespace Qt3DRender diff --git a/src/render/backend/rendertarget_p.h b/src/render/backend/rendertarget_p.h index 5e3e63582..30769dcfc 100644 --- a/src/render/backend/rendertarget_p.h +++ b/src/render/backend/rendertarget_p.h @@ -76,11 +76,9 @@ public: QVector<Qt3DCore::QNodeId> renderOutputs() const; - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - QVector<Qt3DCore::QNodeId> m_renderOutputs; }; diff --git a/src/render/backend/rendertargetoutput.cpp b/src/render/backend/rendertargetoutput.cpp index cba92596d..edfc7132e 100644 --- a/src/render/backend/rendertargetoutput.cpp +++ b/src/render/backend/rendertargetoutput.cpp @@ -55,15 +55,39 @@ RenderTargetOutput::RenderTargetOutput() { } -void RenderTargetOutput::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void RenderTargetOutput::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QRenderTargetOutputData>>(change); - const auto &data = typedChange->data; - m_attachmentData.m_point = data.attachmentPoint; - m_attachmentData.m_mipLevel = data.mipLevel; - m_attachmentData.m_layer = data.layer; - m_attachmentData.m_face = data.face; - m_attachmentData.m_textureUuid = data.textureId; + const QRenderTargetOutput *node = qobject_cast<const QRenderTargetOutput *>(frontEnd); + if (!node) + return; + + const bool oldEnabled = isEnabled(); + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + + if (node->attachmentPoint() != m_attachmentData.m_point) { + m_attachmentData.m_point = node->attachmentPoint(); + markDirty(AbstractRenderer::AllDirty); + } + if (node->mipLevel() != m_attachmentData.m_mipLevel) { + m_attachmentData.m_mipLevel = node->mipLevel(); + markDirty(AbstractRenderer::AllDirty); + } + if (node->layer() != m_attachmentData.m_layer) { + m_attachmentData.m_layer = node->layer(); + markDirty(AbstractRenderer::AllDirty); + } + if (node->face() != m_attachmentData.m_face) { + m_attachmentData.m_face = node->face(); + markDirty(AbstractRenderer::AllDirty); + } + const auto textureId = Qt3DCore::qIdForNode(node->texture()); + if (textureId != m_attachmentData.m_textureUuid) { + m_attachmentData.m_textureUuid = textureId; + markDirty(AbstractRenderer::AllDirty); + } + + if (oldEnabled != isEnabled()) + markDirty(AbstractRenderer::AllDirty); } Qt3DCore::QNodeId RenderTargetOutput::textureUuid() const @@ -96,31 +120,6 @@ QRenderTargetOutput::AttachmentPoint RenderTargetOutput::point() const return m_attachmentData.m_point; } -void RenderTargetOutput::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (e->type() == PropertyUpdated) { - if (propertyChange->propertyName() == QByteArrayLiteral("type")) { - m_attachmentData.m_point = static_cast<QRenderTargetOutput::AttachmentPoint>(propertyChange->value().toInt()); - } - else if (propertyChange->propertyName() == QByteArrayLiteral("texture")) { - m_attachmentData.m_textureUuid = propertyChange->value().value<QNodeId>(); - } - else if (propertyChange->propertyName() == QByteArrayLiteral("mipLevel")) { - m_attachmentData.m_mipLevel = propertyChange->value().toInt(); - } - else if (propertyChange->propertyName() == QByteArrayLiteral("layer")) { - m_attachmentData.m_layer = propertyChange->value().toInt(); - } - else if (propertyChange->propertyName() == QByteArrayLiteral("face")) { - m_attachmentData.m_face = static_cast<QAbstractTexture::CubeMapFace>(propertyChange->value().toInt()); - } - markDirty(AbstractRenderer::AllDirty); - } - - BackendNode::sceneChangeEvent(e); -} - Qt3DRender::Render::Attachment *RenderTargetOutput::attachment() { return &m_attachmentData; diff --git a/src/render/backend/rendertargetoutput_p.h b/src/render/backend/rendertargetoutput_p.h index 20476547b..d72f6d231 100644 --- a/src/render/backend/rendertargetoutput_p.h +++ b/src/render/backend/rendertargetoutput_p.h @@ -76,12 +76,11 @@ public: QString name() const; QAbstractTexture::CubeMapFace face() const; QRenderTargetOutput::AttachmentPoint point() const; - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; Attachment *attachment(); const Attachment *attachment() const; private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; Qt3DCore::QNodeId m_attachmentUuid; Attachment m_attachmentData; }; diff --git a/src/render/framegraph/clearbuffers.cpp b/src/render/framegraph/clearbuffers.cpp index 98de30906..7d018c935 100644 --- a/src/render/framegraph/clearbuffers.cpp +++ b/src/render/framegraph/clearbuffers.cpp @@ -50,6 +50,8 @@ namespace Render { static QVector4D vec4dFromColor(const QColor &color) { + if (!color.isValid()) + return QVector4D(0.0f, 0.0f, 0.0f, 1.0f); return QVector4D(color.redF(), color.greenF(), color.blueF(), color.alphaF()); } @@ -58,6 +60,8 @@ ClearBuffers::ClearBuffers() , m_type(QClearBuffers::None) , m_clearDepthValue(1.f) , m_clearStencilValue(0) + , m_clearColorAsColor(Qt::black) + , m_clearColor(vec4dFromColor(m_clearColorAsColor)) { } diff --git a/src/render/framegraph/framegraph.pri b/src/render/framegraph/framegraph.pri index e833d4590..bb833422f 100644 --- a/src/render/framegraph/framegraph.pri +++ b/src/render/framegraph/framegraph.pri @@ -68,6 +68,7 @@ HEADERS += \ $$PWD/qnopicking.h \ $$PWD/nopicking_p.h \ $$PWD/qsubtreeenabler.h \ + $$PWD/qsubtreeenabler_p.h \ $$PWD/subtreeenabler_p.h SOURCES += \ diff --git a/src/render/framegraph/framegraphvisitor.cpp b/src/render/framegraph/framegraphvisitor.cpp index 5ccad87e1..9af0297a0 100644 --- a/src/render/framegraph/framegraphvisitor.cpp +++ b/src/render/framegraph/framegraphvisitor.cpp @@ -41,6 +41,7 @@ #include "framegraphvisitor_p.h" #include "framegraphnode_p.h" +#include "subtreeenabler_p.h" #include <Qt3DRender/private/renderer_p.h> #include <Qt3DRender/private/managers_p.h> #include <QThreadPool> @@ -61,6 +62,7 @@ FrameGraphVisitor::FrameGraphVisitor(const FrameGraphManager *manager) QVector<FrameGraphNode *> FrameGraphVisitor::traverse(FrameGraphNode *root) { m_leaves.clear(); + m_enablersToDisable.clear(); Q_ASSERT_X(root, Q_FUNC_INFO, "The FrameGraphRoot is null"); @@ -72,10 +74,23 @@ QVector<FrameGraphNode *> FrameGraphVisitor::traverse(FrameGraphNode *root) return m_leaves; } +// intended to be called after traverse +// (returns data that is captured during the traverse) +QVector<FrameGraphNode *> &&FrameGraphVisitor::takeEnablersToDisable() +{ + return std::move(m_enablersToDisable); +} + void FrameGraphVisitor::visit(Render::FrameGraphNode *node) { - if (node->nodeType() == Render::FrameGraphNode::SubtreeEnabler && !node->isEnabled()) - return; + if (node->nodeType() == Render::FrameGraphNode::SubtreeEnabler) { + if (!node->isEnabled()) + return; + if (static_cast<SubtreeEnabler*>(node)->enablement() == QSubtreeEnabler::SingleShot) { + node->setEnabled(false); + m_enablersToDisable.push_back(node); + } + } // Recurse to children (if we have any), otherwise if this is a leaf node, // initiate a rendering from the current camera diff --git a/src/render/framegraph/framegraphvisitor_p.h b/src/render/framegraph/framegraphvisitor_p.h index f4c0d7796..5706a169d 100644 --- a/src/render/framegraph/framegraphvisitor_p.h +++ b/src/render/framegraph/framegraphvisitor_p.h @@ -72,12 +72,14 @@ public: explicit FrameGraphVisitor(const FrameGraphManager *nodeManager); QVector<FrameGraphNode *> traverse(FrameGraphNode *root); + QVector<FrameGraphNode *> &&takeEnablersToDisable(); private: void visit(Render::FrameGraphNode *node); const FrameGraphManager *m_manager; QVector<FrameGraphNode *> m_leaves; + QVector<FrameGraphNode *> m_enablersToDisable; }; } // namespace Render diff --git a/src/render/framegraph/qsubtreeenabler.cpp b/src/render/framegraph/qsubtreeenabler.cpp index 5355b6fbd..d2c25852b 100644 --- a/src/render/framegraph/qsubtreeenabler.cpp +++ b/src/render/framegraph/qsubtreeenabler.cpp @@ -37,8 +37,8 @@ ** ****************************************************************************/ -#include <Qt3DRender/qsubtreeenabler.h> -#include <Qt3DRender/private/qframegraphnode_p.h> +#include "qsubtreeenabler_p.h" +#include <Qt3DRender/qframegraphnodecreatedchange.h> QT_BEGIN_NAMESPACE @@ -100,7 +100,7 @@ namespace Qt3DRender */ QSubtreeEnabler::QSubtreeEnabler(Qt3DCore::QNode *parent) - : QFrameGraphNode(*new QFrameGraphNodePrivate, parent) + : QFrameGraphNode(*new QSubtreeEnablerPrivate, parent) { } @@ -108,6 +108,78 @@ QSubtreeEnabler::~QSubtreeEnabler() { } +/*! + \enum QSubtreeEnabler::Enablement + + Specifies whether subtree enablement is persistent or transient. + + \value Persistent + The value of enabled is persistent. This is the default. + + \value SingleShot + The value of enabled will last for a single frame and then be reset to false. + This might be used for a subtree drawing to an FBO, for example, to only update + the FBO when the relevant portions of the scene changed. +*/ + +/*! + \qmlproperty enumeration Qt3D.Render::SubtreeEnabler::enablement + Controls whether subtree enablement is persistent or transient. + + \value Persistent + The value of enabled is persistent. This is the default. + + \value SingleShot + The value of enabled will last for a single frame and then be reset to false. + This might be used for a subtree drawing to an FBO, for example, to only update + the FBO when the relevant portions of the scene changed. +*/ + +/*! + \property Qt3DRender::QSubtreeEnabler::enablement + Controls whether subtree enablement is persistent or transient. +*/ +QSubtreeEnabler::Enablement QSubtreeEnabler::enablement() const +{ + Q_D(const QSubtreeEnabler); + return d->m_enablement; +} + +void QSubtreeEnabler::setEnablement(QSubtreeEnabler::Enablement enablement) +{ + Q_D(QSubtreeEnabler); + if (d->m_enablement == enablement) + return; + d->m_enablement = enablement; + emit enablementChanged(d->m_enablement); +} + +/*! + \qmlmethod void Qt3D.Render::SubtreeEnabler::requestUpdate() + Requests that the subtree be enabled. + + A conveninence method intended to be used with \c SingleShot enablement. + */ + +/*! + Requests that the subtree be enabled. + + A conveninence method intended to be used with \c SingleShot enablement. + */ +void QSubtreeEnabler::requestUpdate() +{ + setEnabled(true); +} + +Qt3DCore::QNodeCreatedChangeBasePtr QSubtreeEnabler::createNodeCreationChange() const +{ + auto creationChange = QFrameGraphNodeCreatedChangePtr<QSubtreeEnablerData>::create(this); + auto &data = creationChange->data; + Q_D(const QSubtreeEnabler); + data.enablement = d->m_enablement; + return creationChange; +} + } //Qt3DRender QT_END_NAMESPACE diff --git a/src/render/framegraph/qsubtreeenabler.h b/src/render/framegraph/qsubtreeenabler.h index 82334b3da..558e3b8b7 100644 --- a/src/render/framegraph/qsubtreeenabler.h +++ b/src/render/framegraph/qsubtreeenabler.h @@ -47,12 +47,33 @@ QT_BEGIN_NAMESPACE namespace Qt3DRender { +class QSubtreeEnablerPrivate; + class Q_3DRENDERSHARED_EXPORT QSubtreeEnabler : public QFrameGraphNode { Q_OBJECT + Q_PROPERTY(Enablement enablement READ enablement WRITE setEnablement NOTIFY enablementChanged) public: explicit QSubtreeEnabler(Qt3DCore::QNode *parent = nullptr); ~QSubtreeEnabler(); + + enum Enablement { + Persistent, + SingleShot + }; + Q_ENUM(Enablement) + + Enablement enablement() const; + void setEnablement(Enablement enablement); + + Q_INVOKABLE void requestUpdate(); + +Q_SIGNALS: + void enablementChanged(Qt3DRender::QSubtreeEnabler::Enablement enablement); + +private: + Q_DECLARE_PRIVATE(QSubtreeEnabler) + Qt3DCore::QNodeCreatedChangeBasePtr createNodeCreationChange() const override; }; } //Qt3DRender diff --git a/src/render/framegraph/qsubtreeenabler_p.h b/src/render/framegraph/qsubtreeenabler_p.h new file mode 100644 index 000000000..72354fe89 --- /dev/null +++ b/src/render/framegraph/qsubtreeenabler_p.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Ford Motor Company +** 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_QSUBTREEENABLER_P_H +#define QT3DRENDER_QSUBTREEENABLER_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 "qsubtreeenabler.h" +#include <private/qframegraphnode_p.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class QSubtreeEnablerPrivate : public QFrameGraphNodePrivate +{ +public: + QSubtreeEnablerPrivate() = default; + + QSubtreeEnabler::Enablement m_enablement = QSubtreeEnabler::Persistent; + + Q_DECLARE_PUBLIC(QSubtreeEnabler) +}; + +struct QSubtreeEnablerData +{ + QSubtreeEnabler::Enablement enablement; +}; + +} // namespace Qt3DRender + +QT_END_NAMESPACE + +#endif // QT3DRENDER_QSUBTREEENABLER_P_H diff --git a/src/render/framegraph/rendersurfaceselector.cpp b/src/render/framegraph/rendersurfaceselector.cpp index 173da77d6..ed8a79eac 100644 --- a/src/render/framegraph/rendersurfaceselector.cpp +++ b/src/render/framegraph/rendersurfaceselector.cpp @@ -122,12 +122,7 @@ QSize RenderSurfaceSelector::renderTargetSize() const { if (m_renderTargetSize.isValid()) return m_renderTargetSize; - { - SurfaceLocker lock(m_surface); - if (lock.isSurfaceValid() && m_surface && m_surface->size().isValid()) - return m_surface->size(); - } - return QSize(); + return QSize(m_width, m_height); } } // namespace Render diff --git a/src/render/framegraph/subtreeenabler.cpp b/src/render/framegraph/subtreeenabler.cpp index e4b4e4ba7..160e1a5b5 100644 --- a/src/render/framegraph/subtreeenabler.cpp +++ b/src/render/framegraph/subtreeenabler.cpp @@ -38,6 +38,8 @@ ****************************************************************************/ #include "subtreeenabler_p.h" +#include <Qt3DRender/private/qsubtreeenabler_p.h> +#include <Qt3DCore/qpropertyupdatedchange.h> QT_BEGIN_NAMESPACE @@ -46,10 +48,43 @@ namespace Qt3DRender { namespace Render { SubtreeEnabler::SubtreeEnabler() - : FrameGraphNode(FrameGraphNode::SubtreeEnabler) + : FrameGraphNode(FrameGraphNode::SubtreeEnabler, FrameGraphNode::ReadWrite) { } +void SubtreeEnabler::sendDisableToFrontend() +{ + if (m_enablement != QSubtreeEnabler::SingleShot) + return; + + if (isEnabled()) + return; + + auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(peerId()); + e->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); + e->setPropertyName("enabled"); + e->setValue(false); + notifyObservers(e); +} + +void SubtreeEnabler::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) +{ + const QSubtreeEnabler *node = qobject_cast<const QSubtreeEnabler *>(frontEnd); + if (!node) + return; + + if (node->isEnabled() != isEnabled()) + markDirty(AbstractRenderer::AllDirty); + + FrameGraphNode::syncFromFrontEnd(frontEnd, firstTime); + + const auto enablement = node->enablement(); + if (enablement != m_enablement) { + m_enablement = enablement; + markDirty(AbstractRenderer::FrameGraphDirty); + } +} + } //Render } //Qt3DRender diff --git a/src/render/framegraph/subtreeenabler_p.h b/src/render/framegraph/subtreeenabler_p.h index 22782da12..2de8dfabf 100644 --- a/src/render/framegraph/subtreeenabler_p.h +++ b/src/render/framegraph/subtreeenabler_p.h @@ -51,6 +51,7 @@ // We mean it. // +#include <Qt3DRender/qsubtreeenabler.h> #include <Qt3DRender/private/framegraphnode_p.h> QT_BEGIN_NAMESPACE @@ -63,6 +64,13 @@ class Q_AUTOTEST_EXPORT SubtreeEnabler : public FrameGraphNode { public: SubtreeEnabler(); + QSubtreeEnabler::Enablement enablement() const { return m_enablement; } + void sendDisableToFrontend(); + + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; + +private: + QSubtreeEnabler::Enablement m_enablement = QSubtreeEnabler::Persistent; }; } //Render diff --git a/src/render/frontend/qcameralens.cpp b/src/render/frontend/qcameralens.cpp index 296421031..cf30b714a 100644 --- a/src/render/frontend/qcameralens.cpp +++ b/src/render/frontend/qcameralens.cpp @@ -228,13 +228,17 @@ QCameraLensPrivate::QCameraLensPrivate() { } + void QCameraLens::viewAll(Qt3DCore::QNodeId cameraId) { Q_D(QCameraLens); if (d->m_projectionType == PerspectiveProjection) { QVariant v; v.setValue(cameraId); - d->m_pendingViewAllCommand = sendCommand(QLatin1String("QueryRootBoundingVolume"), v); + d->m_pendingViewAllCommand = {QLatin1String("QueryRootBoundingVolume"), + v, + id()}; + d->update(); } } @@ -245,7 +249,10 @@ void QCameraLens::viewEntity(Qt3DCore::QNodeId entityId, Qt3DCore::QNodeId camer QVector<Qt3DCore::QNodeId> ids = {entityId, cameraId}; QVariant v; v.setValue(ids); - d->m_pendingViewAllCommand = sendCommand(QLatin1String("QueryEntityBoundingVolume"), v); + d->m_pendingViewAllCommand = {QLatin1String("QueryEntityBoundingVolume"), + v, + id()}; + d->update(); } } @@ -253,7 +260,7 @@ void QCameraLensPrivate::processViewAllCommand(Qt3DCore::QNodeCommand::CommandId const QVariant &data) { Q_Q(QCameraLens); - if (m_pendingViewAllCommand != commandId) + if (!m_pendingViewAllCommand || m_pendingViewAllCommand.commandId != commandId) return; QVector<float> boundingVolumeData = data.value< QVector<float> >(); @@ -262,7 +269,7 @@ void QCameraLensPrivate::processViewAllCommand(Qt3DCore::QNodeCommand::CommandId QVector3D center(boundingVolumeData[0], boundingVolumeData[1], boundingVolumeData[2]); float radius = boundingVolumeData[3]; Q_EMIT q->viewSphere(center, radius); - m_pendingViewAllCommand = Qt3DCore::QNodeCommand::CommandId(); + m_pendingViewAllCommand = {}; } /*! diff --git a/src/render/frontend/qcameralens_p.h b/src/render/frontend/qcameralens_p.h index 111ab6522..01fcac0e5 100644 --- a/src/render/frontend/qcameralens_p.h +++ b/src/render/frontend/qcameralens_p.h @@ -65,6 +65,25 @@ QT_BEGIN_NAMESPACE namespace Qt3DRender { +struct CameraLensCommand +{ + QString name; + QVariant data; + Qt3DCore::QNodeCommand::CommandId commandId; + + inline operator bool() const { return !name.isEmpty(); } +}; + +inline bool operator ==(const CameraLensCommand &a, const CameraLensCommand &b) noexcept +{ + return a.name == b.name && a.data == b.data && a.commandId == b.commandId; +} + +inline bool operator !=(const CameraLensCommand &a, const CameraLensCommand &b) noexcept +{ + return !(a == b); +} + class Q_3DRENDERSHARED_PRIVATE_EXPORT QCameraLensPrivate : public Qt3DCore::QComponentPrivate { public: @@ -106,7 +125,7 @@ public: float m_exposure; - Qt3DCore::QNodeCommand::CommandId m_pendingViewAllCommand; + CameraLensCommand m_pendingViewAllCommand; void processViewAllCommand(Qt3DCore::QNodeCommand::CommandId commandId, const QVariant &data); private: diff --git a/src/render/frontend/qcomputecommand.cpp b/src/render/frontend/qcomputecommand.cpp index 8b176cd4f..b0bec42d4 100644 --- a/src/render/frontend/qcomputecommand.cpp +++ b/src/render/frontend/qcomputecommand.cpp @@ -156,10 +156,7 @@ QComputeCommandPrivate::QComputeCommandPrivate() void QComputeCommandPrivate::setFrameCount(int frameCount) { m_frameCount = frameCount; - const auto propertyChange = Qt3DCore::QPropertyUpdatedChangePtr::create(m_id); - propertyChange->setPropertyName("frameCount"); - propertyChange->setValue(m_frameCount); - notifyObservers(propertyChange); + update(); } /*! diff --git a/src/render/frontend/qrenderaspect.cpp b/src/render/frontend/qrenderaspect.cpp index 67bcb6c02..70ec70b2b 100644 --- a/src/render/frontend/qrenderaspect.cpp +++ b/src/render/frontend/qrenderaspect.cpp @@ -255,20 +255,20 @@ void QRenderAspectPrivate::registerBackendTypes() q->registerBackendType<Qt3DCore::QEntity, true>(QSharedPointer<Render::RenderEntityFunctor>::create(m_renderer, m_nodeManagers)); q->registerBackendType<Qt3DCore::QTransform, true>(QSharedPointer<Render::NodeFunctor<Render::Transform, Render::TransformManager> >::create(m_renderer)); - q->registerBackendType<Qt3DRender::QCameraLens>(QSharedPointer<Render::CameraLensFunctor>::create(m_renderer, q)); - q->registerBackendType<QLayer>(QSharedPointer<Render::NodeFunctor<Render::Layer, Render::LayerManager> >::create(m_renderer)); - q->registerBackendType<QLevelOfDetail>(QSharedPointer<Render::NodeFunctor<Render::LevelOfDetail, Render::LevelOfDetailManager> >::create(m_renderer)); - q->registerBackendType<QLevelOfDetailSwitch>(QSharedPointer<Render::NodeFunctor<Render::LevelOfDetail, Render::LevelOfDetailManager> >::create(m_renderer)); - q->registerBackendType<QSceneLoader>(QSharedPointer<Render::RenderSceneFunctor>::create(m_renderer, m_nodeManagers->sceneManager())); - q->registerBackendType<QRenderTarget>(QSharedPointer<Render::NodeFunctor<Render::RenderTarget, Render::RenderTargetManager> >::create(m_renderer)); - q->registerBackendType<QRenderTargetOutput>(QSharedPointer<Render::NodeFunctor<Render::RenderTargetOutput, Render::AttachmentManager> >::create(m_renderer)); - q->registerBackendType<QRenderSettings>(QSharedPointer<Render::RenderSettingsFunctor>::create(m_renderer)); - q->registerBackendType<QRenderState>(QSharedPointer<Render::NodeFunctor<Render::RenderStateNode, Render::RenderStateManager> >::create(m_renderer)); + q->registerBackendType<Qt3DRender::QCameraLens, true>(QSharedPointer<Render::CameraLensFunctor>::create(m_renderer, q)); + q->registerBackendType<QLayer, true>(QSharedPointer<Render::NodeFunctor<Render::Layer, Render::LayerManager> >::create(m_renderer)); + q->registerBackendType<QLevelOfDetail, true>(QSharedPointer<Render::NodeFunctor<Render::LevelOfDetail, Render::LevelOfDetailManager> >::create(m_renderer)); + q->registerBackendType<QLevelOfDetailSwitch, true>(QSharedPointer<Render::NodeFunctor<Render::LevelOfDetail, Render::LevelOfDetailManager> >::create(m_renderer)); + q->registerBackendType<QSceneLoader, true>(QSharedPointer<Render::RenderSceneFunctor>::create(m_renderer, m_nodeManagers->sceneManager())); + q->registerBackendType<QRenderTarget, true>(QSharedPointer<Render::NodeFunctor<Render::RenderTarget, Render::RenderTargetManager> >::create(m_renderer)); + q->registerBackendType<QRenderTargetOutput, true>(QSharedPointer<Render::NodeFunctor<Render::RenderTargetOutput, Render::AttachmentManager> >::create(m_renderer)); + q->registerBackendType<QRenderSettings, true>(QSharedPointer<Render::RenderSettingsFunctor>::create(m_renderer)); + q->registerBackendType<QRenderState, true>(QSharedPointer<Render::NodeFunctor<Render::RenderStateNode, Render::RenderStateManager> >::create(m_renderer)); // Geometry + Compute q->registerBackendType<QAttribute, true>(QSharedPointer<Render::NodeFunctor<Render::Attribute, Render::AttributeManager> >::create(m_renderer)); q->registerBackendType<QBuffer, true>(QSharedPointer<Render::BufferFunctor>::create(m_renderer, m_nodeManagers->bufferManager())); - q->registerBackendType<QComputeCommand>(QSharedPointer<Render::NodeFunctor<Render::ComputeCommand, Render::ComputeCommandManager> >::create(m_renderer)); + q->registerBackendType<QComputeCommand, true>(QSharedPointer<Render::NodeFunctor<Render::ComputeCommand, Render::ComputeCommandManager> >::create(m_renderer)); q->registerBackendType<QGeometry, true>(QSharedPointer<Render::NodeFunctor<Render::Geometry, Render::GeometryManager> >::create(m_renderer)); q->registerBackendType<QGeometryRenderer, true>(QSharedPointer<Render::GeometryRendererFunctor>::create(m_renderer, m_nodeManagers->geometryRendererManager())); q->registerBackendType<Qt3DCore::QArmature, true>(QSharedPointer<Render::NodeFunctor<Render::Armature, Render::ArmatureManager>>::create(m_renderer)); @@ -277,22 +277,22 @@ void QRenderAspectPrivate::registerBackendTypes() // Textures q->registerBackendType<QAbstractTexture, true>(QSharedPointer<Render::TextureFunctor>::create(m_renderer, m_nodeManagers->textureManager())); - q->registerBackendType<QAbstractTextureImage>(QSharedPointer<Render::TextureImageFunctor>::create(m_renderer, + q->registerBackendType<QAbstractTextureImage, true>(QSharedPointer<Render::TextureImageFunctor>::create(m_renderer, m_nodeManagers->textureImageManager())); // Material system q->registerBackendType<QEffect, true>(QSharedPointer<Render::NodeFunctor<Render::Effect, Render::EffectManager> >::create(m_renderer)); - q->registerBackendType<QFilterKey>(QSharedPointer<Render::NodeFunctor<Render::FilterKey, Render::FilterKeyManager> >::create(m_renderer)); + q->registerBackendType<QFilterKey, true>(QSharedPointer<Render::NodeFunctor<Render::FilterKey, Render::FilterKeyManager> >::create(m_renderer)); q->registerBackendType<QAbstractLight, true>(QSharedPointer<Render::RenderLightFunctor>::create(m_renderer, m_nodeManagers)); q->registerBackendType<QEnvironmentLight, true>(QSharedPointer<Render::NodeFunctor<Render::EnvironmentLight, Render::EnvironmentLightManager> >::create(m_renderer)); q->registerBackendType<QMaterial, true>(QSharedPointer<Render::NodeFunctor<Render::Material, Render::MaterialManager> >::create(m_renderer)); q->registerBackendType<QParameter, true>(QSharedPointer<Render::NodeFunctor<Render::Parameter, Render::ParameterManager> >::create(m_renderer)); q->registerBackendType<QRenderPass, true>(QSharedPointer<Render::NodeFunctor<Render::RenderPass, Render::RenderPassManager> >::create(m_renderer)); q->registerBackendType<QShaderData>(QSharedPointer<Render::RenderShaderDataFunctor>::create(m_renderer, m_nodeManagers)); - q->registerBackendType<QShaderProgram>(QSharedPointer<Render::NodeFunctor<Render::Shader, Render::ShaderManager> >::create(m_renderer)); - q->registerBackendType<QShaderProgramBuilder>(QSharedPointer<Render::NodeFunctor<Render::ShaderBuilder, Render::ShaderBuilderManager> >::create(m_renderer)); + q->registerBackendType<QShaderProgram, true>(QSharedPointer<Render::NodeFunctor<Render::Shader, Render::ShaderManager> >::create(m_renderer)); + q->registerBackendType<QShaderProgramBuilder, true>(QSharedPointer<Render::NodeFunctor<Render::ShaderBuilder, Render::ShaderBuilderManager> >::create(m_renderer)); q->registerBackendType<QTechnique, true>(QSharedPointer<Render::TechniqueFunctor>::create(m_renderer, m_nodeManagers)); - q->registerBackendType<QShaderImage>(QSharedPointer<Render::NodeFunctor<Render::ShaderImage, Render::ShaderImageManager>>::create(m_renderer)); + q->registerBackendType<QShaderImage, true>(QSharedPointer<Render::NodeFunctor<Render::ShaderImage, Render::ShaderImageManager>>::create(m_renderer)); // Framegraph q->registerBackendType<QFrameGraphNode, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::FrameGraphNode, QFrameGraphNode> >::create(m_renderer)); @@ -320,9 +320,9 @@ void QRenderAspectPrivate::registerBackendTypes() q->registerBackendType<QSubtreeEnabler, true>(QSharedPointer<Render::FrameGraphNodeFunctor<Render::SubtreeEnabler, QSubtreeEnabler> >::create(m_renderer)); // Picking - q->registerBackendType<QObjectPicker>(QSharedPointer<Render::NodeFunctor<Render::ObjectPicker, Render::ObjectPickerManager> >::create(m_renderer)); - q->registerBackendType<QRayCaster>(QSharedPointer<Render::NodeFunctor<Render::RayCaster, Render::RayCasterManager> >::create(m_renderer)); - q->registerBackendType<QScreenRayCaster>(QSharedPointer<Render::NodeFunctor<Render::RayCaster, Render::RayCasterManager> >::create(m_renderer)); + q->registerBackendType<QObjectPicker, true>(QSharedPointer<Render::NodeFunctor<Render::ObjectPicker, Render::ObjectPickerManager> >::create(m_renderer)); + q->registerBackendType<QRayCaster, true>(QSharedPointer<Render::NodeFunctor<Render::RayCaster, Render::RayCasterManager> >::create(m_renderer)); + q->registerBackendType<QScreenRayCaster, true>(QSharedPointer<Render::NodeFunctor<Render::RayCaster, Render::RayCasterManager> >::create(m_renderer)); // Plugins for (const QString &plugin : qAsConst(m_pluginConfig)) diff --git a/src/render/frontend/qrendersettings.cpp b/src/render/frontend/qrendersettings.cpp index 6ddef6e8a..d106e4205 100644 --- a/src/render/frontend/qrendersettings.cpp +++ b/src/render/frontend/qrendersettings.cpp @@ -96,6 +96,11 @@ void QRenderSettingsPrivate::init() q, SLOT(_q_onWorldSpaceToleranceChanged(float))); } +void QRenderSettingsPrivate::invalidateFrame() +{ + update(); +} + /*! \internal */ void QRenderSettingsPrivate::_q_onPickingMethodChanged(QPickingSettings::PickMethod pickMethod) { @@ -156,6 +161,12 @@ QPickingSettings *QRenderSettings::pickingSettings() return &(d->m_pickingSettings); } +const QPickingSettings *QRenderSettings::pickingSettings() const +{ + Q_D(const QRenderSettings); + return &(d->m_pickingSettings); +} + /*! \qmlproperty FrameGraphNode RenderSettings::activeFrameGraph diff --git a/src/render/frontend/qrendersettings.h b/src/render/frontend/qrendersettings.h index 9d2baa58b..c8771a8fa 100644 --- a/src/render/frontend/qrendersettings.h +++ b/src/render/frontend/qrendersettings.h @@ -71,6 +71,7 @@ public: Q_ENUM(RenderPolicy) // LCOV_EXCL_LINE QPickingSettings* pickingSettings(); + const QPickingSettings* pickingSettings() const; QFrameGraphNode *activeFrameGraph() const; RenderPolicy renderPolicy() const; diff --git a/src/render/frontend/qrendersettings_p.h b/src/render/frontend/qrendersettings_p.h index f91397bd2..88f91810a 100644 --- a/src/render/frontend/qrendersettings_p.h +++ b/src/render/frontend/qrendersettings_p.h @@ -71,6 +71,8 @@ public: QFrameGraphNode *m_activeFrameGraph; QRenderSettings::RenderPolicy m_renderPolicy; + void invalidateFrame(); + void _q_onPickingMethodChanged(QPickingSettings::PickMethod pickMethod); void _q_onPickResultModeChanged(QPickingSettings::PickResultMode pickResultMode); void _q_onFaceOrientationPickingModeChanged(QPickingSettings::FaceOrientationPickingMode faceOrientationPickingMode); diff --git a/src/render/frontend/qrendertarget.cpp b/src/render/frontend/qrendertarget.cpp index 9aa9c8c41..2a74db775 100644 --- a/src/render/frontend/qrendertarget.cpp +++ b/src/render/frontend/qrendertarget.cpp @@ -126,11 +126,7 @@ void QRenderTarget::addOutput(QRenderTargetOutput *output) if (!output->parent()) output->setParent(this); - if (d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeAddedChangePtr::create(id(), output); - change->setPropertyName("output"); - d->notifyObservers(change); - } + d->update(); } } @@ -141,11 +137,7 @@ void QRenderTarget::removeOutput(QRenderTargetOutput *output) { Q_D(QRenderTarget); - if (output && d->m_changeArbiter != nullptr) { - const auto change = QPropertyNodeRemovedChangePtr::create(id(), output); - change->setPropertyName("output"); - d->notifyObservers(change); - } + d->update(); d->m_outputs.removeOne(output); // Remove bookkeeping connection d->unregisterDestructionHelper(output); diff --git a/src/render/io/scene.cpp b/src/render/io/scene.cpp index d95f42a48..e7f289f8a 100644 --- a/src/render/io/scene.cpp +++ b/src/render/io/scene.cpp @@ -76,36 +76,20 @@ void Scene::setStatus(QSceneLoader::Status status) notifyObservers(e); } -void Scene::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void Scene::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QSceneLoaderData>>(change); - const auto &data = typedChange->data; - m_source = data.source; - Q_ASSERT(m_sceneManager); - if (Qt3DCore::QDownloadHelperService::isLocal(m_source)) - m_sceneManager->addSceneData(m_source, peerId()); - else - m_sceneManager->startSceneDownload(m_source, peerId()); -} - -void Scene::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - if (e->type() == PropertyUpdated) { - QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (propertyChange->propertyName() == QByteArrayLiteral("source")) { - m_source = propertyChange->value().toUrl(); - - // If the source is empty -> we need to unload anything that was - // previously loaded and reset the status accordingly. This means - // we need to call addSceneData with the empty source to send a - // change to the frontend that will trigger the removal of the - // previous scene. The reason this scheme is employed is because - // the backend also takes care of updating the status. - if (m_source.isEmpty() || Qt3DCore::QDownloadHelperService::isLocal(m_source)) - m_sceneManager->addSceneData(m_source, peerId()); - else - m_sceneManager->startSceneDownload(m_source, peerId()); - } + const QSceneLoader *node = qobject_cast<const QSceneLoader *>(frontEnd); + if (!node) + return; + + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + + if (node->source() != m_source) { + m_source = node->source(); + if (m_source.isEmpty() || Qt3DCore::QDownloadHelperService::isLocal(m_source)) + m_sceneManager->addSceneData(m_source, peerId()); + else + m_sceneManager->startSceneDownload(m_source, peerId()); } markDirty(AbstractRenderer::AllDirty); } diff --git a/src/render/io/scene_p.h b/src/render/io/scene_p.h index 631f23124..04b9bba1a 100644 --- a/src/render/io/scene_p.h +++ b/src/render/io/scene_p.h @@ -72,7 +72,7 @@ class Q_AUTOTEST_EXPORT Scene : public BackendNode public: Scene(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; QUrl source() const; void setSceneSubtree(Qt3DCore::QEntity *subTree); void setSceneManager(SceneManager *manager); @@ -81,8 +81,6 @@ public: void setStatus(QSceneLoader::Status status); private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - SceneManager *m_sceneManager; QUrl m_source; }; diff --git a/src/render/jobs/job_common_p.h b/src/render/jobs/job_common_p.h index 9c83624b8..7aa6f64ba 100644 --- a/src/render/jobs/job_common_p.h +++ b/src/render/jobs/job_common_p.h @@ -109,6 +109,7 @@ namespace JobTypes { UpdateLayerEntity, SendTextureChangesToFrontend, SendSetFenceHandlesToFrontend, + SendDisablesToFrontend }; } // JobTypes diff --git a/src/render/materialsystem/filterkey.cpp b/src/render/materialsystem/filterkey.cpp index 167413451..d51a06eec 100644 --- a/src/render/materialsystem/filterkey.cpp +++ b/src/render/materialsystem/filterkey.cpp @@ -65,31 +65,23 @@ void FilterKey::cleanup() m_value.clear(); } -void FilterKey::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void FilterKey::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QFilterKeyData>>(change); - const auto &data = typedChange->data; - m_name = data.name; - m_value = data.value; -} + const QFilterKey *node = qobject_cast<const QFilterKey *>(frontEnd); + if (!node) + return; -void FilterKey::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - switch (e->type()) { - case PropertyUpdated: { - QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e); - if (propertyChange->propertyName() == QByteArrayLiteral("value")) - m_value = propertyChange->value(); - else if (propertyChange->propertyName() == QByteArrayLiteral("name")) - m_name = propertyChange->value().toString(); + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + if (node->name() != m_name) { + m_name = node->name(); markDirty(AbstractRenderer::AllDirty); } - default: - break; + if (node->value() != m_value) { + m_value = node->value(); + markDirty(AbstractRenderer::AllDirty); } - BackendNode::sceneChangeEvent(e); } bool FilterKey::operator ==(const FilterKey &other) diff --git a/src/render/materialsystem/filterkey_p.h b/src/render/materialsystem/filterkey_p.h index 69d298503..f4fb2c3d0 100644 --- a/src/render/materialsystem/filterkey_p.h +++ b/src/render/materialsystem/filterkey_p.h @@ -71,13 +71,11 @@ public: const QVariant &value() const { return m_value; } const QString &name() const { return m_name; } - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; bool operator ==(const FilterKey &other); bool operator !=(const FilterKey &other); private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - QVariant m_value; QString m_name; }; diff --git a/src/render/materialsystem/shader.cpp b/src/render/materialsystem/shader.cpp index d42b0dda7..f35fba9fa 100644 --- a/src/render/materialsystem/shader.cpp +++ b/src/render/materialsystem/shader.cpp @@ -101,23 +101,24 @@ void Shader::cleanup() m_status = QShaderProgram::NotReady; } -void Shader::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void Shader::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QShaderProgramData>>(change); - const auto &data = typedChange->data; - - for (int i = QShaderProgram::Vertex; i <= QShaderProgram::Compute; ++i) - m_shaderCode[i].clear(); - - m_shaderCode[QShaderProgram::Vertex] = data.vertexShaderCode; - m_shaderCode[QShaderProgram::TessellationControl] = data.tessellationControlShaderCode; - m_shaderCode[QShaderProgram::TessellationEvaluation] = data.tessellationEvaluationShaderCode; - m_shaderCode[QShaderProgram::Geometry] = data.geometryShaderCode; - m_shaderCode[QShaderProgram::Fragment] = data.fragmentShaderCode; - m_shaderCode[QShaderProgram::Compute] = data.computeShaderCode; - m_isLoaded = false; - updateDNA(); - markDirty(AbstractRenderer::ShadersDirty); + const QShaderProgram *node = qobject_cast<const QShaderProgram *>(frontEnd); + if (!node) + return; + + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + + if (firstTime) + for (int i = QShaderProgram::Vertex; i <= QShaderProgram::Compute; ++i) + m_shaderCode[i].clear(); + + for (int i = QShaderProgram::Vertex; i <= QShaderProgram::Compute; ++i) { + const QShaderProgram::ShaderType shaderType = static_cast<QShaderProgram::ShaderType>(i); + const QByteArray code = node->shaderCode(shaderType); + if (code != m_shaderCode.value(shaderType)) + setShaderCode(shaderType, code); + } } void Shader::setGraphicsContext(GraphicsContext *context) @@ -174,29 +175,6 @@ void Shader::setShaderCode(QShaderProgram::ShaderType type, const QByteArray &co markDirty(AbstractRenderer::ShadersDirty); } -void Shader::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - if (e->type() == PropertyUpdated) { - QPropertyUpdatedChangePtr propertyChange = e.staticCast<QPropertyUpdatedChange>(); - QVariant propertyValue = propertyChange->value(); - - if (propertyChange->propertyName() == QByteArrayLiteral("vertexShaderCode")) - setShaderCode(QShaderProgram::Vertex, propertyValue.toByteArray()); - else if (propertyChange->propertyName() == QByteArrayLiteral("fragmentShaderCode")) - setShaderCode(QShaderProgram::Fragment, propertyValue.toByteArray()); - else if (propertyChange->propertyName() == QByteArrayLiteral("tessellationControlShaderCode")) - setShaderCode(QShaderProgram::TessellationControl, propertyValue.toByteArray()); - else if (propertyChange->propertyName() == QByteArrayLiteral("tessellationEvaluationShaderCode")) - setShaderCode(QShaderProgram::TessellationEvaluation, propertyValue.toByteArray()); - else if (propertyChange->propertyName() == QByteArrayLiteral("geometryShaderCode")) - setShaderCode(QShaderProgram::Geometry, propertyValue.toByteArray()); - else if (propertyChange->propertyName() == QByteArrayLiteral("computeShaderCode")) - setShaderCode(QShaderProgram::Compute, propertyValue.toByteArray()); - } - - BackendNode::sceneChangeEvent(e); -} - QHash<QString, ShaderUniform> Shader::activeUniformsForUniformBlock(int blockIndex) const { return m_uniformBlockIndexToShaderUniforms.value(blockIndex); diff --git a/src/render/materialsystem/shader_p.h b/src/render/materialsystem/shader_p.h index 9eb24904c..f8cdde3b7 100644 --- a/src/render/materialsystem/shader_p.h +++ b/src/render/materialsystem/shader_p.h @@ -99,7 +99,7 @@ public: QVector<QByteArray> shaderCode() const; void setShaderCode(QShaderProgram::ShaderType type, const QByteArray &code); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; bool isLoaded() const { QMutexLocker lock(&m_mutex); return m_isLoaded; } void setLoaded(bool loaded) { QMutexLocker lock(&m_mutex); m_isLoaded = loaded; } ProgramDNA dna() const Q_DECL_NOTHROW { return m_dna; } @@ -126,8 +126,6 @@ public: inline bool hasPendingNotifications() const { return !m_pendingNotifications.empty(); } private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - QVector<QString> m_uniformsNames; QVector<int> m_uniformsNamesIds; QVector<ShaderUniform> m_uniforms; diff --git a/src/render/materialsystem/shaderbuilder.cpp b/src/render/materialsystem/shaderbuilder.cpp index c1ec7f75a..b80a66a50 100644 --- a/src/render/materialsystem/shaderbuilder.cpp +++ b/src/render/materialsystem/shaderbuilder.cpp @@ -279,47 +279,46 @@ void ShaderBuilder::generateCode(ShaderBuilder::ShaderType type) notifyObservers(propertyChange); } -void ShaderBuilder::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +void ShaderBuilder::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - if (e->type() == PropertyUpdated) { - QPropertyUpdatedChangePtr propertyChange = e.staticCast<QPropertyUpdatedChange>(); - QVariant propertyValue = propertyChange->value(); - - if (propertyChange->propertyName() == QByteArrayLiteral("shaderProgram")) - m_shaderProgramId = propertyValue.value<Qt3DCore::QNodeId>(); - else if (propertyChange->propertyName() == QByteArrayLiteral("enabledLayers")) - setEnabledLayers(propertyValue.toStringList()); - else if (propertyChange->propertyName() == QByteArrayLiteral("vertexShaderGraph")) - setShaderGraph(Vertex, propertyValue.toUrl()); - else if (propertyChange->propertyName() == QByteArrayLiteral("tessellationControlShaderGraph")) - setShaderGraph(TessellationControl, propertyValue.toUrl()); - else if (propertyChange->propertyName() == QByteArrayLiteral("tessellationEvaluationShaderGraph")) - setShaderGraph(TessellationEvaluation, propertyValue.toUrl()); - else if (propertyChange->propertyName() == QByteArrayLiteral("geometryShaderGraph")) - setShaderGraph(Geometry, propertyValue.toUrl()); - else if (propertyChange->propertyName() == QByteArrayLiteral("fragmentShaderGraph")) - setShaderGraph(Fragment, propertyValue.toUrl()); - else if (propertyChange->propertyName() == QByteArrayLiteral("computeShaderGraph")) - setShaderGraph(Compute, propertyValue.toUrl()); + const QShaderProgramBuilder *node = qobject_cast<const QShaderProgramBuilder *>(frontEnd); + if (!node) + return; + + const bool oldEnabled = isEnabled(); + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + if (oldEnabled != isEnabled()) { markDirty(AbstractRenderer::ShadersDirty); } - BackendNode::sceneChangeEvent(e); -} -void ShaderBuilder::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) -{ - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QShaderProgramBuilderData>>(change); - const auto &data = typedChange->data; - - m_shaderProgramId = data.shaderProgramId; - m_enabledLayers = data.enabledLayers; - setShaderGraph(Vertex, data.vertexShaderGraph); - setShaderGraph(TessellationControl, data.tessellationControlShaderGraph); - setShaderGraph(TessellationEvaluation, data.tessellationEvaluationShaderGraph); - setShaderGraph(Geometry, data.geometryShaderGraph); - setShaderGraph(Fragment, data.fragmentShaderGraph); - setShaderGraph(Compute, data.computeShaderGraph); + const Qt3DCore::QNodeId shaderProgramId = Qt3DCore::qIdForNode(node->shaderProgram()); + if (shaderProgramId != m_shaderProgramId) { + m_shaderProgramId = shaderProgramId; + markDirty(AbstractRenderer::ShadersDirty); + } + + if (node->enabledLayers() != m_enabledLayers) { + setEnabledLayers(node->enabledLayers()); + markDirty(AbstractRenderer::ShadersDirty); + } + + static const std::pair<ShaderType, QUrl (QShaderProgramBuilder::*)() const> shaderTypesToGetters[] = { + {Vertex, &QShaderProgramBuilder::vertexShaderGraph}, + {TessellationControl, &QShaderProgramBuilder::tessellationControlShaderGraph}, + {TessellationEvaluation, &QShaderProgramBuilder::tessellationEvaluationShaderGraph}, + {Geometry, &QShaderProgramBuilder::geometryShaderGraph}, + {Fragment, &QShaderProgramBuilder::fragmentShaderGraph}, + {Compute, &QShaderProgramBuilder::computeShaderGraph}, + }; + + for (auto it = std::cbegin(shaderTypesToGetters), end = std::cend(shaderTypesToGetters); it != end; ++it) { + const QUrl url = (node->*(it->second))(); + if (url != m_graphs.value(it->first)) { + setShaderGraph(it->first, url); + markDirty(AbstractRenderer::ShadersDirty); + } + } } } // namespace Render diff --git a/src/render/materialsystem/shaderbuilder_p.h b/src/render/materialsystem/shaderbuilder_p.h index 00c4e1c28..12234bb6c 100644 --- a/src/render/materialsystem/shaderbuilder_p.h +++ b/src/render/materialsystem/shaderbuilder_p.h @@ -95,10 +95,9 @@ public: void generateCode(ShaderType type); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; void setEnabledLayers(const QStringList &layers); GraphicsApiFilterData m_graphicsApi; diff --git a/src/render/materialsystem/shaderimage.cpp b/src/render/materialsystem/shaderimage.cpp index cbda98ed0..c1fb72bfd 100644 --- a/src/render/materialsystem/shaderimage.cpp +++ b/src/render/materialsystem/shaderimage.cpp @@ -40,6 +40,7 @@ #include "shaderimage_p.h" #include <Qt3DRender/private/qshaderimage_p.h> #include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DRender/qabstracttexture.h> QT_BEGIN_NAMESPACE @@ -70,44 +71,45 @@ void ShaderImage::cleanup() m_format = QShaderImage::NoFormat; } -void ShaderImage::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +void ShaderImage::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e); - if (e->type() == Qt3DCore::PropertyUpdated) { - if (propertyChange->propertyName() == QByteArrayLiteral("texture")) { - m_textureId = propertyChange->value().value<Qt3DCore::QNodeId>(); - markDirty(AbstractRenderer::ParameterDirty); - } else if (propertyChange->propertyName() == QByteArrayLiteral("mipLevel")) { - m_mipLevel = propertyChange->value().toInt(); - markDirty(AbstractRenderer::ParameterDirty); - } else if (propertyChange->propertyName() == QByteArrayLiteral("layer")) { - m_layer = propertyChange->value().toInt(); - markDirty(AbstractRenderer::ParameterDirty); - } else if (propertyChange->propertyName() == QByteArrayLiteral("layered")) { - m_layered = propertyChange->value().toBool(); - markDirty(AbstractRenderer::ParameterDirty); - } else if (propertyChange->propertyName() == QByteArrayLiteral("format")) { - m_format = propertyChange->value().value<QShaderImage::ImageFormat>(); - markDirty(AbstractRenderer::ParameterDirty); - } else if (propertyChange->propertyName() == QByteArrayLiteral("access")) { - m_access = propertyChange->value().value<QShaderImage::Access>(); - markDirty(AbstractRenderer::ParameterDirty); - } + const QShaderImage *node = qobject_cast<const QShaderImage *>(frontEnd); + if (!node) + return; + + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + + const Qt3DCore::QNodeId textureNodeId = Qt3DCore::qIdForNode(node->texture()); + if (textureNodeId != m_textureId) { + m_textureId = textureNodeId; + markDirty(AbstractRenderer::ParameterDirty); + } + + if (node->mipLevel() != m_mipLevel) { + m_mipLevel = node->mipLevel(); + markDirty(AbstractRenderer::ParameterDirty); + } + + if (node->layer() != m_layer) { + m_layer = node->layer(); + markDirty(AbstractRenderer::ParameterDirty); + } + + if (node->layered() != m_layered) { + m_layered = node->layered(); + markDirty(AbstractRenderer::ParameterDirty); + } + + if (node->format() != m_format) { + m_format = node->format(); + markDirty(AbstractRenderer::ParameterDirty); + } + + if (node->access() != m_access) { + m_access = node->access(); + markDirty(AbstractRenderer::ParameterDirty); } - BackendNode::sceneChangeEvent(e); -} -void ShaderImage::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) -{ - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QShaderImageData>>(change); - const QShaderImageData &data = typedChange->data; - - m_textureId = data.textureId; - m_mipLevel = data.mipLevel; - m_layer = data.layer; - m_layered = data.layered; - m_access = data.access; - m_format = data.format; } } // namespace Render diff --git a/src/render/materialsystem/shaderimage_p.h b/src/render/materialsystem/shaderimage_p.h index 6e4de4186..1a1294a21 100644 --- a/src/render/materialsystem/shaderimage_p.h +++ b/src/render/materialsystem/shaderimage_p.h @@ -66,7 +66,7 @@ public: ShaderImage(); void cleanup(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; Qt3DCore::QNodeId textureId() const { return m_textureId; } int mipLevel() const { return m_mipLevel; } @@ -86,8 +86,6 @@ public: #endif private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - Qt3DCore::QNodeId m_textureId; int m_mipLevel; int m_layer; diff --git a/src/render/picking/objectpicker.cpp b/src/render/picking/objectpicker.cpp index 0b3846621..e278d6b6f 100644 --- a/src/render/picking/objectpicker.cpp +++ b/src/render/picking/objectpicker.cpp @@ -75,40 +75,38 @@ void ObjectPicker::cleanup() notifyJob(); } -void ObjectPicker::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void ObjectPicker::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QObjectPickerData>>(change); - const auto &data = typedChange->data; - m_hoverEnabled = data.hoverEnabled; - m_dragEnabled = data.dragEnabled; - m_priority = data.priority; - notifyJob(); -} + const QObjectPicker *node = qobject_cast<const QObjectPicker *>(frontEnd); + if (!node) + return; -void ObjectPicker::notifyJob() -{ - if (m_renderer && m_renderer->pickBoundingVolumeJob()) - qSharedPointerCast<PickBoundingVolumeJob>(m_renderer->pickBoundingVolumeJob())->markPickersDirty(); -} + BackendNode::syncFromFrontEnd(frontEnd, firstTime); -void ObjectPicker::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - if (e->type() == Qt3DCore::PropertyUpdated) { - const Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e); + if (node->isHoverEnabled() != m_hoverEnabled) { + m_hoverEnabled = node->isHoverEnabled(); + markDirty(AbstractRenderer::AllDirty); + notifyJob(); + } - if (propertyChange->propertyName() == QByteArrayLiteral("hoverEnabled")) { - m_hoverEnabled = propertyChange->value().toBool(); - } else if (propertyChange->propertyName() == QByteArrayLiteral("dragEnabled")) { - m_dragEnabled = propertyChange->value().toBool(); - } else if (propertyChange->propertyName() == QByteArrayLiteral("priority")) { - m_priority = propertyChange->value().toInt(); - } + if (node->isDragEnabled() != m_dragEnabled) { + m_dragEnabled = node->isDragEnabled(); + markDirty(AbstractRenderer::AllDirty); + notifyJob(); + } + if (node->priority() != m_priority) { + m_priority = node->priority(); markDirty(AbstractRenderer::AllDirty); notifyJob(); } - BackendNode::sceneChangeEvent(e); +} + +void ObjectPicker::notifyJob() +{ + if (m_renderer && m_renderer->pickBoundingVolumeJob()) + qSharedPointerCast<PickBoundingVolumeJob>(m_renderer->pickBoundingVolumeJob())->markPickersDirty(); } bool ObjectPicker::isPressed() const diff --git a/src/render/picking/objectpicker_p.h b/src/render/picking/objectpicker_p.h index 1e8bf12bf..b4f7d073c 100644 --- a/src/render/picking/objectpicker_p.h +++ b/src/render/picking/objectpicker_p.h @@ -69,7 +69,7 @@ public: ~ObjectPicker(); void cleanup(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) final; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; bool isPressed() const; bool isHoverEnabled() const; bool isDragEnabled() const; @@ -86,7 +86,6 @@ public: int priority() const; private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; void notifyJob(); int m_priority; diff --git a/src/render/picking/raycaster.cpp b/src/render/picking/raycaster.cpp index a5fbf1206..34bbaefd9 100644 --- a/src/render/picking/raycaster.cpp +++ b/src/render/picking/raycaster.cpp @@ -41,6 +41,7 @@ #include "qpickevent.h" #include <Qt3DRender/private/abstractrenderer_p.h> #include <Qt3DRender/qabstractraycaster.h> +#include <Qt3DRender/qlayer.h> #include <Qt3DRender/private/qabstractraycaster_p.h> #include <Qt3DRender/private/raycastingjob_p.h> #include <Qt3DCore/qpropertyupdatedchange.h> @@ -119,70 +120,63 @@ void RayCaster::cleanup() notifyJob(); } -void RayCaster::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void RayCaster::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QAbstractRayCasterData>>(change); - const auto &data = typedChange->data; - m_type = data.casterType; - m_runMode = data.runMode; - m_origin = data.origin; - m_direction = data.direction; - m_length = data.length; - m_position = data.position; - m_filterMode = data.filterMode; - m_layerIds = data.layerIds; -} + const QAbstractRayCaster *node = qobject_cast<const QAbstractRayCaster *>(frontEnd); + if (!node) + return; -void RayCaster::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - switch (e->type()) { - case PropertyValueAdded: { - const auto change = qSharedPointerCast<QPropertyNodeAddedChange>(e); - if (change->propertyName() == QByteArrayLiteral("layer")) { - m_layerIds.append(change->addedNodeId()); - markDirty(AbstractRenderer::LayersDirty); - notifyJob(); - } - break; + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + + if (node->runMode() != m_runMode) { + m_runMode = node->runMode(); + notifyJob(); + markDirty(AbstractRenderer::AllDirty); + } + + if (node->filterMode() != m_filterMode) { + m_filterMode = node->filterMode(); + notifyJob(); + markDirty(AbstractRenderer::AllDirty); + } + + const Qt3DCore::QNodeIdVector layerIds = Qt3DCore::qIdsForNodes(node->layers()); + if (layerIds != m_layerIds) { + m_layerIds = layerIds; + markDirty(AbstractRenderer::LayersDirty); + notifyJob(); } - case PropertyValueRemoved: { - const auto change = qSharedPointerCast<QPropertyNodeRemovedChange>(e); - if (change->propertyName() == QByteArrayLiteral("layer")) { - m_layerIds.removeOne(change->removedNodeId()); - markDirty(AbstractRenderer::LayersDirty); - notifyJob(); - } - break; + const QAbstractRayCasterPrivate *d = static_cast<const QAbstractRayCasterPrivate *>(QNodePrivate::get(node)); + if (d->m_direction != m_direction) { + m_direction = d->m_direction; + notifyJob(); + markDirty(AbstractRenderer::AllDirty); } - case PropertyUpdated: { - const Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e); - - if (propertyChange->propertyName() == QByteArrayLiteral("origin")) { - m_origin = propertyChange->value().value<QVector3D>(); - } else if (propertyChange->propertyName() == QByteArrayLiteral("direction")) { - m_direction = propertyChange->value().value<QVector3D>(); - } else if (propertyChange->propertyName() == QByteArrayLiteral("length")) { - m_length = propertyChange->value().toFloat(); - } else if (propertyChange->propertyName() == QByteArrayLiteral("position")) { - m_position = propertyChange->value().toPoint(); - } else if (propertyChange->propertyName() == QByteArrayLiteral("runMode")) { - m_runMode = propertyChange->value().value<QAbstractRayCaster::RunMode>(); - } else if (propertyChange->propertyName() == QByteArrayLiteral("filterMode")) { - m_filterMode = propertyChange->value().value<QAbstractRayCaster::FilterMode>(); - } + if (!qFuzzyCompare(d->m_length, m_length)) { + m_length = d->m_length; + notifyJob(); + markDirty(AbstractRenderer::AllDirty); + } + if (d->m_origin != m_origin) { + m_origin = d->m_origin; notifyJob(); markDirty(AbstractRenderer::AllDirty); - break; } - default: - break; + if (d->m_position != m_position) { + m_position = d->m_position; + notifyJob(); + markDirty(AbstractRenderer::AllDirty); } - BackendNode::sceneChangeEvent(e); + if (d->m_rayCasterType != m_type) { + m_type = d->m_rayCasterType; + notifyJob(); + markDirty(AbstractRenderer::AllDirty); + } } void RayCaster::dispatchHits(const QAbstractRayCaster::Hits &hits) diff --git a/src/render/picking/raycaster_p.h b/src/render/picking/raycaster_p.h index 6fe6ee322..2be87ec3c 100644 --- a/src/render/picking/raycaster_p.h +++ b/src/render/picking/raycaster_p.h @@ -80,13 +80,12 @@ public: Qt3DCore::QNodeIdVector layerIds() const; QAbstractRayCaster::FilterMode filterMode() const; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; void cleanup(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) final; void dispatchHits(const QAbstractRayCaster::Hits &hits); private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; void notifyJob(); QAbstractRayCasterPrivate::RayCasterType m_type = QAbstractRayCasterPrivate::WorldSpaceRayCaster; diff --git a/src/render/renderers/opengl/graphicshelpers/imagesubmissioncontext.cpp b/src/render/renderers/opengl/graphicshelpers/imagesubmissioncontext.cpp index a5633c306..ca600f994 100644 --- a/src/render/renderers/opengl/graphicshelpers/imagesubmissioncontext.cpp +++ b/src/render/renderers/opengl/graphicshelpers/imagesubmissioncontext.cpp @@ -72,8 +72,10 @@ GLenum glAccessEnumForShaderImageAccess(QShaderImage::Access access) case QShaderImage::WriteOnly: return GL_WRITE_ONLY; case QShaderImage::ReadWrite: - return GL_READ_WRITE; + default: + break; } + return GL_READ_WRITE; } GLenum glImageFormatToGL(QShaderImage::ImageFormat format) diff --git a/src/render/renderers/opengl/renderer/rendercommand_p.h b/src/render/renderers/opengl/renderer/rendercommand_p.h index 67e02d35b..61cc6d17d 100644 --- a/src/render/renderers/opengl/renderer/rendercommand_p.h +++ b/src/render/renderers/opengl/renderer/rendercommand_p.h @@ -89,7 +89,7 @@ public: // A QAttribute pack might be interesting // This is a temporary fix in the meantime, to remove the hacked methods in Technique - QVector<int> m_attributes; + QVector<int> m_activeAttributes; float m_depth; int m_changeCost; @@ -103,7 +103,7 @@ public: CommandType m_type; int m_workGroups[3]; - // Values filled for draw calls + // Values filled for draw calls by Renderer (in prepare Submission) GLsizei m_primitiveCount; QGeometryRenderer::PrimitiveType m_primitiveType; int m_restartIndexValue; diff --git a/src/render/renderers/opengl/renderer/renderer.cpp b/src/render/renderers/opengl/renderer/renderer.cpp index 2df3d1270..45f13c424 100644 --- a/src/render/renderers/opengl/renderer/renderer.cpp +++ b/src/render/renderers/opengl/renderer/renderer.cpp @@ -92,6 +92,7 @@ #include <Qt3DRender/private/commandthread_p.h> #include <Qt3DRender/private/glcommands_p.h> #include <Qt3DRender/private/setfence_p.h> +#include <Qt3DRender/private/subtreeenabler_p.h> #include <Qt3DRender/qcameralens.h> #include <Qt3DCore/private/qeventfilterservice_p.h> @@ -197,6 +198,7 @@ Renderer::Renderer(QRenderAspect::RenderType type) , m_textureGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForDirtyTextures(); }, JobTypes::DirtyTextureGathering)) , m_sendTextureChangesToFrontendJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { sendTextureChangesToFrontend(); }, JobTypes::SendTextureChangesToFrontend)) , m_sendSetFenceHandlesToFrontendJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { sendSetFenceHandlesToFrontend(); }, JobTypes::SendSetFenceHandlesToFrontend)) + , m_sendDisablesToFrontendJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { sendDisablesToFrontend(); }, JobTypes::SendDisablesToFrontend)) , m_introspectShaderJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { reloadDirtyShaders(); }, JobTypes::DirtyShaderGathering)) , m_syncLoadingJobs(Render::GenericLambdaJobPtr<std::function<void ()>>::create([] {}, JobTypes::SyncLoadingJobs)) , m_ownedContext(false) @@ -894,7 +896,7 @@ void Renderer::prepareCommandsSubmission(const QVector<RenderView *> &renderView if (rGeometry->isDirty()) m_dirtyGeometry.push_back(rGeometry); - if (!command->m_attributes.isEmpty() && (requiresFullVAOUpdate || requiresPartialVAOUpdate)) { + if (!command->m_activeAttributes.isEmpty() && (requiresFullVAOUpdate || requiresPartialVAOUpdate)) { Profiling::GLTimeRecorder recorder(Profiling::VAOUpload); // Activate shader m_submissionContext->activateShader(shader->dna()); @@ -916,9 +918,8 @@ void Renderer::prepareCommandsSubmission(const QVector<RenderView *> &renderView // Prepare the ShaderParameterPack based on the active uniforms of the shader shader->prepareUniforms(command->m_parameterPack); - // TO DO: The step below could be performed by the RenderCommand builder job { // Scoped to show extent - command->m_isValid = !command->m_attributes.empty(); + command->m_isValid = !command->m_activeAttributes.empty(); if (!command->m_isValid) continue; @@ -939,7 +940,7 @@ void Renderer::prepareCommandsSubmission(const QVector<RenderView *> &renderView indirectAttribute = attribute; break; case QAttribute::VertexAttribute: { - if (command->m_attributes.contains(attribute->nameId())) + if (command->m_activeAttributes.contains(attribute->nameId())) estimatedCount = qMax(attribute->count(), estimatedCount); break; } @@ -1204,6 +1205,21 @@ void Renderer::sendSetFenceHandlesToFrontend() } } +// Executed in a job +void Renderer::sendDisablesToFrontend() +{ + const auto updatedDisables = std::move(m_updatedDisables); + FrameGraphManager *fgManager = m_nodesManager->frameGraphManager(); + for (const auto &nodeId : updatedDisables) { + FrameGraphNode *fgNode = fgManager->lookupNode(nodeId); + if (fgNode != nullptr) { // Node could have been deleted before we got a chance to notify it + Q_ASSERT(fgNode->nodeType() == FrameGraphNode::SubtreeEnabler); + SubtreeEnabler *enabler = static_cast<SubtreeEnabler *>(fgNode); + enabler->sendDisableToFrontend(); + } + } +} + // Render Thread (or QtQuick RenderThread when using Scene3D) // Scene3D: When using Scene3D rendering, we can't assume that when // updateGLResources is called, the resource handles points to still existing @@ -1808,26 +1824,32 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() // populate the RenderView with a set of RenderCommands that get // their details from the RenderNodes that are visible to the // Camera selected by the framegraph configuration - 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); + if (frameGraphDirty) { + FrameGraphVisitor visitor(m_nodesManager->frameGraphManager()); + m_frameGraphLeaves = 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 (!m_frameGraphLeaves.contains(leafNode)) + m_cache.leafNodeCache.remove(leafNode); + } + + // Handle single shot subtree enablers + const auto subtreeEnablers = visitor.takeEnablersToDisable(); + for (auto *node : subtreeEnablers) + m_updatedDisables.push_back(node->peerId()); + if (m_updatedDisables.size() > 0) + renderBinJobs.push_back(m_sendDisablesToFrontendJob); } - const int fgBranchCount = fgLeaves.size(); + const int fgBranchCount = m_frameGraphLeaves.size(); for (int i = 0; i < fgBranchCount; ++i) { - RenderViewBuilder builder(fgLeaves.at(i), i, this); + RenderViewBuilder builder(m_frameGraphLeaves.at(i), i, this); builder.setLayerCacheNeedsToBeRebuilt(layersCacheNeedsToBeRebuilt); builder.setRenderableCacheNeedsToBeRebuilt(renderableDirty); builder.setComputableCacheNeedsToBeRebuilt(computeableDirty); builder.setLightGathererCacheNeedsToBeRebuilt(lightsDirty); builder.setMaterialGathererCacheNeedsToBeRebuilt(materialCacheNeedsToBeRebuilt); - builder.setRenderableCacheNeedsToBeRebuilt(renderableDirty); - builder.setComputableCacheNeedsToBeRebuilt(computeableDirty); builder.setLightGathererCacheNeedsToBeRebuilt(lightsDirty); builder.prepareJobs(); @@ -2150,7 +2172,7 @@ bool Renderer::updateVAOWithAttributes(Geometry *geometry, if ((attributeWasDirty = attribute->isDirty()) == true || forceUpdate) m_submissionContext->specifyIndices(buffer); // Vertex Attribute - } else if (command->m_attributes.contains(attribute->nameId())) { + } else if (command->m_activeAttributes.contains(attribute->nameId())) { if ((attributeWasDirty = attribute->isDirty()) == true || forceUpdate) { // Find the location for the attribute const QVector<ShaderAttribute> shaderAttributes = shader->attributes(); @@ -2195,7 +2217,7 @@ bool Renderer::requiresVAOAttributeUpdate(Geometry *geometry, continue; if ((attribute->attributeType() == QAttribute::IndexAttribute && attribute->isDirty()) || - (command->m_attributes.contains(attribute->nameId()) && attribute->isDirty())) + (command->m_activeAttributes.contains(attribute->nameId()) && attribute->isDirty())) return true; } return false; diff --git a/src/render/renderers/opengl/renderer/renderer_p.h b/src/render/renderers/opengl/renderer/renderer_p.h index bfab85e4f..c7b4f8805 100644 --- a/src/render/renderers/opengl/renderer/renderer_p.h +++ b/src/render/renderers/opengl/renderer/renderer_p.h @@ -381,6 +381,7 @@ private: GenericLambdaJobPtr<std::function<void ()>> m_textureGathererJob; GenericLambdaJobPtr<std::function<void ()>> m_sendTextureChangesToFrontendJob; GenericLambdaJobPtr<std::function<void ()>> m_sendSetFenceHandlesToFrontendJob; + GenericLambdaJobPtr<std::function<void ()>> m_sendDisablesToFrontendJob; IntrospectShadersJobPtr m_introspectShaderJob; SynchronizerJobPtr m_syncLoadingJobs; @@ -392,6 +393,7 @@ private: void reloadDirtyShaders(); void sendTextureChangesToFrontend(); void sendSetFenceHandlesToFrontend(); + void sendDisablesToFrontend(); QMutex m_abandonedVaosMutex; QVector<HVao> m_abandonedVaos; @@ -402,6 +404,7 @@ private: QVector<HTexture> m_dirtyTextures; QVector<QPair<Texture::TextureUpdateInfo, Qt3DCore::QNodeIdVector>> m_updatedTextureProperties; QVector<QPair<Qt3DCore::QNodeId, GLFence>> m_updatedSetFences; + QVector<Qt3DCore::QNodeId> m_updatedDisables; Qt3DCore::QNodeIdVector m_textureIdsToCleanup; bool m_ownedContext; @@ -421,6 +424,8 @@ private: QMetaObject::Connection m_contextConnection; RendererCache m_cache; bool m_shouldSwapBuffers; + + QVector<FrameGraphNode *> m_frameGraphLeaves; }; } // namespace Render diff --git a/src/render/renderers/opengl/renderer/renderview.cpp b/src/render/renderers/opengl/renderer/renderview.cpp index b00f2c473..420b32325 100644 --- a/src/render/renderers/opengl/renderer/renderview.cpp +++ b/src/render/renderers/opengl/renderer/renderview.cpp @@ -632,21 +632,18 @@ QVector<RenderCommand *> RenderView::buildDrawRenderCommands(const QVector<Entit const Qt3DCore::QNodeId materialComponentId = entity->componentUuid<Material>(); const HMaterial materialHandle = entity->componentHandle<Material>(); const QVector<RenderPassParameterData> renderPassData = m_parameters.value(materialComponentId); - HGeometry geometryHandle = m_manager->lookupHandle<Geometry, GeometryManager, HGeometry>(geometryRenderer->geometryId()); - Geometry *geometry = m_manager->data<Geometry, GeometryManager>(geometryHandle); // 1 RenderCommand per RenderPass pass on an Entity with a Mesh for (const RenderPassParameterData &passData : renderPassData) { // Add the RenderPass Parameters RenderCommand *command = new RenderCommand(); + command->m_geometryRenderer = geometryRendererHandle; + command->m_geometry = m_manager->geometryManager()->lookupHandle(geometryRenderer->geometryId()); // Project the camera-to-object-center vector onto the camera // view vector. This gives a depth value suitable as the key // for BackToFront sorting. command->m_depth = Vector3D::dotProduct(entity->worldBoundingVolume()->center() - m_data.m_eyePos, m_data.m_eyeViewDir); - - command->m_geometry = geometryHandle; - command->m_geometryRenderer = geometryRendererHandle; command->m_material = materialHandle; // For RenderPass based states we use the globally set RenderState // if no renderstates are defined as part of the pass. That means: @@ -686,51 +683,6 @@ QVector<RenderCommand *> RenderView::buildDrawRenderCommands(const QVector<Entit lightSources.mid(0, std::max(lightSources.size(), MAX_LIGHTS)), m_environmentLight); - // Store all necessary information for actual drawing if command is valid - command->m_isValid = !command->m_attributes.empty(); - if (command->m_isValid) { - // Update the draw command with what's going to be needed for the drawing - uint primitiveCount = geometryRenderer->vertexCount(); - uint estimatedCount = 0; - Attribute *indexAttribute = nullptr; - - const QVector<Qt3DCore::QNodeId> attributeIds = geometry->attributes(); - for (Qt3DCore::QNodeId attributeId : attributeIds) { - Attribute *attribute = m_manager->attributeManager()->lookupResource(attributeId); - if (attribute->attributeType() == QAttribute::IndexAttribute) - indexAttribute = attribute; - else if (command->m_attributes.contains(attribute->nameId())) - estimatedCount = qMax(attribute->count(), estimatedCount); - } - - // Update the draw command with all the information required for the drawing - command->m_drawIndexed = (indexAttribute != nullptr); - if (command->m_drawIndexed) { - command->m_indexAttributeDataType = GraphicsContext::glDataTypeFromAttributeDataType(indexAttribute->vertexBaseType()); - command->m_indexAttributeByteOffset = indexAttribute->byteOffset(); - } - - // Use the count specified by the GeometryRender - // If not specified use the indexAttribute count if present - // Otherwise tries to use the count from the attribute with the highest count - if (primitiveCount == 0) { - if (indexAttribute) - primitiveCount = indexAttribute->count(); - else - primitiveCount = estimatedCount; - } - - command->m_primitiveCount = primitiveCount; - command->m_primitiveType = geometryRenderer->primitiveType(); - command->m_primitiveRestartEnabled = geometryRenderer->primitiveRestartEnabled(); - command->m_restartIndexValue = geometryRenderer->restartIndexValue(); - command->m_firstInstance = geometryRenderer->firstInstance(); - command->m_instanceCount = geometryRenderer->instanceCount(); - command->m_firstVertex = geometryRenderer->firstVertex(); - command->m_indexOffset = geometryRenderer->indexOffset(); - command->m_verticesPerPatch = geometryRenderer->verticesPerPatch(); - } - commands.append(command); } } @@ -1049,7 +1001,7 @@ void RenderView::setShaderAndUniforms(RenderCommand *command, // Set default attributes for (const int attributeNameId : attributeNamesIds) - command->m_attributes.push_back(attributeNameId); + command->m_activeAttributes.push_back(attributeNameId); // Parameters remaining could be // -> uniform scalar / vector diff --git a/src/render/renderstates/genericstate_p.h b/src/render/renderstates/genericstate_p.h index b07487d65..e3ece36f5 100644 --- a/src/render/renderstates/genericstate_p.h +++ b/src/render/renderstates/genericstate_p.h @@ -80,7 +80,7 @@ public: virtual StateMask mask() const = 0; virtual bool equalTo(const RenderStateImpl &renderState) const = 0; - virtual void updateProperty(const char *name, const QVariant &value); + virtual void updateProperties(const QRenderState *); }; template <class StateSetImpl, StateMask stateMask, typename ... T> diff --git a/src/render/renderstates/qstenciloperation.cpp b/src/render/renderstates/qstenciloperation.cpp index af7e014f5..86b4c706b 100644 --- a/src/render/renderstates/qstenciloperation.cpp +++ b/src/render/renderstates/qstenciloperation.cpp @@ -106,7 +106,7 @@ QStencilOperation::QStencilOperation(QNode *parent) { Q_D(QStencilOperation); - const auto resend = [d]() { d->resendArguments(); }; + const auto resend = [d]() { d->update(); }; (void) connect(d->m_front, &QStencilOperationArguments::allTestsPassOperationChanged, resend); (void) connect(d->m_front, &QStencilOperationArguments::depthTestFailureOperationChanged, resend); @@ -125,17 +125,6 @@ QStencilOperation::~QStencilOperation() } /*! \internal */ -void QStencilOperationPrivate::resendArguments() -{ - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(m_id); - QStencilOperationData data; - fillData(data); - e->setPropertyName("arguments"); - e->setValue(QVariant::fromValue(data)); - notifyObservers(e); -} - -/*! \internal */ void QStencilOperationPrivate::fillData(QStencilOperationData &data) const { data.front.face = m_front->faceMode(); diff --git a/src/render/renderstates/qstenciloperation_p.h b/src/render/renderstates/qstenciloperation_p.h index a1c0cda4a..d38abf0d7 100644 --- a/src/render/renderstates/qstenciloperation_p.h +++ b/src/render/renderstates/qstenciloperation_p.h @@ -76,7 +76,6 @@ public: QStencilOperationArguments *m_front; QStencilOperationArguments *m_back; - void resendArguments(); void fillData(QStencilOperationData &data) const; }; diff --git a/src/render/renderstates/qstenciltest.cpp b/src/render/renderstates/qstenciltest.cpp index a364c3b88..8f6738e54 100644 --- a/src/render/renderstates/qstenciltest.cpp +++ b/src/render/renderstates/qstenciltest.cpp @@ -109,7 +109,7 @@ QStencilTest::QStencilTest(QNode *parent) { Q_D(QStencilTest); - const auto resend = [d]() { d->resendArguments(); }; + const auto resend = [d]() { d->update(); }; (void) connect(d->m_front, &QStencilTestArguments::comparisonMaskChanged, resend); (void) connect(d->m_front, &QStencilTestArguments::faceModeChanged, resend); @@ -128,17 +128,6 @@ QStencilTest::~QStencilTest() } /*! \internal */ -void QStencilTestPrivate::resendArguments() -{ - auto e = Qt3DCore::QPropertyUpdatedChangePtr::create(m_id); - QStencilTestData data; - fillData(data); - e->setPropertyName("arguments"); - e->setValue(QVariant::fromValue(data)); - notifyObservers(e); -} - -/*! \internal */ void QStencilTestPrivate::fillData(QStencilTestData &data) const { data.front.face = m_front->faceMode(); diff --git a/src/render/renderstates/qstenciltest_p.h b/src/render/renderstates/qstenciltest_p.h index 328e34878..9ddfc6e33 100644 --- a/src/render/renderstates/qstenciltest_p.h +++ b/src/render/renderstates/qstenciltest_p.h @@ -78,7 +78,6 @@ public: QStencilTestArguments *m_front; QStencilTestArguments *m_back; - void resendArguments(); void fillData(QStencilTestData &data) const; }; diff --git a/src/render/renderstates/renderstatenode.cpp b/src/render/renderstates/renderstatenode.cpp index f83640154..bd218c803 100644 --- a/src/render/renderstates/renderstatenode.cpp +++ b/src/render/renderstates/renderstatenode.cpp @@ -90,118 +90,105 @@ namespace Render { namespace { -StateVariant createStateImplementation(const Qt3DRender::QRenderStateCreatedChangeBasePtr renderStateChange) +StateVariant createStateImplementation(const QRenderState *node) { - switch (renderStateChange->renderStateType()) { + const QRenderStatePrivate *d = static_cast<const QRenderStatePrivate *>(Qt3DCore::QNodePrivate::get(node)); + switch (d->m_type) { case AlphaCoverageStateMask: { return StateVariant::createState<AlphaCoverage>(); } case AlphaTestMask: { - const auto typedChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChange<QAlphaTestData>>(renderStateChange); - const auto &data = typedChange->data; - return StateVariant::createState<AlphaFunc>(data.alphaFunction, data.referenceValue); + const QAlphaTest *alphaTest = static_cast<const QAlphaTest *>(node); + return StateVariant::createState<AlphaFunc>(alphaTest->alphaFunction(), alphaTest->referenceValue()); } case BlendStateMask: { - const auto typedChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChange<QBlendEquationData>>(renderStateChange); - const auto &data = typedChange->data; - return StateVariant::createState<BlendEquation>(data.blendFunction); + const QBlendEquation *blendEquation = static_cast<const QBlendEquation *>(node); + return StateVariant::createState<BlendEquation>(blendEquation->blendFunction()); } case BlendEquationArgumentsMask: { - const auto typedChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChange<QBlendEquationArgumentsData>>(renderStateChange); - const auto &data = typedChange->data; + const QBlendEquationArguments *blendArgs = static_cast<const QBlendEquationArguments *>(node); return StateVariant::createState<BlendEquationArguments>( - data.sourceRgb, data.destinationRgb, - data.sourceAlpha, data.destinationAlpha, - renderStateChange->isNodeEnabled(), - data.bufferIndex); + blendArgs->sourceRgb(), blendArgs->destinationRgb(), + blendArgs->sourceAlpha(), blendArgs->destinationAlpha(), + blendArgs->isEnabled(), + blendArgs->bufferIndex()); } case MSAAEnabledStateMask: { - return StateVariant::createState<MSAAEnabled>(renderStateChange->isNodeEnabled()); + return StateVariant::createState<MSAAEnabled>(node->isEnabled()); } case CullFaceStateMask: { - const auto typedChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChange<QCullFaceData>>(renderStateChange); - const auto &data = typedChange->data; - return StateVariant::createState<CullFace>(data.mode); + const QCullFace *cullFace = static_cast<const QCullFace *>(node); + return StateVariant::createState<CullFace>(cullFace->mode()); } case DepthRangeMask: { - const auto typedChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChange<QDepthRangeData>>(renderStateChange); - const auto &data = typedChange->data; - return StateVariant::createState<DepthRange>(data.nearValue, data.farValue); + const QDepthRange *depthRange = static_cast<const QDepthRange *>(node); + return StateVariant::createState<DepthRange>(depthRange->nearValue(), depthRange->farValue()); } case DepthWriteStateMask: { - return StateVariant::createState<NoDepthMask>(false); + return StateVariant::createState<NoDepthMask>(!node->isEnabled()); } case DepthTestStateMask: { - const auto typedChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChange<QDepthTestData>>(renderStateChange); - const auto &data = typedChange->data; - return StateVariant::createState<DepthTest>(data.depthFunction); + const QDepthTest *depthTest = static_cast<const QDepthTest *>(node); + return StateVariant::createState<DepthTest>(depthTest->depthFunction()); } case RasterModeMask: { - const auto typedChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChange<QRasterModeData>>(renderStateChange); - const auto &data = typedChange->data; - return StateVariant::createState<RasterMode>(data.faceMode, data.rasterMode); + const QRasterMode *rasterMode = static_cast<const QRasterMode *>(node); + return StateVariant::createState<RasterMode>(rasterMode->faceMode(), rasterMode->rasterMode()); } case FrontFaceStateMask: { - const auto typedChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChange<QFrontFaceData>>(renderStateChange); - const auto &data = typedChange->data; - return StateVariant::createState<FrontFace>(data.direction); + const QFrontFace *frontFace = static_cast<const QFrontFace *>(node); + return StateVariant::createState<FrontFace>(frontFace->direction()); } case ScissorStateMask: { - const auto typedChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChange<QScissorTestData>>(renderStateChange); - const auto &data = typedChange->data; - return StateVariant::createState<ScissorTest>(data.left, data.bottom, - data.width, data.height); + const QScissorTest *scissorTest = static_cast<const QScissorTest *>(node); + return StateVariant::createState<ScissorTest>(scissorTest->left(), scissorTest->bottom(), + scissorTest->width(), scissorTest->height()); } case StencilTestStateMask: { - const auto typedChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChange<QStencilTestData>>(renderStateChange); - const auto &data = typedChange->data; - return StateVariant::createState<StencilTest>(data.front.stencilFunction, - data.front.referenceValue, - data.front.comparisonMask, - data.back.stencilFunction, - data.back.referenceValue, - data.back.comparisonMask); + const QStencilTest *stencilTest = static_cast<const QStencilTest *>(node); + return StateVariant::createState<StencilTest>(stencilTest->front()->stencilFunction(), + stencilTest->front()->referenceValue(), + stencilTest->front()->comparisonMask(), + stencilTest->back()->stencilFunction(), + stencilTest->back()->referenceValue(), + stencilTest->back()->comparisonMask()); } case PointSizeMask: { - const auto typedChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChange<QPointSizeData>>(renderStateChange); - const auto &data = typedChange->data; - const bool isProgrammable = (data.sizeMode == QPointSize::Programmable); - return StateVariant::createState<PointSize>(isProgrammable, data.value); + const QPointSize *pointSize = static_cast<const QPointSize *>(node); + const bool isProgrammable = (pointSize->sizeMode() == QPointSize::Programmable); + return StateVariant::createState<PointSize>(isProgrammable, pointSize->value()); } case PolygonOffsetStateMask: { - const auto typedChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChange<QPolygonOffsetData>>(renderStateChange); - const auto &data = typedChange->data; - return StateVariant::createState<PolygonOffset>(data.scaleFactor, data.depthSteps); + const QPolygonOffset *offset = static_cast<const QPolygonOffset *>(node); + return StateVariant::createState<PolygonOffset>(offset->scaleFactor(), offset->depthSteps()); } case ColorStateMask: { - const auto typedChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChange<QColorMaskData>>(renderStateChange); - const auto &data = typedChange->data; - return StateVariant::createState<ColorMask>(data.redMasked, data.greenMasked, - data.blueMasked, data.alphaMasked); + const QColorMask *colorMask = static_cast<const QColorMask *>(node); + return StateVariant::createState<ColorMask>(colorMask->isRedMasked(), colorMask->isGreenMasked(), + colorMask->isBlueMasked(), colorMask->isAlphaMasked()); } case ClipPlaneMask: { - const auto typedChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChange<QClipPlaneData>>(renderStateChange); - const auto &data = typedChange->data; - return StateVariant::createState<ClipPlane>(data.planeIndex, - data.normal, - data.distance); + const QClipPlane *clipPlane = static_cast<const QClipPlane *>(node); + return StateVariant::createState<ClipPlane>(clipPlane->planeIndex(), + clipPlane->normal(), + clipPlane->distance()); } case SeamlessCubemapMask: { @@ -209,21 +196,19 @@ StateVariant createStateImplementation(const Qt3DRender::QRenderStateCreatedChan } case StencilOpMask: { - const auto typedChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChange<QStencilOperationData>>(renderStateChange); - const auto &data = typedChange->data; - return StateVariant::createState<StencilOp>(data.front.stencilTestFailureOperation, - data.front.depthTestFailureOperation, - data.front.allTestsPassOperation, - data.back.stencilTestFailureOperation, - data.back.depthTestFailureOperation, - data.back.allTestsPassOperation); + const QStencilOperation *stencilOp = static_cast<const QStencilOperation *>(node); + return StateVariant::createState<StencilOp>(stencilOp->front()->stencilTestFailureOperation(), + stencilOp->front()->depthTestFailureOperation(), + stencilOp->front()->allTestsPassOperation(), + stencilOp->back()->stencilTestFailureOperation(), + stencilOp->back()->depthTestFailureOperation(), + stencilOp->back()->allTestsPassOperation()); } case StencilWriteStateMask: { - const auto typedChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChange<QStencilMaskData>>(renderStateChange); - const auto &data = typedChange->data; - return StateVariant::createState<StencilMask>(data.frontOutputMask, - data.backOutputMask); + const QStencilMask *stencilMask = static_cast<const QStencilMask *>(node); + return StateVariant::createState<StencilMask>(stencilMask->frontOutputMask(), + stencilMask->backOutputMask()); } case DitheringStateMask: { @@ -231,9 +216,8 @@ StateVariant createStateImplementation(const Qt3DRender::QRenderStateCreatedChan } case LineWidthMask: { - const auto typedChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChange<QLineWidthData>>(renderStateChange); - const auto &data = typedChange->data; - return StateVariant::createState<LineWidth>(data.value, data.smooth); + const QLineWidth *lineWidth = static_cast<const QLineWidth *>(node); + return StateVariant::createState<LineWidth>(lineWidth->value(), lineWidth->smooth()); } default: @@ -258,21 +242,19 @@ void RenderStateNode::cleanup() { } -void RenderStateNode::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &chang3) +void RenderStateNode::syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) { - cleanup(); - const auto renderStateChange = qSharedPointerCast<Qt3DRender::QRenderStateCreatedChangeBase>(chang3); - m_impl = createStateImplementation(renderStateChange); -} + const QRenderState *node = qobject_cast<const QRenderState *>(frontEnd); + if (!node) + return; -void RenderStateNode::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - if (e->type() == Qt3DCore::PropertyUpdated) { - Qt3DCore::QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<Qt3DCore::QPropertyUpdatedChange>(e); - m_impl.state()->updateProperty(propertyChange->propertyName(), propertyChange->value()); - markDirty(AbstractRenderer::AllDirty); - } - BackendNode::sceneChangeEvent(e); + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + + if (firstTime) + m_impl = createStateImplementation(node); + + m_impl.state()->updateProperties(node); + markDirty(AbstractRenderer::AllDirty); } } // namespace Render diff --git a/src/render/renderstates/renderstatenode_p.h b/src/render/renderstates/renderstatenode_p.h index 277b8a7c8..e0258112f 100644 --- a/src/render/renderstates/renderstatenode_p.h +++ b/src/render/renderstates/renderstatenode_p.h @@ -63,8 +63,7 @@ public: RenderStateNode(); virtual ~RenderStateNode(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; - + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; StateMask type() const { return m_impl.type; } StateVariant impl() const { return m_impl; } @@ -72,7 +71,6 @@ protected: void cleanup(); private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; StateVariant m_impl; }; diff --git a/src/render/renderstates/renderstates.cpp b/src/render/renderstates/renderstates.cpp index 77143ecd3..bd4a209a1 100644 --- a/src/render/renderstates/renderstates.cpp +++ b/src/render/renderstates/renderstates.cpp @@ -48,152 +48,181 @@ #include <Qt3DRender/private/graphicscontext_p.h> #include <Qt3DRender/private/qstenciloperation_p.h> #include <Qt3DRender/private/qstenciltest_p.h> +#include <Qt3DRender/qblendequationarguments.h> +#include <Qt3DRender/qblendequation.h> +#include <Qt3DRender/qalphatest.h> +#include <Qt3DRender/qdepthrange.h> +#include <Qt3DRender/qdepthtest.h> +#include <Qt3DRender/qrastermode.h> +#include <Qt3DRender/qfrontface.h> +#include <Qt3DRender/qscissortest.h> +#include <Qt3DRender/qpolygonoffset.h> +#include <Qt3DRender/qcolormask.h> +#include <Qt3DRender/qclipplane.h> +#include <Qt3DRender/qstencilmask.h> +#include <Qt3DRender/qlinewidth.h> QT_BEGIN_NAMESPACE namespace Qt3DRender { namespace Render { -void RenderStateImpl::updateProperty(const char *name, const QVariant &value) +void RenderStateImpl::updateProperties(const QRenderState *) { - Q_UNUSED(name); - Q_UNUSED(value); } -void BlendEquationArguments::updateProperty(const char *name, const QVariant &value) +void BlendEquationArguments::updateProperties(const QRenderState *node) { - if (name == QByteArrayLiteral("sourceRgb")) std::get<0>(m_values) = value.toInt(); - else if (name == QByteArrayLiteral("destinationRgb")) std::get<1>(m_values) = value.toInt(); - else if (name == QByteArrayLiteral("sourceAlpha")) std::get<2>(m_values) = value.toInt(); - else if (name == QByteArrayLiteral("destinationAlpha")) std::get<3>(m_values) = value.toInt(); - else if (name == QByteArrayLiteral("enabled")) std::get<4>(m_values) = value.toBool(); - else if (name == QByteArrayLiteral("bufferIndex")) std::get<5>(m_values) = value.toInt(); + const QBlendEquationArguments *args = static_cast<const QBlendEquationArguments *>(node); + + std::get<0>(m_values) = args->sourceRgb(); + std::get<1>(m_values) = args->destinationRgb(); + std::get<2>(m_values) = args->sourceAlpha(); + std::get<3>(m_values) = args->destinationAlpha(); + std::get<4>(m_values) = args->isEnabled(); + std::get<5>(m_values) = args->bufferIndex(); } -void BlendEquation::updateProperty(const char *name, const QVariant &value) +void BlendEquation::updateProperties(const QRenderState *node) { - if (name == QByteArrayLiteral("blendFunction")) std::get<0>(m_values) = value.toInt(); + const QBlendEquation *equation = static_cast<const QBlendEquation *>(node); + std::get<0>(m_values) = equation->blendFunction(); } -void AlphaFunc::updateProperty(const char *name, const QVariant &value) +void AlphaFunc::updateProperties(const QRenderState *node) { - if (name == QByteArrayLiteral("alphaFunction")) - std::get<0>(m_values) = value.toInt(); - if (name == QByteArrayLiteral("referenceValue")) - std::get<1>(m_values) = value.toFloat(); + const QAlphaTest *alphaTest = static_cast<const QAlphaTest *>(node); + std::get<0>(m_values) = alphaTest->alphaFunction(); + std::get<1>(m_values) = alphaTest->referenceValue(); } -void MSAAEnabled::updateProperty(const char *name, const QVariant &value) +void MSAAEnabled::updateProperties(const QRenderState *node) { - if (name == QByteArrayLiteral("enabled")) - std::get<0>(m_values) = value.toBool(); + std::get<0>(m_values) = node->isEnabled(); } -void DepthRange::updateProperty(const char *name, const QVariant &value) +void DepthRange::updateProperties(const QRenderState *node) { - if (name == QByteArrayLiteral("nearValue")) std::get<0>(m_values) = value.toDouble(); - else if (name == QByteArrayLiteral("farValue")) std::get<1>(m_values) = value.toDouble(); + const QDepthRange *depthRange = static_cast<const QDepthRange *>(node); + + std::get<0>(m_values) = depthRange->nearValue(); + std::get<1>(m_values) = depthRange->farValue(); } -void DepthTest::updateProperty(const char *name, const QVariant &value) +void DepthTest::updateProperties(const QRenderState *node) { - if (name == QByteArrayLiteral("depthFunction")) std::get<0>(m_values) = value.toInt(); + const QDepthTest *depthTest = static_cast<const QDepthTest *>(node); + + std::get<0>(m_values) = depthTest->depthFunction(); } -void RasterMode::updateProperty(const char *name, const QVariant &value) +void RasterMode::updateProperties(const QRenderState *node) { - if (name == QByteArrayLiteral("rasterMode")) std::get<0>(m_values) = value.toInt(); - if (name == QByteArrayLiteral("faceMode")) std::get<1>(m_values) = value.toInt(); + const QRasterMode *rasterMode = static_cast<const QRasterMode *>(node); + + std::get<0>(m_values) = rasterMode->faceMode(); + std::get<1>(m_values) = rasterMode->rasterMode(); } -void CullFace::updateProperty(const char *name, const QVariant &value) +void CullFace::updateProperties(const QRenderState *node) { - if (name == QByteArrayLiteral("mode")) std::get<0>(m_values) = value.toInt(); + const QCullFace *cullFace = static_cast<const QCullFace *>(node); + + std::get<0>(m_values) = cullFace->mode(); } -void FrontFace::updateProperty(const char *name, const QVariant &value) +void FrontFace::updateProperties(const QRenderState *node) { - if (name == QByteArrayLiteral("direction")) std::get<0>(m_values) = value.toInt(); + const QFrontFace *frontFace = static_cast<const QFrontFace *>(node); + + std::get<0>(m_values) = frontFace->direction(); } -void NoDepthMask::updateProperty(const char *name, const QVariant &value) +void NoDepthMask::updateProperties(const QRenderState *node) { - if (name == QByteArrayLiteral("mask")) std::get<0>(m_values) = value.toBool(); + std::get<0>(m_values) = !node->isEnabled(); } -void ScissorTest::updateProperty(const char *name, const QVariant &value) +void ScissorTest::updateProperties(const QRenderState *node) { - if (name == QByteArrayLiteral("left")) std::get<0>(m_values) = value.toInt(); - else if (name == QByteArrayLiteral("bottom")) std::get<1>(m_values) = value.toInt(); - else if (name == QByteArrayLiteral("width")) std::get<2>(m_values) = value.toInt(); - else if (name == QByteArrayLiteral("height")) std::get<3>(m_values) = value.toInt(); + const QScissorTest *scissorTest = static_cast<const QScissorTest *>(node); + + std::get<0>(m_values) = scissorTest->left(); + std::get<1>(m_values) = scissorTest->bottom(); + std::get<2>(m_values) = scissorTest->width(); + std::get<3>(m_values) = scissorTest->height(); } -void StencilTest::updateProperty(const char *name, const QVariant &value) +void StencilTest::updateProperties(const QRenderState *node) { - if (name == QByteArrayLiteral("arguments")) { - const QStencilTestData data = value.value<QStencilTestData>(); - std::get<0>(m_values) = data.front.stencilFunction; - std::get<1>(m_values) = data.front.referenceValue; - std::get<2>(m_values) = data.front.comparisonMask; - std::get<3>(m_values) = data.back.stencilFunction; - std::get<4>(m_values) = data.back.referenceValue; - std::get<5>(m_values) = data.back.comparisonMask; - } + const QStencilTest *stencilTest = static_cast<const QStencilTest *>(node); + std::get<0>(m_values) = stencilTest->front()->stencilFunction(); + std::get<1>(m_values) = stencilTest->front()->referenceValue(); + std::get<2>(m_values) = stencilTest->front()->comparisonMask(); + std::get<3>(m_values) = stencilTest->back()->stencilFunction(); + std::get<4>(m_values) = stencilTest->back()->referenceValue(); + std::get<5>(m_values) = stencilTest->back()->comparisonMask(); } -void PointSize::updateProperty(const char *name, const QVariant &value) +void PointSize::updateProperties(const QRenderState *node) { - if (name == QByteArrayLiteral("sizeMode")) std::get<0>(m_values) = (value.toInt() == QPointSize::Programmable); - else if (name == QByteArrayLiteral("value")) std::get<1>(m_values) = value.toFloat(); + const QPointSize *pointSize = static_cast<const QPointSize *>(node); + + std::get<0>(m_values) = (pointSize->sizeMode() == QPointSize::Programmable); + std::get<1>(m_values) = pointSize->value(); } -void PolygonOffset::updateProperty(const char *name, const QVariant &value) +void PolygonOffset::updateProperties(const QRenderState *node) { - if (name == QByteArrayLiteral("scaleFactor")) std::get<0>(m_values) = value.toFloat(); - else if (name == QByteArrayLiteral("depthSteps")) std::get<1>(m_values) = value.toFloat(); + const QPolygonOffset *offset = static_cast<const QPolygonOffset *>(node); + + std::get<0>(m_values) = offset->scaleFactor(); + std::get<1>(m_values) = offset->depthSteps(); } -void ColorMask::updateProperty(const char *name, const QVariant &value) +void ColorMask::updateProperties(const QRenderState *node) { - if (name == QByteArrayLiteral("redMasked")) std::get<0>(m_values) = value.toBool(); - else if (name == QByteArrayLiteral("greenMasked")) std::get<1>(m_values) = value.toBool(); - else if (name == QByteArrayLiteral("blueMasked")) std::get<2>(m_values) = value.toBool(); - else if (name == QByteArrayLiteral("alphaMasked")) std::get<3>(m_values) = value.toBool(); + const QColorMask *colorMask = static_cast<const QColorMask *>(node); + + std::get<0>(m_values) = colorMask->isRedMasked(); + std::get<1>(m_values) = colorMask->isGreenMasked(); + std::get<2>(m_values) = colorMask->isBlueMasked(); + std::get<3>(m_values) = colorMask->isAlphaMasked(); } -void ClipPlane::updateProperty(const char *name, const QVariant &value) +void ClipPlane::updateProperties(const QRenderState *node) { - if (name == QByteArrayLiteral("planeIndex")) std::get<0>(m_values) = value.toInt(); - else if (name == QByteArrayLiteral("normal")) std::get<1>(m_values) = value.value<QVector3D>(); - else if (name == QByteArrayLiteral("distance")) std::get<2>(m_values) = value.toFloat(); + const QClipPlane *clipPlane = static_cast<const QClipPlane *>(node); + + std::get<0>(m_values) = clipPlane->planeIndex(); + std::get<1>(m_values) = clipPlane->normal(); + std::get<2>(m_values) = clipPlane->distance(); } -void StencilOp::updateProperty(const char *name, const QVariant &value) +void StencilOp::updateProperties(const QRenderState *node) { - if (name == QByteArrayLiteral("arguments")) { - const QStencilOperationData data = value.value<QStencilOperationData>(); - std::get<0>(m_values) = data.front.stencilTestFailureOperation; - std::get<1>(m_values) = data.front.depthTestFailureOperation; - std::get<2>(m_values) = data.front.allTestsPassOperation; - std::get<3>(m_values) = data.back.stencilTestFailureOperation; - std::get<4>(m_values) = data.back.depthTestFailureOperation; - std::get<5>(m_values) = data.back.allTestsPassOperation; - } + const QStencilOperation *stencilOp = static_cast<const QStencilOperation *>(node); + + std::get<0>(m_values) = stencilOp->front()->stencilTestFailureOperation(); + std::get<1>(m_values) = stencilOp->front()->depthTestFailureOperation(); + std::get<2>(m_values) = stencilOp->front()->allTestsPassOperation(); + std::get<3>(m_values) = stencilOp->back()->stencilTestFailureOperation(); + std::get<4>(m_values) = stencilOp->back()->depthTestFailureOperation(); + std::get<5>(m_values) = stencilOp->back()->allTestsPassOperation(); } -void StencilMask::updateProperty(const char *name, const QVariant &value) +void StencilMask::updateProperties(const QRenderState *node) { - if (name == QByteArrayLiteral("frontOutputMask")) std::get<0>(m_values) = value.toInt(); - else if (name == QByteArrayLiteral("backOutputMask")) std::get<1>(m_values) = value.toInt(); + const QStencilMask *stencilMask = static_cast<const QStencilMask *>(node); + std::get<0>(m_values) = stencilMask->frontOutputMask(); + std::get<1>(m_values) = stencilMask->backOutputMask(); } -void LineWidth::updateProperty(const char *name, const QVariant &value) +void LineWidth::updateProperties(const QRenderState *node) { - if (name == QByteArrayLiteral("value")) - std::get<0>(m_values) = value.toFloat(); - else if (name == QByteArrayLiteral("smooth")) - std::get<1>(m_values) = value.toBool(); + const QLineWidth *lineWidth = static_cast<const QLineWidth *>(node); + std::get<0>(m_values) = lineWidth->value(); + std::get<1>(m_values) = lineWidth->smooth(); } } // namespace Render diff --git a/src/render/renderstates/renderstates_p.h b/src/render/renderstates/renderstates_p.h index 7c6dc4ebd..6c8e9d551 100644 --- a/src/render/renderstates/renderstates_p.h +++ b/src/render/renderstates/renderstates_p.h @@ -62,61 +62,61 @@ namespace Render { class Q_AUTOTEST_EXPORT BlendEquationArguments : public GenericState<BlendEquationArguments, BlendEquationArgumentsMask, GLenum, GLenum, GLenum, GLenum, bool, int> { public: - void updateProperty(const char *name, const QVariant &value) override; + void updateProperties(const QRenderState *node) override; }; class Q_AUTOTEST_EXPORT BlendEquation : public GenericState<BlendEquation, BlendStateMask, GLenum> { public: - void updateProperty(const char *name, const QVariant &value) override; + void updateProperties(const QRenderState *node) override; }; class Q_AUTOTEST_EXPORT AlphaFunc : public GenericState<AlphaFunc, AlphaTestMask, GLenum, GLclampf> { public: - void updateProperty(const char *name, const QVariant &value) override; + void updateProperties(const QRenderState *node) override; }; class Q_AUTOTEST_EXPORT MSAAEnabled : public GenericState<MSAAEnabled, MSAAEnabledStateMask, GLboolean> { public: - void updateProperty(const char *name, const QVariant &value) override; + void updateProperties(const QRenderState *node) override; }; class Q_AUTOTEST_EXPORT DepthRange : public GenericState<DepthRange, DepthRangeMask, double, double> { public: - void updateProperty(const char *name, const QVariant &value) override; + void updateProperties(const QRenderState *node) override; }; class Q_AUTOTEST_EXPORT DepthTest : public GenericState<DepthTest, DepthTestStateMask, GLenum> { public: - void updateProperty(const char *name, const QVariant &value) override; + void updateProperties(const QRenderState *node) override; }; class Q_AUTOTEST_EXPORT RasterMode : public GenericState<RasterMode, RasterModeMask, GLenum, GLenum> { public: - void updateProperty(const char *name, const QVariant &value) override; + void updateProperties(const QRenderState *node) override; }; class Q_AUTOTEST_EXPORT NoDepthMask : public GenericState<NoDepthMask, DepthWriteStateMask, GLboolean> { public: - void updateProperty(const char *name, const QVariant &value) override; + void updateProperties(const QRenderState *node) override; }; class Q_AUTOTEST_EXPORT CullFace : public GenericState<CullFace, CullFaceStateMask, GLenum> { public: - void updateProperty(const char *name, const QVariant &value) override; + void updateProperties(const QRenderState *node) override; }; class Q_AUTOTEST_EXPORT FrontFace : public GenericState<FrontFace, FrontFaceStateMask, GLenum> { public: - void updateProperty(const char *name, const QVariant &value) override; + void updateProperties(const QRenderState *node) override; }; class Q_AUTOTEST_EXPORT Dithering : public GenericState<Dithering, DitheringStateMask> @@ -126,13 +126,13 @@ class Q_AUTOTEST_EXPORT Dithering : public GenericState<Dithering, DitheringStat class Q_AUTOTEST_EXPORT ScissorTest : public GenericState<ScissorTest, ScissorStateMask, int, int, int, int> { public: - void updateProperty(const char *name, const QVariant &value) override; + void updateProperties(const QRenderState *node) override; }; class Q_AUTOTEST_EXPORT StencilTest : public GenericState<StencilTest, StencilTestStateMask, GLenum, int, uint, GLenum, int, uint> { public: - void updateProperty(const char *name, const QVariant &value) override; + void updateProperties(const QRenderState *node) override; }; class Q_AUTOTEST_EXPORT AlphaCoverage : public GenericState<AlphaCoverage, AlphaCoverageStateMask> @@ -142,26 +142,26 @@ class Q_AUTOTEST_EXPORT AlphaCoverage : public GenericState<AlphaCoverage, Alpha class Q_AUTOTEST_EXPORT PointSize : public GenericState<PointSize, PointSizeMask, bool, GLfloat> { public: - void updateProperty(const char *name, const QVariant &value) override; + void updateProperties(const QRenderState *node) override; }; class Q_AUTOTEST_EXPORT PolygonOffset : public GenericState<PolygonOffset, PolygonOffsetStateMask, GLfloat, GLfloat> { public: - void updateProperty(const char *name, const QVariant &value) override; + void updateProperties(const QRenderState *node) override; }; class Q_AUTOTEST_EXPORT ColorMask : public GenericState<ColorMask, ColorStateMask, GLboolean, GLboolean, GLboolean, GLboolean> { public: - void updateProperty(const char *name, const QVariant &value) override; + void updateProperties(const QRenderState *node) override; }; class Q_AUTOTEST_EXPORT ClipPlane : public GenericState<ClipPlane, ClipPlaneMask, int, QVector3D, float> { public: - void updateProperty(const char *name, const QVariant &value) override; + void updateProperties(const QRenderState *node) override; }; class Q_AUTOTEST_EXPORT SeamlessCubemap : public GenericState<SeamlessCubemap, SeamlessCubemapMask> @@ -171,19 +171,19 @@ class Q_AUTOTEST_EXPORT SeamlessCubemap : public GenericState<SeamlessCubemap, S class Q_AUTOTEST_EXPORT StencilOp : public GenericState<StencilOp, StencilOpMask, GLenum, GLenum, GLenum, GLenum, GLenum, GLenum> { public: - void updateProperty(const char *name, const QVariant &value) override; + void updateProperties(const QRenderState *node) override; }; class Q_AUTOTEST_EXPORT StencilMask : public GenericState<StencilMask, StencilWriteStateMask, uint, uint> { public: - void updateProperty(const char *name, const QVariant &value) override; + void updateProperties(const QRenderState *node) override; }; class Q_AUTOTEST_EXPORT LineWidth : public GenericState<LineWidth, LineWidthMask, GLfloat, bool> { public: - void updateProperty(const char *name, const QVariant &value) override; + void updateProperties(const QRenderState *node) override; }; } // namespace Render diff --git a/src/render/texture/qabstracttextureimage.cpp b/src/render/texture/qabstracttextureimage.cpp index 42f8eb747..a5d342d83 100644 --- a/src/render/texture/qabstracttextureimage.cpp +++ b/src/render/texture/qabstracttextureimage.cpp @@ -94,6 +94,12 @@ QAbstractTextureImagePrivate::~QAbstractTextureImagePrivate() { } +QTextureImageDataGeneratorPtr QAbstractTextureImagePrivate::dataGenerator() const +{ + Q_Q(const QAbstractTextureImage); + return q->dataGenerator(); +} + /*! \qmltype AbstractTextureImage \instantiates Qt3DRender::QAbstractTextureImage diff --git a/src/render/texture/qabstracttextureimage_p.h b/src/render/texture/qabstracttextureimage_p.h index a5299acd7..f93d0e3ca 100644 --- a/src/render/texture/qabstracttextureimage_p.h +++ b/src/render/texture/qabstracttextureimage_p.h @@ -54,6 +54,7 @@ #include <Qt3DCore/private/qnode_p.h> #include <Qt3DRender/private/qt3drender_global_p.h> #include <Qt3DRender/qabstracttexture.h> +#include <Qt3DRender/qtextureimagedatagenerator.h> QT_BEGIN_NAMESPACE @@ -72,6 +73,7 @@ public: int m_mipLevel; int m_layer; QAbstractTexture::CubeMapFace m_face; + QTextureImageDataGeneratorPtr dataGenerator() const; }; struct QAbstractTextureImageData diff --git a/src/render/texture/qtexture.cpp b/src/render/texture/qtexture.cpp index 5a6adece3..734942847 100644 --- a/src/render/texture/qtexture.cpp +++ b/src/render/texture/qtexture.cpp @@ -1156,6 +1156,7 @@ void TextureDownloadRequest::onCompleted() /*! \class Qt3DRender::QTexture1D + \inheaderfile Qt3DRender/QTexture \inmodule Qt3DRender \since 5.5 \brief A QAbstractTexture with a Target1D target format. @@ -1176,6 +1177,7 @@ QTexture1D::~QTexture1D() /*! \class Qt3DRender::QTexture1DArray + \inheaderfile Qt3DRender/QTexture \inmodule Qt3DRender \since 5.5 \brief A QAbstractTexture with a Target1DArray target format. @@ -1196,6 +1198,7 @@ QTexture1DArray::~QTexture1DArray() /*! \class Qt3DRender::QTexture2D + \inheaderfile Qt3DRender/QTexture \inmodule Qt3DRender \since 5.5 \brief A QAbstractTexture with a Target2D target format. @@ -1216,6 +1219,7 @@ QTexture2D::~QTexture2D() /*! \class Qt3DRender::QTexture2DArray + \inheaderfile Qt3DRender/QTexture \inmodule Qt3DRender \since 5.5 \brief A QAbstractTexture with a Target2DArray target format. @@ -1236,6 +1240,7 @@ QTexture2DArray::~QTexture2DArray() /*! \class Qt3DRender::QTexture3D + \inheaderfile Qt3DRender/QTexture \inmodule Qt3DRender \since 5.5 \brief A QAbstractTexture with a Target3D target format. @@ -1256,6 +1261,7 @@ QTexture3D::~QTexture3D() /*! \class Qt3DRender::QTextureCubeMap + \inheaderfile Qt3DRender/QTexture \inmodule Qt3DRender \since 5.5 \brief A QAbstractTexture with a TargetCubeMap target format. @@ -1276,6 +1282,7 @@ QTextureCubeMap::~QTextureCubeMap() /*! \class Qt3DRender::QTextureCubeMapArray + \inheaderfile Qt3DRender/QTexture \inmodule Qt3DRender \since 5.5 \brief A QAbstractTexture with a TargetCubeMapArray target format. @@ -1296,6 +1303,7 @@ QTextureCubeMapArray::~QTextureCubeMapArray() /*! \class Qt3DRender::QTexture2DMultisample + \inheaderfile Qt3DRender/QTexture \inmodule Qt3DRender \since 5.5 \brief A QAbstractTexture with a Target2DMultisample target format. @@ -1316,6 +1324,7 @@ QTexture2DMultisample::~QTexture2DMultisample() /*! \class Qt3DRender::QTexture2DMultisampleArray + \inheaderfile Qt3DRender/QTexture \inmodule Qt3DRender \since 5.5 \brief A QAbstractTexture with a Target2DMultisampleArray target format. @@ -1336,6 +1345,7 @@ QTexture2DMultisampleArray::~QTexture2DMultisampleArray() /*! \class Qt3DRender::QTextureRectangle + \inheaderfile Qt3DRender/QTexture \inmodule Qt3DRender \since 5.5 \brief A QAbstractTexture with a TargetRectangle target format. @@ -1356,6 +1366,7 @@ QTextureRectangle::~QTextureRectangle() /*! \class Qt3DRender::QTextureBuffer + \inheaderfile Qt3DRender/QTexture \inmodule Qt3DRender \since 5.5 \brief A QAbstractTexture with a TargetBuffer target format. @@ -1395,6 +1406,7 @@ void QTextureLoaderPrivate::updateGenerator() /*! \class Qt3DRender::QTextureLoader + \inheaderfile Qt3DRender/QTexture \inmodule Qt3DRender \brief Handles the texture loading and setting the texture's properties. */ @@ -1608,8 +1620,9 @@ bool QTextureFromSourceGenerator::isMirrored() const } /*! - * \class QSharedGLTexture + * \class Qt3DRender::QSharedGLTexture * \inmodule Qt3DRender + * \inheaderfile Qt3DRender/QTexture * \brief Allows to use a textureId from a separate OpenGL context in a Qt 3D scene. * * Depending on the rendering mode used by Qt 3D, the shared context will either be: @@ -1636,6 +1649,14 @@ bool QTextureFromSourceGenerator::isMirrored() const * specify the correct sampler type to be used. */ +/*! + \qmltype SharedGLTexture + \instantiates Qt3DRender::QSharedGLTexture + \inqmlmodule Qt3D.Render + \brief Allows to use a textureId from a separate OpenGL context in a Qt 3D scene. + \since 5.13 +*/ + QSharedGLTexture::QSharedGLTexture(Qt3DCore::QNode *parent) : QAbstractTexture(parent) { @@ -1648,7 +1669,7 @@ QSharedGLTexture::~QSharedGLTexture() } /*! - * \qmlproperty textureId + * \qmlproperty int SharedGLTexture::textureId * * The OpenGL texture id value that you want Qt3D to gain access to. */ diff --git a/src/render/texture/textureimage.cpp b/src/render/texture/textureimage.cpp index 87cfdbca6..512949d91 100644 --- a/src/render/texture/textureimage.cpp +++ b/src/render/texture/textureimage.cpp @@ -72,36 +72,39 @@ void TextureImage::cleanup() m_face = QAbstractTexture::CubeMapPositiveX; } -void TextureImage::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +void TextureImage::syncFromFrontEnd(const QNode *frontEnd, bool firstTime) { - const auto typedChange = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<QAbstractTextureImageData>>(change); - const auto &data = typedChange->data; - m_mipLevel = data.mipLevel; - m_layer = data.layer; - m_face = data.face; - m_generator = data.generator; - m_dirty = true; -} + const QAbstractTextureImage *node = qobject_cast<const QAbstractTextureImage *>(frontEnd); + if (!node) + return; -void TextureImage::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) -{ - QPropertyUpdatedChangePtr propertyChange = qSharedPointerCast<QPropertyUpdatedChange>(e); - - if (e->type() == PropertyUpdated) { - if (propertyChange->propertyName() == QByteArrayLiteral("layer")) { - m_layer = propertyChange->value().toInt(); - } else if (propertyChange->propertyName() == QByteArrayLiteral("mipLevel")) { - m_mipLevel = propertyChange->value().toInt(); - } else if (propertyChange->propertyName() == QByteArrayLiteral("face")) { - m_face = static_cast<QAbstractTexture::CubeMapFace>(propertyChange->value().toInt()); - } else if (propertyChange->propertyName() == QByteArrayLiteral("dataGenerator")) { - m_generator = propertyChange->value().value<QTextureImageDataGeneratorPtr>(); - } + const bool oldEnabled = isEnabled(); + BackendNode::syncFromFrontEnd(frontEnd, firstTime); + m_dirty |= (oldEnabled != isEnabled()); + + if (node->layer() != m_layer) { + m_layer = node->layer(); + m_dirty = true; + } + + if (node->mipLevel() != m_mipLevel) { + m_mipLevel = node->mipLevel(); + m_dirty = true; + } + + if (node->face() != m_face) { + m_face = node->face(); + m_dirty = true; + } + + const QAbstractTextureImagePrivate *d = static_cast<const QAbstractTextureImagePrivate *>(QNodePrivate::get(node)); + if (d->dataGenerator() != m_generator) { + m_generator = d->dataGenerator(); m_dirty = true; } - markDirty(AbstractRenderer::AllDirty); - BackendNode::sceneChangeEvent(e); + if (m_dirty) + markDirty(AbstractRenderer::AllDirty); } void TextureImage::unsetDirty() diff --git a/src/render/texture/textureimage_p.h b/src/render/texture/textureimage_p.h index 490fe4432..57bbdea75 100644 --- a/src/render/texture/textureimage_p.h +++ b/src/render/texture/textureimage_p.h @@ -77,7 +77,7 @@ public: ~TextureImage(); void cleanup(); - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override; + void syncFromFrontEnd(const Qt3DCore::QNode *frontEnd, bool firstTime) override; inline int layer() const { return m_layer; } inline int mipLevel() const { return m_mipLevel; } @@ -87,8 +87,6 @@ public: void unsetDirty(); private: - void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) final; - bool m_dirty; int m_layer; int m_mipLevel; |