1// Copyright (C) 2019 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#ifndef QSSGSCENEMANAGER_P_H
5#define QSSGSCENEMANAGER_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtCore/QObject>
19#include <QtCore/QSet>
20
21#include <QtQuick3D/private/qtquick3dglobal_p.h>
22
23#include <QtQuick3DRuntimeRender/private/qssgrendergraphobject_p.h>
24
25#include "qquick3dnode_p.h"
26
27#include <QtCore/qpointer.h>
28
29QT_BEGIN_NAMESPACE
30
31class QSGDynamicTexture;
32class QQuickWindow;
33class QSSGBufferManager;
34class QSSGRenderContextInterface;
35class QSSGRenderRoot;
36struct QSSGRenderLayer;
37
38class Q_QUICK3D_EXPORT QQuick3DWindowAttachment : public QObject
39{
40 Q_OBJECT
41public:
42 enum SyncResultFlag : quint32
43 {
44 None,
45 SharedResourcesDirty = 0x1,
46 ExtensionsDiry = 0x2,
47 };
48
49 using SyncResult = std::underlying_type_t<SyncResultFlag>;
50
51 explicit QQuick3DWindowAttachment(QQuickWindow *window);
52 ~QQuick3DWindowAttachment() override;
53
54 Q_INVOKABLE void preSync();
55 Q_INVOKABLE void cleanupResources();
56 Q_INVOKABLE SyncResult synchronize(QSet<QSSGRenderGraphObject *> &resourceLoaders);
57 Q_INVOKABLE void requestUpdate();
58 Q_INVOKABLE void evaluateEol();
59
60 QQuickWindow *window() const;
61
62 QSSGRenderRoot *rootNode() const { return m_rootNode; }
63
64 const std::shared_ptr<QSSGRenderContextInterface> &rci() const { return m_rci; }
65 void setRci(const std::shared_ptr<QSSGRenderContextInterface> &rciptr);
66
67 void registerSceneManager(QQuick3DSceneManager &manager);
68 void unregisterSceneManager(QQuick3DSceneManager &manager);
69
70 void queueForCleanup(QSSGRenderGraphObject *obj);
71 void queueForCleanup(QQuick3DSceneManager *manager);
72 void queueForCleanup(QSSGRenderLayer *layer);
73
74Q_SIGNALS:
75 void releaseCachedResources();
76 void renderContextInterfaceChanged();
77
78private:
79 Q_INVOKABLE void onReleaseCachedResources();
80 Q_INVOKABLE void onInvalidated();
81
82 QPointer<QQuickWindow> m_window;
83 QSSGRenderRoot *m_rootNode = nullptr;
84 std::shared_ptr<QSSGRenderContextInterface> m_rci;
85 QList<QQuick3DSceneManager *> sceneManagers;
86 QList<QQuick3DSceneManager *> sceneManagerCleanupQueue;
87 QList<QSSGRenderGraphObject *> pendingResourceCleanupQueue;
88 QSet<QSSGRenderGraphObject *> resourceCleanupQueue;
89 QList<QSSGRenderLayer *> pendingLayerCleanupQueue;
90};
91
92class Q_QUICK3D_EXPORT QQuick3DSceneManager : public QObject
93{
94 Q_OBJECT
95public:
96 using SyncResultFlag = QQuick3DWindowAttachment::SyncResultFlag;
97 using SyncResult = QQuick3DWindowAttachment::SyncResult;
98
99 explicit QQuick3DSceneManager(QObject *parent = nullptr);
100 ~QQuick3DSceneManager() override;
101
102 void setWindow(QQuickWindow *window);
103 QQuickWindow *window();
104
105 void dirtyItem(QQuick3DObject *item);
106 void requestUpdate();
107 void cleanup(QSSGRenderGraphObject *item);
108
109 void polishItems();
110 void forcePolish();
111 void sync();
112 void preSync();
113
114 SyncResult cleanupNodes();
115 SyncResult updateDirtyResourceNodes();
116 void updateDirtySpatialNodes();
117 SyncResult updateDiryExtensions();
118 SyncResult updateDirtyResourceSecondPass();
119
120 void updateDirtyResource(QQuick3DObject *resourceObject);
121 void updateDirtySpatialNode(QQuick3DNode *spatialNode);
122 void updateBoundingBoxes(QSSGBufferManager &mgr);
123
124 QQuick3DObject *lookUpNode(const QSSGRenderGraphObject *node) const;
125
126 // Where the enumerator is placed will decide the priority it gets.
127 // NOTE: Place new list types before 'Count'.
128 // NOTE: InstanceNodes are nodes that have an instance root set, we'll process these
129 // after the other nodes but before light nodes; this implies that lights are not good candidates
130 // for being instance roots...
131 enum class NodePriority { Skeleton, Other, ModelWithInstanceRoot, Lights, Count };
132 enum class ResourcePriority { TextureData, Texture, Other, Count };
133 enum class ExtensionPriority { RenderExtension, Count };
134
135 static inline size_t resourceListIndex(QSSGRenderGraphObject::Type type)
136 {
137 Q_ASSERT(!QSSGRenderGraphObject::isNodeType(type));
138
139 if (QSSGRenderGraphObject::isTexture(type))
140 return size_t(ResourcePriority::Texture);
141
142 if (type == QSSGRenderGraphObject::Type::TextureData)
143 return size_t(ResourcePriority::TextureData);
144
145 return size_t(ResourcePriority::Other);
146 }
147
148 static inline size_t nodeListIndex(QSSGRenderGraphObject::Type type)
149 {
150 Q_ASSERT(QSSGRenderGraphObject::isNodeType(type));
151
152 if (QSSGRenderGraphObject::isLight(type))
153 return size_t(NodePriority::Lights);
154
155 if (type == QSSGRenderGraphObject::Type::Skeleton)
156 return size_t(NodePriority::Skeleton);
157
158 return size_t(NodePriority::Other);
159 }
160
161 static constexpr size_t extensionListIndex(QSSGRenderGraphObject::Type type)
162 {
163 Q_ASSERT(QSSGRenderGraphObject::isExtension(type));
164
165 return size_t(ExtensionPriority::RenderExtension);
166 }
167
168 static QQuick3DWindowAttachment *getOrSetWindowAttachment(QQuickWindow &window);
169
170 QQuick3DObject *dirtyResources[size_t(ResourcePriority::Count)] {};
171 QQuick3DObject *dirtyNodes[size_t(NodePriority::Count)] {};
172 QQuick3DObject *dirtyExtensions[size_t(ExtensionPriority::Count)] {};
173 // For exceptions to the norm we create a list of resources that
174 // we get a second update.
175 // In the case of the render extensions the resources are update first and for the
176 // first time the extensions have not been run and therefore have no backend node, which
177 // we'll need to use connect the render result from the extension with the texture.
178 QSet<QQuick3DObject *> dirtySecondPassResources;
179
180 QList<QQuick3DObject *> dirtyBoundingBoxList;
181 QSet<QSSGRenderGraphObject *> cleanupNodeList;
182 QList<QSSGRenderGraphObject *> resourceCleanupQueue;
183
184 QSet<QQuick3DObject *> parentlessItems;
185 QVector<QSGDynamicTexture *> qsgDynamicTextures;
186 QHash<QSSGRenderGraphObject *, QQuick3DObject *> m_nodeMap;
187 QSet<QSSGRenderGraphObject *> resourceLoaders;
188 QQuickWindow *m_window = nullptr;
189 QPointer<QQuick3DWindowAttachment> wattached;
190 int inputHandlingEnabled = 0; // Holds the count of active item2Ds, input disabled if zero.
191 bool sharedResourceRemoved = false;
192 friend QQuick3DObject;
193
194Q_SIGNALS:
195 void needsUpdate();
196 void windowChanged();
197
198private Q_SLOTS:
199 SyncResult updateResources(QQuick3DObject **listHead);
200 void updateNodes(QQuick3DObject **listHead);
201 SyncResult updateExtensions(QQuick3DObject **listHead);
202};
203
204class QSSGCleanupObject : public QObject
205{
206 Q_OBJECT
207public:
208 QSSGCleanupObject(std::shared_ptr<QSSGRenderContextInterface> rci,
209 QList<QSSGRenderGraphObject *> resourceCleanupQueue,
210 QQuickWindow *window);
211
212 ~QSSGCleanupObject() override;
213
214 Q_INVOKABLE void cleanupResources();
215
216private:
217 std::shared_ptr<QSSGRenderContextInterface> m_rci;
218 QPointer<QQuickWindow> m_window;
219 QList<QSSGRenderGraphObject *> m_resourceCleanupQueue;
220};
221
222QT_END_NAMESPACE
223
224QML_DECLARE_TYPE(QQuick3DSceneManager)
225
226#endif // QSSGSCENEMANAGER_P_H
227

source code of qtquick3d/src/quick3d/qquick3dscenemanager_p.h