aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/quick3d_visual/updatespatialnode/testupdatespatialnode.cpp
blob: a370356c2d75b000d99d60b1bbef07ebcbe38e34 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only

#include "testupdatespatialnode.h"
#include <ssg/qssgrenderextensions.h>
#include <ssg/qssgrenderhelpers.h>
#include <QThread>
#include <QTest>

#include <QtQuick3D/private/qquick3dobject_p.h>

#include <QtQuick3DRuntimeRender/private/qssgrendernode_p.h>

template <typename T>
static void tst_updateSpatialNode(QQuick3DObject *owner,
                                  TestData &testData,
                                  QSSGRenderGraphObject *&node)
{
    QVERIFY(owner != nullptr);

    // If updateSpatialNode is called there shall be a sceneManager set
    const auto sceneManager = QQuick3DObjectPrivate::get(owner)->sceneManager;
    Q_ASSERT(sceneManager);

    const auto &nodeMap = sceneManager->m_nodeMap;

    if (testData.callCount == 0) {
        // 1. The first time we'll create a new node
        // There should be no links to this object in the node map
        const auto values = nodeMap.values();
        QVERIFY(!values.contains(owner));
        QVERIFY(node == nullptr);
        node = new T;
    } else  if (testData.callCount == 1) {
        // 2. The second time we'll delete it and return nullptr.
        // This should cause any link to this object to be removed from the node map (On next sync).
        QVERIFY(node != nullptr);
        node = nullptr;
    } else if (testData.callCount == 2) {
        // 3. The third time we verify that the received node is nullptr (It was indeed uppdate)
        //    and then we'll create a new node.
        QVERIFY(node == nullptr);
        // There should be no links to this object in the node map
        const auto values = nodeMap.values();
        QVERIFY(!values.contains(owner));
        node = new T;
        testData.finalNode = node;
    } else if (testData.callCount == 3) {
        // The forth time we verify that the received node is the same as the new one.
        QCOMPARE(node, testData.finalNode);
    } else {
        Q_UNREACHABLE();
    }

    testData.callCount++;

    // as long as the count is less then the expected could we trigger an update
    const bool done = testData.callCount >= testData.expectedCallCount;
    if (!done)
        QMetaObject::invokeMethod(owner, "update", Qt::QueuedConnection);
}


/// RESOURCE OBJECT
///
///

TestData testData_ResourceObject { 3 };

class MyCustomGraphObject : public QSSGRenderGraphObject
{
public:
    MyCustomGraphObject() : QSSGRenderGraphObject(Type(BaseType::Resource)) {}
    ~MyCustomGraphObject() override
    {
        testData_ResourceObject.destroyedCount++;
    }
};

MyCustomResource::MyCustomResource(QQuick3DObject *parent)
    : QQuick3DObject(parent)
{
}

QSSGRenderGraphObject *MyCustomResource::updateSpatialNode(QSSGRenderGraphObject *node)
{
    tst_updateSpatialNode<MyCustomGraphObject>(this, testData_ResourceObject, node);

    return node;
}

/// NODE OBJECT
///
///

TestData testData_NodeObject { 3 };

class MyCustomRenderNode : public QSSGRenderNode
{
public:
    MyCustomRenderNode() : QSSGRenderNode() {}
    ~MyCustomRenderNode() override
    {
        testData_NodeObject.destroyedCount++;
    }
};

MyCustomNode::MyCustomNode(QQuick3DNode *parent)
    : QQuick3DNode(parent)
{

}

QSSGRenderGraphObject *MyCustomNode::updateSpatialNode(QSSGRenderGraphObject *node)
{
    tst_updateSpatialNode<MyCustomRenderNode>(this, testData_NodeObject, node);

    return node;
}

/// EXTENSION OBJECT
///
///

TestData testData_ExtensionObject { 3 };

class MyCustomExtensionImpl : public QSSGRenderExtension
{
public:
    MyCustomExtensionImpl() {}
    ~MyCustomExtensionImpl() override
    {
        testData_ExtensionObject.destroyedCount++;
    }

    bool prepareData(QSSGFrameData &data) override { Q_UNUSED(data); return true; }
    void prepareRender(QSSGFrameData &data) override { Q_UNUSED(data); }
    void render(QSSGFrameData &data) override { Q_UNUSED(data); }
    void resetForFrame() override {}

    RenderMode mode() const override { return RenderMode::Standalone; }
    RenderStage stage() const override { return RenderStage::PreColor; }
};

MyCustomExtension::MyCustomExtension(QQuick3DObject *parent)
    : QQuick3DRenderExtension(parent)
{

}

QSSGRenderGraphObject *MyCustomExtension::updateSpatialNode(QSSGRenderGraphObject *node)
{
    tst_updateSpatialNode<MyCustomExtensionImpl>(this, testData_ExtensionObject, node);

    return node;
}