summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTarja Sundqvist <tarja.sundqvist@qt.io>2023-03-23 15:59:10 +0200
committerTarja Sundqvist <tarja.sundqvist@qt.io>2023-03-23 15:59:10 +0200
commite94b0fa39a2f4bf260969fb18bf075dba39b2df1 (patch)
treeff3e15fc92de5ff410db03b22510b76526c42d94
parentc3c7e6ebc29cce466d954f72f340a257d76b5ec2 (diff)
parentb85ba6f86396f28ab7326da0c7c5cebfeb0fe02f (diff)
downloadqt3d-5.15.tar.gz
Merge remote-tracking branch 'origin/tqtc/lts-5.15.9' into tqtc/lts-5.15-opensourcev5.15.9-lts-lgpl5.15
Change-Id: I23c3c668f84eb2ef9108a217fa85185b6422402b
-rw-r--r--.qmake.conf2
-rw-r--r--src/quick3d/imports/scene3d/scene3dview.cpp38
-rw-r--r--src/quick3d/imports/scene3d/scene3dview_p.h9
-rw-r--r--tests/auto/core/qchangearbiter/qchangearbiter.pro2
-rw-r--r--tests/auto/core/qchangearbiter/tst_qchangearbiter.cpp810
-rw-r--r--tests/auto/render/opengl/graphicshelpergl4/BLACKLIST4
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