diff options
author | Tarja Sundqvist <tarja.sundqvist@qt.io> | 2023-03-23 15:59:10 +0200 |
---|---|---|
committer | Tarja Sundqvist <tarja.sundqvist@qt.io> | 2023-03-23 15:59:10 +0200 |
commit | e94b0fa39a2f4bf260969fb18bf075dba39b2df1 (patch) | |
tree | ff3e15fc92de5ff410db03b22510b76526c42d94 | |
parent | c3c7e6ebc29cce466d954f72f340a257d76b5ec2 (diff) | |
parent | b85ba6f86396f28ab7326da0c7c5cebfeb0fe02f (diff) |
Merge remote-tracking branch 'origin/tqtc/lts-5.15.9' into tqtc/lts-5.15-opensourcev5.15.9-lts-lgpl
Change-Id: I23c3c668f84eb2ef9108a217fa85185b6422402b
-rw-r--r-- | .qmake.conf | 2 | ||||
-rw-r--r-- | src/quick3d/imports/scene3d/scene3dview.cpp | 38 | ||||
-rw-r--r-- | src/quick3d/imports/scene3d/scene3dview_p.h | 9 | ||||
-rw-r--r-- | tests/auto/core/qchangearbiter/qchangearbiter.pro | 2 | ||||
-rw-r--r-- | tests/auto/core/qchangearbiter/tst_qchangearbiter.cpp | 810 | ||||
-rw-r--r-- | tests/auto/render/opengl/graphicshelpergl4/BLACKLIST | 4 |
6 files changed, 70 insertions, 795 deletions
diff --git a/.qmake.conf b/.qmake.conf index f12bc5230..ce81baa81 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -6,4 +6,4 @@ load(qt_build_config) DEFINES += QT_NO_FOREACH DEFINES += QT_NO_JAVA_STYLE_ITERATORS -MODULE_VERSION = 5.15.8 +MODULE_VERSION = 5.15.9 diff --git a/src/quick3d/imports/scene3d/scene3dview.cpp b/src/quick3d/imports/scene3d/scene3dview.cpp index f38d135f0..ddf58ccad 100644 --- a/src/quick3d/imports/scene3d/scene3dview.cpp +++ b/src/quick3d/imports/scene3d/scene3dview.cpp @@ -118,6 +118,10 @@ namespace Qt3DRender { There are no restriction on the sharing of elements between different scenes in different Scene3DView instances. + + By default, you are in charge of ensuring the lifetime of the referenced + Entity. If you wish to transfer this duty to the Scene3DView, the + ownsEntity property can be set to true (defaults to false). */ namespace { @@ -146,6 +150,7 @@ Scene3DView::Scene3DView(QQuickItem *parent) , m_holderViewport(new Qt3DRender::QViewport()) , m_dirtyFlags(DirtyNode|DirtyTexture) , m_texture(nullptr) + , m_ownsEntity(false) { setFlag(QQuickItem::ItemHasContents, true);\ @@ -157,8 +162,11 @@ Scene3DView::Scene3DView(QQuickItem *parent) Scene3DView::~Scene3DView() { - if (m_entity) - abandonSubtree(m_entity); + if (m_entity) { + abandonSubtree(m_entity.data()); + if (m_ownsEntity) + m_entity->deleteLater(); + } if (m_scene3D) m_scene3D->removeView(this); @@ -166,7 +174,7 @@ Scene3DView::~Scene3DView() Qt3DCore::QEntity *Scene3DView::entity() const { - return m_entity; + return m_entity.data(); } Scene3DItem *Scene3DView::scene3D() const @@ -197,6 +205,11 @@ QSGTexture *Scene3DView::texture() const return m_texture; } +bool Scene3DView::ownsEntity() const +{ + return m_ownsEntity; +} + // Called by Scene3DRender::beforeSynchronizing in RenderThread void Scene3DView::markSGNodeDirty() { @@ -207,17 +220,20 @@ void Scene3DView::markSGNodeDirty() // Main Thread void Scene3DView::setEntity(Qt3DCore::QEntity *entity) { - if (m_entity == entity) + if (m_entity.data() == entity) return; - if (m_entity) - abandonSubtree(m_entity); + if (m_entity) { + abandonSubtree(m_entity.data()); + if (m_ownsEntity) + m_entity->deleteLater(); + } m_entity = entity; emit entityChanged(); if (m_entity) - adoptSubtree(m_entity); + adoptSubtree(m_entity.data()); } // Main Thread @@ -247,6 +263,14 @@ void Scene3DView::setScene3D(Scene3DItem *scene3D) } } +void Scene3DView::setOwnsEntity(bool ownsEntity) +{ + if (ownsEntity == m_ownsEntity) + return; + m_ownsEntity = ownsEntity; + emit ownsEntityChanged(); +} + // Render Thread QSGNode *Scene3DView::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNodeData *) { diff --git a/src/quick3d/imports/scene3d/scene3dview_p.h b/src/quick3d/imports/scene3d/scene3dview_p.h index ffb80f93b..5181073c8 100644 --- a/src/quick3d/imports/scene3d/scene3dview_p.h +++ b/src/quick3d/imports/scene3d/scene3dview_p.h @@ -53,6 +53,7 @@ #include <QtQuick/QQuickItem> #include <QtCore/QFlags> +#include <QtCore/QPointer> QT_BEGIN_NAMESPACE @@ -76,6 +77,7 @@ class Scene3DView : public QQuickItem Q_OBJECT Q_PROPERTY(Qt3DCore::QEntity* entity READ entity WRITE setEntity NOTIFY entityChanged) Q_PROPERTY(Qt3DRender::Scene3DItem *scene3D READ scene3D WRITE setScene3D NOTIFY scene3DChanged) + Q_PROPERTY(bool ownsEntity READ ownsEntity WRITE setOwnsEntity NOTIFY ownsEntityChanged) Q_CLASSINFO("DefaultProperty", "entity") public: @@ -97,15 +99,19 @@ public: void setTexture(QSGTexture *texture); QSGTexture *texture() const; + bool ownsEntity() const; + void markSGNodeDirty(); public Q_SLOTS: void setEntity(Qt3DCore::QEntity *entity); void setScene3D(Scene3DItem *scene3D); + void setOwnsEntity(bool ownsEntity); Q_SIGNALS: void entityChanged(); void scene3DChanged(); + void ownsEntityChanged(); private: QSGNode *updatePaintNode(QSGNode *node, UpdatePaintNodeData *nodeData) override; @@ -113,7 +119,7 @@ private: void abandonSubtree(Qt3DCore::QEntity *subtree); Scene3DItem *m_scene3D; - Qt3DCore::QEntity *m_entity; + QPointer<Qt3DCore::QEntity> m_entity; Qt3DCore::QNode *m_previousFGParent; Qt3DCore::QEntity *m_holderEntity; @@ -125,6 +131,7 @@ private: DirtyFlags m_dirtyFlags; QSGTexture *m_texture; + bool m_ownsEntity; }; Q_DECLARE_OPERATORS_FOR_FLAGS(Scene3DView::DirtyFlags) diff --git a/tests/auto/core/qchangearbiter/qchangearbiter.pro b/tests/auto/core/qchangearbiter/qchangearbiter.pro index 64a7b36e7..4628bf6cd 100644 --- a/tests/auto/core/qchangearbiter/qchangearbiter.pro +++ b/tests/auto/core/qchangearbiter/qchangearbiter.pro @@ -6,3 +6,5 @@ QT += testlib core core-private 3dcore 3dcore-private SOURCES += \ tst_qchangearbiter.cpp + +include(../common/common.pri) diff --git a/tests/auto/core/qchangearbiter/tst_qchangearbiter.cpp b/tests/auto/core/qchangearbiter/tst_qchangearbiter.cpp index 4837ac87b..9f79e4272 100644 --- a/tests/auto/core/qchangearbiter/tst_qchangearbiter.cpp +++ b/tests/auto/core/qchangearbiter/tst_qchangearbiter.cpp @@ -31,17 +31,7 @@ QT_WARNING_DISABLE_DEPRECATED #include <QtTest/QTest> -#include <Qt3DCore/private/qobserverinterface_p.h> -#include <Qt3DCore/private/qobservableinterface_p.h> #include <Qt3DCore/private/qchangearbiter_p.h> -#include <Qt3DCore/private/qpostman_p.h> -#include <Qt3DCore/qscenechange.h> -#include <Qt3DCore/qcomponentaddedchange.h> -#include <Qt3DCore/qcomponentremovedchange.h> -#include <Qt3DCore/qpropertyupdatedchange.h> -#include <Qt3DCore/qpropertynodeaddedchange.h> -#include <Qt3DCore/qpropertynoderemovedchange.h> -#include <Qt3DCore/qscenechange.h> #include <Qt3DCore/private/qscene_p.h> #include <Qt3DCore/qnode.h> #include <Qt3DCore/qentity.h> @@ -51,95 +41,14 @@ QT_WARNING_DISABLE_DEPRECATED #include <Qt3DCore/private/qbackendnode_p.h> #include <QThread> #include <QWaitCondition> +#include "testpostmanarbiter.h" class tst_QChangeArbiter : public QObject { Q_OBJECT private slots: - void registerObservers(); - void registerSceneObserver(); - void unregisterObservers(); - void unregisterSceneObservers(); - void distributeFrontendChanges(); - void distributePropertyChanges(); - void distributeBackendChanges(); -}; - -class AllChangesChange : public Qt3DCore::QSceneChange -{ -public: - AllChangesChange(Qt3DCore::QNodeId subjectId) - : Qt3DCore::QSceneChange(Qt3DCore::AllChanges, subjectId) - { - } -}; - -class tst_Node : public Qt3DCore::QEntity -{ -public: - explicit tst_Node(Qt3DCore::QNode *parent = 0) : Qt3DCore::QEntity(parent) - {} - - void sendNodeAddedNotification(QNode *node) - { - Qt3DCore::QPropertyNodeAddedChangePtr e(new Qt3DCore::QPropertyNodeAddedChange(id(), node)); - e->setPropertyName("PropertyValueAdded"); - Qt3DCore::QNodePrivate::get(this)->notifyObservers(e); - } - - void sendNodeRemovedNotification(QNode *node) - { - Qt3DCore::QPropertyNodeRemovedChangePtr e(new Qt3DCore::QPropertyNodeRemovedChange(id(), node)); - e->setPropertyName("PropertyValueRemoved"); - Qt3DCore::QNodePrivate::get(this)->notifyObservers(e); - } - - void sendNodeUpdatedNotification() - { - Qt3DCore::QPropertyUpdatedChangePtr e(new Qt3DCore::QPropertyUpdatedChange(id())); - e->setPropertyName("PropertyUpdated"); - Qt3DCore::QNodePrivate::get(this)->notifyObservers(e); - } - - void sendComponentAddedNotification(Qt3DCore::QComponent *component) - { - Qt3DCore::QComponentAddedChangePtr e(new Qt3DCore::QComponentAddedChange(this, component)); - Qt3DCore::QNodePrivate::get(this)->notifyObservers(e); - } - - void sendComponentRemovedNotification(Qt3DCore::QComponent *component) - { - Qt3DCore::QComponentRemovedChangePtr e(new Qt3DCore::QComponentRemovedChange(this, component)); - Qt3DCore::QNodePrivate::get(this)->notifyObservers(e); - } - - void sendAllChangesNotification() - { - Qt3DCore::QSceneChangePtr e(new AllChangesChange(id())); - Qt3DCore::QNodePrivate::get(this)->notifyObservers(e); - } - - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) override - { - QVERIFY(!change.isNull()); - m_lastChanges << change; - } - - Qt3DCore::QSceneChangePtr lastChange() const - { - if (m_lastChanges.isEmpty()) - return Qt3DCore::QSceneChangePtr(); - return m_lastChanges.last(); - } - - QList<Qt3DCore::QSceneChangePtr> lastChanges() const - { - return m_lastChanges; - } - -private: - QList<Qt3DCore::QSceneChangePtr> m_lastChanges; + void recordsDirtyNodes(); }; // used to test property change notifications @@ -180,722 +89,51 @@ private: float m_prop2 = 0.0f; }; -class tst_SimpleObserver : public Qt3DCore::QObserverInterface -{ -public: - - // QObserverInterface interface - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override - { - QVERIFY(!e.isNull()); - m_lastChanges.append(e); - } - - Qt3DCore::QSceneChangePtr lastChange() const - { - if (m_lastChanges.isEmpty()) - return Qt3DCore::QSceneChangePtr(); - return m_lastChanges.last(); - } - - QList<Qt3DCore::QSceneChangePtr> lastChanges() const - { - return m_lastChanges; - } - - void clear() - { - m_lastChanges.clear(); - } - -private: - QList<Qt3DCore::QSceneChangePtr> m_lastChanges; -}; - -class tst_BackendObserverObservable : public Qt3DCore::QBackendNode -{ -public: - - tst_BackendObserverObservable() - : Qt3DCore::QBackendNode(ReadWrite) - {} - - // QObserverInterface interface - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override - { - QVERIFY(!e.isNull()); - m_lastChanges << e; - m_targetId = e->subjectId(); - } - - // should be called in thread - void sendReply() - { - Qt3DCore::QPropertyUpdatedChangePtr reply; - reply = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(m_targetId); - reply->setDeliveryFlags(Qt3DCore::QSceneChange::DeliverToAll); - reply->setPropertyName("Reply"); - notifyObservers(reply); - qDebug() << Q_FUNC_INFO; - } - - Qt3DCore::QSceneChangePtr lastChange() const - { - if (m_lastChanges.isEmpty()) - return Qt3DCore::QSceneChangePtr(); - return m_lastChanges.last(); - } - - QList<Qt3DCore::QSceneChangePtr> lastChanges() const - { - return m_lastChanges; - } - - void clear() - { - m_lastChanges.clear(); - } - -private: - QList<Qt3DCore::QSceneChangePtr> m_lastChanges; - Qt3DCore::QNodeId m_targetId; - -}; - -class ThreadedAnswer : public QThread -{ - Q_OBJECT -public: - ThreadedAnswer(Qt3DCore::QChangeArbiter *arbiter, tst_BackendObserverObservable *backend) - : QThread() - , m_arbiter(arbiter) - , m_backendObs(backend) - {} - - ~ThreadedAnswer() { qDebug() << this; } - - void run() override - { - // create backend change queue on QChangeArbiter - Qt3DCore::QChangeArbiter::createThreadLocalChangeQueue(m_arbiter); - m_backendObs->sendReply(); - // gives time for other threads to start waiting - QThread::currentThread()->sleep(1); - // wake waiting condition - m_waitingForReplyToBeSent.wakeOne(); - exec(); - Qt3DCore::QChangeArbiter::destroyThreadLocalChangeQueue(m_arbiter); - } - - QWaitCondition *waitingCondition() { return &m_waitingForReplyToBeSent; } - -private: - Qt3DCore::QChangeArbiter *m_arbiter; - tst_BackendObserverObservable *m_backendObs; - QWaitCondition m_waitingForReplyToBeSent; -}; - -class tst_PostManObserver : public Qt3DCore::QAbstractPostman -{ -public: - - tst_PostManObserver() - : m_sceneInterface(nullptr) - , m_allowFrontendNotifications(false) - {} - - void setScene(Qt3DCore::QScene *scene) final - { - m_sceneInterface = scene; - } - - void setAllowFrontendNotifications(bool allow) - { - m_allowFrontendNotifications = allow; - } - - // QObserverInterface interface - void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) - { - QVERIFY(!e.isNull()); - Qt3DCore::QPropertyUpdatedChangePtr change = qSharedPointerDynamicCast<Qt3DCore::QPropertyUpdatedChange>(e); - QVERIFY(!change.isNull()); - Qt3DCore::QNode *targetNode = m_sceneInterface->lookupNode(change->subjectId()); - QVERIFY(targetNode != nullptr); - m_lastChanges << e; - } - - Qt3DCore::QSceneChangePtr lastChange() const - { - if (m_lastChanges.isEmpty()) - return Qt3DCore::QSceneChangePtr(); - return m_lastChanges.last(); - } - - QList<Qt3DCore::QSceneChangePtr> lastChanges() const - { - return m_lastChanges; - } - - void notifyBackend(const Qt3DCore::QSceneChangePtr &e) final - { - m_sceneInterface->arbiter()->sceneChangeEventWithLock(e); - } - - bool shouldNotifyFrontend(const Qt3DCore::QSceneChangePtr &) - { - return m_allowFrontendNotifications; - } - -private: - Qt3DCore::QScene *m_sceneInterface; - QList<Qt3DCore::QSceneChangePtr> m_lastChanges; - bool m_allowFrontendNotifications; -}; - -void tst_QChangeArbiter::registerObservers() -{ - // GIVEN - QScopedPointer<Qt3DCore::QChangeArbiter> arbiter(new Qt3DCore::QChangeArbiter()); - QScopedPointer<Qt3DCore::QScene> scene(new Qt3DCore::QScene()); - QScopedPointer<Qt3DCore::QAbstractPostman> postman(new tst_PostManObserver); - arbiter->setPostman(postman.data()); - arbiter->setScene(scene.data()); - postman->setScene(scene.data()); - scene->setArbiter(arbiter.data()); - // Replaces initialize as we have no JobManager in this case - Qt3DCore::QChangeArbiter::createThreadLocalChangeQueue(arbiter.data()); - - // WHEN - Qt3DCore::QNode *root = new tst_Node(); - Qt3DCore::QNode *child = new tst_Node(); - Qt3DCore::QNodePrivate::get(root)->setScene(scene.data()); - scene->addObservable(root); - - QList<tst_SimpleObserver *> observers; - for (int i = 0; i < 5; i++) { - tst_SimpleObserver *s = new tst_SimpleObserver(); - arbiter->registerObserver(s, root->id()); - observers << s; - } - - arbiter->syncChanges(); - - // THEN - for (tst_SimpleObserver *o : qAsConst(observers)) - QVERIFY(o->lastChange().isNull()); - - child->setParent(root); - arbiter->syncChanges(); - for (tst_SimpleObserver *o : qAsConst(observers)) { - QCOMPARE(o->lastChanges().size(), 1); - QVERIFY(o->lastChanges().last()->type() == Qt3DCore::PropertyValueAdded); - } - - Qt3DCore::QChangeArbiter::destroyThreadLocalChangeQueue(arbiter.data()); -} - -void tst_QChangeArbiter::registerSceneObserver() -{ - // GIVEN - Qt3DCore::QComponent dummyComponent; - QScopedPointer<Qt3DCore::QChangeArbiter> arbiter(new Qt3DCore::QChangeArbiter()); - QScopedPointer<Qt3DCore::QScene> scene(new Qt3DCore::QScene()); - QScopedPointer<Qt3DCore::QAbstractPostman> postman(new tst_PostManObserver); - arbiter->setPostman(postman.data()); - arbiter->setScene(scene.data()); - postman->setScene(scene.data()); - scene->setArbiter(arbiter.data()); - // Replaces initialize as we have no JobManager in this case - Qt3DCore::QChangeArbiter::createThreadLocalChangeQueue(arbiter.data()); - - // WHEN - tst_Node *root = new tst_Node(); - Qt3DCore::QNode *child = new tst_Node(); - Qt3DCore::QNodePrivate::get(root)->setScene(scene.data()); - Qt3DCore::QNodePrivate::get(root)->m_hasBackendNode = true; - scene->addObservable(root); - - QList<tst_SimpleObserver *> observers; - for (int i = 0; i < 5; i++) { - tst_SimpleObserver *s = new tst_SimpleObserver(); - arbiter->registerObserver(s, root->id()); - observers << s; - } - - arbiter->syncChanges(); - - // THEN - for (tst_SimpleObserver *o : qAsConst(observers)) - QVERIFY(o->lastChange().isNull()); - - // WHEN - child->setParent(root); - arbiter->syncChanges(); - - // THEN - for (tst_SimpleObserver *o : qAsConst(observers)) { - QVERIFY(!o->lastChange().isNull()); - QVERIFY(o->lastChange()->type() == Qt3DCore::PropertyValueAdded); - } - - // WHEN - root->sendComponentAddedNotification(&dummyComponent); - arbiter->syncChanges(); - - // THEN - for (tst_SimpleObserver *o : qAsConst(observers)) { - QVERIFY(!o->lastChange().isNull()); - QVERIFY(o->lastChange()->type() == Qt3DCore::ComponentAdded); - } - - Qt3DCore::QChangeArbiter::destroyThreadLocalChangeQueue(arbiter.data()); -} - -void tst_QChangeArbiter::unregisterObservers() -{ - // GIVEN - QScopedPointer<Qt3DCore::QChangeArbiter> arbiter(new Qt3DCore::QChangeArbiter()); - QScopedPointer<Qt3DCore::QScene> scene(new Qt3DCore::QScene()); - QScopedPointer<Qt3DCore::QAbstractPostman> postman(new tst_PostManObserver); - arbiter->setPostman(postman.data()); - arbiter->setScene(scene.data()); - postman->setScene(scene.data()); - scene->setArbiter(arbiter.data()); - // Replaces initialize as we have no JobManager in this case - Qt3DCore::QChangeArbiter::createThreadLocalChangeQueue(arbiter.data()); - - // WHEN - tst_Node *root = new tst_Node(); - Qt3DCore::QNode *child = new tst_Node(); - Qt3DCore::QNodePrivate::get(root)->setScene(scene.data()); - scene->addObservable(root); - - QList<tst_SimpleObserver *> observers; - for (int i = 0; i < 5; i++) { - tst_SimpleObserver *s = new tst_SimpleObserver(); - arbiter->registerObserver(s, root->id()); - observers << s; - } - - arbiter->syncChanges(); - - // THEN - for (tst_SimpleObserver *o : qAsConst(observers)) - QVERIFY(o->lastChange().isNull()); - - // WHEN - child->setParent(root); - arbiter->syncChanges(); - - // THEN - for (tst_SimpleObserver *o : qAsConst(observers)) { - QVERIFY(!o->lastChange().isNull()); - QVERIFY(o->lastChange()->type() == Qt3DCore::PropertyValueAdded); - } - - // WHEN - for (tst_SimpleObserver *o : qAsConst(observers)) - arbiter->unregisterObserver(o, root->id()); - - root->sendAllChangesNotification(); - arbiter->syncChanges(); - - // THEN - for (tst_SimpleObserver *o : qAsConst(observers)) { - QVERIFY(!o->lastChange().isNull()); - QVERIFY(o->lastChange()->type() == Qt3DCore::PropertyValueAdded); - } - - Qt3DCore::QChangeArbiter::destroyThreadLocalChangeQueue(arbiter.data()); -} - -void tst_QChangeArbiter::unregisterSceneObservers() -{ - // GIVEN - Qt3DCore::QComponent dummyComponent; - QScopedPointer<Qt3DCore::QChangeArbiter> arbiter(new Qt3DCore::QChangeArbiter()); - QScopedPointer<Qt3DCore::QScene> scene(new Qt3DCore::QScene()); - QScopedPointer<Qt3DCore::QAbstractPostman> postman(new tst_PostManObserver); - arbiter->setPostman(postman.data()); - arbiter->setScene(scene.data()); - postman->setScene(scene.data()); - scene->setArbiter(arbiter.data()); - // Replaces initialize as we have no JobManager in this case - Qt3DCore::QChangeArbiter::createThreadLocalChangeQueue(arbiter.data()); - - // WHEN - tst_Node *root = new tst_Node(); - Qt3DCore::QNode *child = new tst_Node(); - Qt3DCore::QNodePrivate::get(root)->setScene(scene.data()); - Qt3DCore::QNodePrivate::get(root)->m_hasBackendNode = true; - Qt3DCore::QNodePrivate::get(child)->m_hasBackendNode = true; - scene->addObservable(root); - - QList<tst_SimpleObserver *> observers; - for (int i = 0; i < 5; i++) { - tst_SimpleObserver *s = new tst_SimpleObserver(); - arbiter->registerObserver(s, root->id()); - observers << s; - } - - arbiter->syncChanges(); - - // THEN - for (tst_SimpleObserver *o : qAsConst(observers)) - QVERIFY(o->lastChange().isNull()); - - // WHEN - child->setParent(root); - arbiter->syncChanges(); - - // THEN - for (tst_SimpleObserver *o : qAsConst(observers)) { - QVERIFY(!o->lastChange().isNull()); - QVERIFY(o->lastChange()->type() == Qt3DCore::PropertyValueAdded); - } - - // WHEN - root->sendComponentAddedNotification(&dummyComponent); - arbiter->syncChanges(); - - // THEN - for (tst_SimpleObserver *o : qAsConst(observers)) { - QVERIFY(!o->lastChange().isNull()); - QVERIFY(o->lastChange()->type() == Qt3DCore::ComponentAdded); - } - - // WHEN - child->setParent(Q_NODE_NULLPTR); - arbiter->syncChanges(); - - // THEN - for (tst_SimpleObserver *o : qAsConst(observers)) { - QVERIFY(!o->lastChange().isNull()); - QVERIFY(o->lastChange()->type() == Qt3DCore::PropertyValueRemoved); - } - - // WHEN - child->setParent(root); - arbiter->syncChanges(); - - // THEN - for (tst_SimpleObserver *o : qAsConst(observers)) { - QVERIFY(!o->lastChange().isNull()); - QVERIFY(o->lastChange()->type() == Qt3DCore::PropertyValueAdded); - } - - Qt3DCore::QChangeArbiter::destroyThreadLocalChangeQueue(arbiter.data()); -} - -void tst_QChangeArbiter::distributeFrontendChanges() -{ - // GIVEN - Qt3DCore::QComponent dummyComponent; - Qt3DCore::QNode dummyNode; - QScopedPointer<Qt3DCore::QChangeArbiter> arbiter(new Qt3DCore::QChangeArbiter()); - QScopedPointer<Qt3DCore::QScene> scene(new Qt3DCore::QScene()); - QScopedPointer<Qt3DCore::QAbstractPostman> postman(new tst_PostManObserver); - arbiter->setPostman(postman.data()); - arbiter->setScene(scene.data()); - postman->setScene(scene.data()); - scene->setArbiter(arbiter.data()); - // Replaces initialize as we have no JobManager in this case - Qt3DCore::QChangeArbiter::createThreadLocalChangeQueue(arbiter.data()); - - // WHEN - tst_Node *root = new tst_Node(); - Qt3DCore::QNodePrivate::get(root)->setScene(scene.data()); - scene->addObservable(root); - - tst_SimpleObserver *backendAllChangedObserver = new tst_SimpleObserver(); - tst_SimpleObserver *backendNodeAddedObserver = new tst_SimpleObserver(); - tst_SimpleObserver *backendNodeRemovedObserver = new tst_SimpleObserver(); - tst_SimpleObserver *backendNodeUpdatedObserver = new tst_SimpleObserver(); - tst_SimpleObserver *backendComponentAddedObserver = new tst_SimpleObserver(); - tst_SimpleObserver *backendComponentRemovedObserver = new tst_SimpleObserver(); - - arbiter->registerObserver(backendAllChangedObserver, root->id()); - arbiter->registerObserver(backendNodeAddedObserver, root->id(), Qt3DCore::PropertyValueAdded); - arbiter->registerObserver(backendNodeUpdatedObserver, root->id(), Qt3DCore::PropertyUpdated); - arbiter->registerObserver(backendNodeRemovedObserver, root->id(), Qt3DCore::PropertyValueRemoved); - arbiter->registerObserver(backendComponentAddedObserver, root->id(), Qt3DCore::ComponentAdded); - arbiter->registerObserver(backendComponentRemovedObserver, root->id(), Qt3DCore::ComponentRemoved); - - arbiter->syncChanges(); - - // THEN - QVERIFY(backendAllChangedObserver->lastChange().isNull()); - QVERIFY(backendNodeAddedObserver->lastChange().isNull()); - QVERIFY(backendNodeUpdatedObserver->lastChange().isNull()); - QVERIFY(backendNodeRemovedObserver->lastChange().isNull()); - QVERIFY(backendComponentAddedObserver->lastChange().isNull()); - QVERIFY(backendComponentRemovedObserver->lastChange().isNull()); - - // WHEN - root->sendNodeAddedNotification(&dummyNode); - arbiter->syncChanges(); - - // THEN - QCOMPARE(backendAllChangedObserver->lastChanges().count(), 1); - QCOMPARE(backendNodeAddedObserver->lastChanges().count(), 1); - QCOMPARE(backendNodeUpdatedObserver->lastChanges().count(), 0); - QCOMPARE(backendNodeRemovedObserver->lastChanges().count(), 0); - QCOMPARE(backendComponentAddedObserver->lastChanges().count(), 0); - QCOMPARE(backendComponentRemovedObserver->lastChanges().count(), 0); - - // WHEN - root->sendNodeUpdatedNotification(); - arbiter->syncChanges(); - - // THEN - QCOMPARE(backendAllChangedObserver->lastChanges().count(), 2); - QCOMPARE(backendNodeAddedObserver->lastChanges().count(), 1); - QCOMPARE(backendNodeUpdatedObserver->lastChanges().count(), 1); - QCOMPARE(backendNodeRemovedObserver->lastChanges().count(), 0); - QCOMPARE(backendComponentAddedObserver->lastChanges().count(), 0); - QCOMPARE(backendComponentRemovedObserver->lastChanges().count(), 0); - - // WHEN - root->sendNodeRemovedNotification(&dummyNode); - arbiter->syncChanges(); - - // THEN - QCOMPARE(backendAllChangedObserver->lastChanges().count(), 3); - QCOMPARE(backendNodeAddedObserver->lastChanges().count(), 1); - QCOMPARE(backendNodeUpdatedObserver->lastChanges().count(), 1); - QCOMPARE(backendNodeRemovedObserver->lastChanges().count(), 1); - QCOMPARE(backendComponentAddedObserver->lastChanges().count(), 0); - QCOMPARE(backendComponentRemovedObserver->lastChanges().count(), 0); - - // WHEN - root->sendComponentAddedNotification(&dummyComponent); - arbiter->syncChanges(); - - // THEN - QCOMPARE(backendAllChangedObserver->lastChanges().count(), 4); - QCOMPARE(backendNodeAddedObserver->lastChanges().count(), 1); - QCOMPARE(backendNodeUpdatedObserver->lastChanges().count(), 1); - QCOMPARE(backendNodeRemovedObserver->lastChanges().count(), 1); - QCOMPARE(backendComponentAddedObserver->lastChanges().count(), 1); - QCOMPARE(backendComponentRemovedObserver->lastChanges().count(), 0); - - // WHEN - root->sendComponentRemovedNotification(&dummyComponent); - arbiter->syncChanges(); - - // THEN - QCOMPARE(backendAllChangedObserver->lastChanges().count(), 5); - QCOMPARE(backendNodeAddedObserver->lastChanges().count(), 1); - QCOMPARE(backendNodeUpdatedObserver->lastChanges().count(), 1); - QCOMPARE(backendNodeRemovedObserver->lastChanges().count(), 1); - QCOMPARE(backendComponentAddedObserver->lastChanges().count(), 1); - QCOMPARE(backendComponentRemovedObserver->lastChanges().count(), 1); - - // WHEN - root->sendAllChangesNotification(); - arbiter->syncChanges(); - - // THEN - QCOMPARE(backendAllChangedObserver->lastChanges().count(), 6); - QCOMPARE(backendNodeAddedObserver->lastChanges().count(), 2); - QCOMPARE(backendNodeUpdatedObserver->lastChanges().count(), 2); - QCOMPARE(backendNodeRemovedObserver->lastChanges().count(), 2); - QCOMPARE(backendComponentAddedObserver->lastChanges().count(), 2); - QCOMPARE(backendComponentRemovedObserver->lastChanges().count(), 2); - - Qt3DCore::QChangeArbiter::destroyThreadLocalChangeQueue(arbiter.data()); -} - -void tst_QChangeArbiter::distributePropertyChanges() +void tst_QChangeArbiter::recordsDirtyNodes() { // GIVEN - QScopedPointer<Qt3DCore::QChangeArbiter> arbiter(new Qt3DCore::QChangeArbiter()); + QScopedPointer<TestArbiter> arbiter(new TestArbiter()); QScopedPointer<Qt3DCore::QScene> scene(new Qt3DCore::QScene()); - QScopedPointer<Qt3DCore::QAbstractPostman> postman(new tst_PostManObserver); - arbiter->setPostman(postman.data()); - arbiter->setScene(scene.data()); - postman->setScene(scene.data()); +// arbiter->setScene(scene.data()); scene->setArbiter(arbiter.data()); - // Replaces initialize as we have no JobManager in this case - Qt3DCore::QChangeArbiter::createThreadLocalChangeQueue(arbiter.data()); - - // Test change notifications made to the root node: // WHEN - PropertyTestNode *root = new PropertyTestNode(); - Qt3DCore::QNodePrivate::get(root)->setScene(scene.data()); - Qt3DCore::QNodePrivate::get(root)->m_hasBackendNode = true; - scene->addObservable(root); + auto *root = new PropertyTestNode(); + auto *child = new PropertyTestNode(root); - tst_SimpleObserver *rootObserver = new tst_SimpleObserver(); - arbiter->registerObserver(rootObserver, root->id()); - arbiter->syncChanges(); + root->setProp1(883); + child->setProp2(1584); // THEN - QVERIFY(rootObserver->lastChange().isNull()); + QCOMPARE(arbiter->dirtyNodes.size(), 0); // WHEN - root->setProp1(root->prop1() + 1); + Qt3DCore::QNodePrivate::get(root)->setArbiter(arbiter.data()); + root->setProp1(884); + child->setProp2(1585); // THEN - auto dirtyNodes = arbiter->takeDirtyFrontEndNodes(); - QCOMPARE(dirtyNodes.size(), 1); - QCOMPARE(dirtyNodes.front(), root); + QCOMPARE(arbiter->dirtyNodes.size(), 1); + QCOMPARE(arbiter->dirtyNodes.front(), root); - // WHEN - root->setProp2(root->prop2() + 1.f); - - // THEN - dirtyNodes = arbiter->takeDirtyFrontEndNodes(); - QCOMPARE(dirtyNodes.size(), 1); - QCOMPARE(dirtyNodes.front(), root); - - // Test change notifications made to an entity that was added to the scene - // via QNode::setParent() + arbiter->dirtyNodes.clear(); // WHEN - PropertyTestNode *setParentChild = new PropertyTestNode(); - setParentChild->setParent(root); - tst_SimpleObserver *setParentChildObserver = new tst_SimpleObserver(); - arbiter->registerObserver(setParentChildObserver, setParentChild->id()); - setParentChild->setProp2(setParentChild->prop2() + 1.f); + Qt3DCore::QNodePrivate::get(child)->setArbiter(arbiter.data()); + child->setProp2(1586); // THEN - dirtyNodes = arbiter->takeDirtyFrontEndNodes(); - QCOMPARE(dirtyNodes.size(), 1); - QCOMPARE(dirtyNodes.front(), setParentChild); + QCOMPARE(arbiter->dirtyNodes.size(), 1); + QCOMPARE(arbiter->dirtyNodes.front(), child); - // Test change notifications made to an entity that was added to the scene - // via the QNode() constructor parent parameter + arbiter->dirtyNodes.clear(); // WHEN - PropertyTestNode *directChild = new PropertyTestNode(root); - QCoreApplication::processEvents(); // make sure the post-ctor initialization is executed for the node - tst_SimpleObserver *directChildObserver = new tst_SimpleObserver(); - arbiter->registerObserver(directChildObserver, directChild->id()); - directChild->setProp1(directChild->prop1() + 1); - - // THEN - dirtyNodes = arbiter->takeDirtyFrontEndNodes(); - QCOMPARE(dirtyNodes.size(), 1); - QCOMPARE(dirtyNodes.front(), directChild); - - Qt3DCore::QChangeArbiter::destroyThreadLocalChangeQueue(arbiter.data()); -} - -void tst_QChangeArbiter::distributeBackendChanges() -{ - - // GIVEN - QScopedPointer<Qt3DCore::QChangeArbiter> arbiter(new Qt3DCore::QChangeArbiter()); - QScopedPointer<Qt3DCore::QScene> scene(new Qt3DCore::QScene()); - QScopedPointer<tst_PostManObserver> postman(new tst_PostManObserver); - arbiter->setPostman(postman.data()); - arbiter->setScene(scene.data()); - postman->setScene(scene.data()); - scene->setArbiter(arbiter.data()); - // Replaces initialize as we have no JobManager in this case - Qt3DCore::QChangeArbiter::createThreadLocalChangeQueue(arbiter.data()); - - // In order for backend -> frontend changes to work properly, - // the backend notification should only be sent - // from a worker thread which has a dedicated ChangeQueue in the - // ChangeArbiter different than the frontend ChangeQueue. In this - // test we will only check that the backend has received the frontend notification - - - // WHEN - tst_Node *root = new tst_Node(); - Qt3DCore::QNodePrivate::get(root)->setScene(scene.data()); - Qt3DCore::QNodePrivate::get(root)->m_hasBackendNode = true; - scene->addObservable(root); - - tst_BackendObserverObservable *backenObserverObservable = new tst_BackendObserverObservable(); - arbiter->registerObserver(Qt3DCore::QBackendNodePrivate::get(backenObserverObservable), root->id()); - arbiter->scene()->addObservable(Qt3DCore::QBackendNodePrivate::get(backenObserverObservable), root->id()); - Qt3DCore::QBackendNodePrivate::get(backenObserverObservable)->setArbiter(arbiter.data()); - - arbiter->syncChanges(); + root->setProp1(887); + child->setProp2(1587); // THEN - QVERIFY(root->lastChange().isNull()); - QVERIFY(backenObserverObservable->lastChange().isNull()); - QCOMPARE(backenObserverObservable->lastChanges().count(), 0); - - // WHEN - root->sendAllChangesNotification(); - arbiter->syncChanges(); - - // THEN - // backend observer receives event from frontend node "root" - QCOMPARE(root->lastChanges().count(), 0); - QCOMPARE(postman->lastChanges().count(), 0); - QTRY_COMPARE(backenObserverObservable->lastChanges().count(), 1); - - backenObserverObservable->clear(); - - { - // WHEN - // simulate a worker thread - QScopedPointer<ThreadedAnswer> answer(new ThreadedAnswer(arbiter.data(), backenObserverObservable)); - postman->setAllowFrontendNotifications(false); - QWaitCondition *waitingForBackendReplyCondition = answer->waitingCondition(); - - QMutex mutex; - // sends reply from another thread (simulates job thread) - answer->start(); - mutex.lock(); - waitingForBackendReplyCondition->wait(&mutex); - mutex.unlock(); - - // To verify that backendObserver sent a reply - arbiter->syncChanges(); - - // THEN - // the repliers should receive it's reply - QTRY_COMPARE(backenObserverObservable->lastChanges().count(), 1); - // verify that postMan has received the change - QCOMPARE(postman->lastChanges().count(), 0); - answer->exit(); - answer->wait(); - backenObserverObservable->clear(); - } - - { - // WHEN - // simulate a worker thread - QScopedPointer<ThreadedAnswer> answer(new ThreadedAnswer(arbiter.data(), backenObserverObservable)); - postman->setAllowFrontendNotifications(true); - QWaitCondition *waitingForBackendReplyCondition = answer->waitingCondition(); - QMutex mutex; - // sends reply from another thread (simulates job thread) - answer->start(); - mutex.lock(); - waitingForBackendReplyCondition->wait(&mutex); - mutex.unlock(); - - // To verify that backendObserver sent a reply - arbiter->syncChanges(); - - // THEN - // the repliers should receive it's reply - QTRY_COMPARE(backenObserverObservable->lastChanges().count(), 1); - // verify that postMan has received the change - QCOMPARE(postman->lastChanges().count(), 1); - - // verify correctness of the reply - Qt3DCore::QPropertyUpdatedChangePtr c = qSharedPointerDynamicCast<Qt3DCore::QPropertyUpdatedChange>(postman->lastChange()); - QVERIFY(!c.isNull()); - QVERIFY(c->subjectId() == root->id()); - qDebug() << c->propertyName(); - QVERIFY(strcmp(c->propertyName(), "Reply") == 0); - QVERIFY(c->type() == Qt3DCore::PropertyUpdated); - answer->exit(); - answer->wait(); - } - - Qt3DCore::QChangeArbiter::destroyThreadLocalChangeQueue(arbiter.data()); + QCOMPARE(arbiter->dirtyNodes.size(), 2); } QTEST_MAIN(tst_QChangeArbiter) diff --git a/tests/auto/render/opengl/graphicshelpergl4/BLACKLIST b/tests/auto/render/opengl/graphicshelpergl4/BLACKLIST new file mode 100644 index 000000000..ab691c11c --- /dev/null +++ b/tests/auto/render/opengl/graphicshelpergl4/BLACKLIST @@ -0,0 +1,4 @@ +# See qtbase/src/testlib/qtestblacklist.cpp for format +#QTBUG-101556 +[bindFrameBufferAttachment] +ubuntu-20 |