Revision control
Copy as Markdown
// Copyright (C) 2019 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#ifndef QSSGSCENEMANAGER_P_H
#define QSSGSCENEMANAGER_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QtCore/QObject>
#include <QtCore/QSet>
#include <QtQuick3D/private/qtquick3dglobal_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrendergraphobject_p.h>
#include "qquick3dnode_p.h"
#include <QtCore/qpointer.h>
QT_BEGIN_NAMESPACE
class QSGDynamicTexture;
class QQuickWindow;
class QSSGBufferManager;
class QSSGRenderContextInterface;
class QSSGRenderRoot;
struct QSSGRenderLayer;
class QSSGRenderExtension;
class QSSGRenderUserPass;
class Q_QUICK3D_EXPORT QQuick3DWindowAttachment : public QObject
{
Q_OBJECT
public:
enum SyncResultFlag : quint32
{
None,
SharedResourcesDirty = 0x1,
ExtensionsDiry = 0x2,
};
using SyncResult = std::underlying_type_t<SyncResultFlag>;
explicit QQuick3DWindowAttachment(QQuickWindow *window);
~QQuick3DWindowAttachment() override;
Q_INVOKABLE void preSync();
Q_INVOKABLE void cleanupResources();
Q_INVOKABLE SyncResult synchronize(QSet<QSSGRenderGraphObject *> &resourceLoaders);
Q_INVOKABLE void requestUpdate();
Q_INVOKABLE void evaluateEol();
QQuickWindow *window() const;
QSSGRenderRoot *rootNode() const { return m_rootNode; }
const std::shared_ptr<QSSGRenderContextInterface> &rci() const { return m_rci; }
void setRci(const std::shared_ptr<QSSGRenderContextInterface> &rciptr);
void registerSceneManager(QQuick3DSceneManager &manager);
void unregisterSceneManager(QQuick3DSceneManager &manager);
void queueForCleanup(QSSGRenderGraphObject *obj);
void queueForCleanup(QQuick3DSceneManager *manager);
void queueForCleanup(QSSGRenderLayer *layer);
Q_SIGNALS:
void releaseCachedResources();
void renderContextInterfaceChanged();
private:
Q_INVOKABLE void onReleaseCachedResources();
Q_INVOKABLE void onInvalidated();
QPointer<QQuickWindow> m_window;
QSSGRenderRoot *m_rootNode = nullptr;
std::shared_ptr<QSSGRenderContextInterface> m_rci;
QList<QQuick3DSceneManager *> sceneManagers;
QList<QQuick3DSceneManager *> sceneManagerCleanupQueue;
QList<QSSGRenderGraphObject *> pendingResourceCleanupQueue;
QSet<QSSGRenderGraphObject *> resourceCleanupQueue;
QList<QSSGRenderLayer *> pendingLayerCleanupQueue;
};
class Q_QUICK3D_EXPORT QQuick3DSceneManager : public QObject
{
Q_OBJECT
public:
using SyncResultFlag = QQuick3DWindowAttachment::SyncResultFlag;
using SyncResult = QQuick3DWindowAttachment::SyncResult;
explicit QQuick3DSceneManager(QObject *parent = nullptr);
~QQuick3DSceneManager() override;
void setWindow(QQuickWindow *window);
QQuickWindow *window();
void dirtyItem(QQuick3DObject *item);
void requestUpdate();
void cleanup(QSSGRenderGraphObject *item);
void polishItems();
void forcePolish();
void sync();
void preSync();
SyncResult cleanupNodes();
SyncResult updateDirtyResourceNodes();
void updateDirtySpatialNodes();
SyncResult updateDiryExtensions();
SyncResult updateDirtyResourceSecondPass();
void updateDirtyResource(QQuick3DObject *resourceObject);
void updateDirtySpatialNode(QQuick3DNode *spatialNode);
void updateBoundingBoxes(QSSGBufferManager &mgr);
QQuick3DObject *lookUpNode(const QSSGRenderGraphObject *node) const;
// Where the enumerator is placed will decide the priority it gets.
// NOTE: Place new list types before 'Count'.
// NOTE: InstanceNodes are nodes that have an instance root set, we'll process these
// after the other nodes but before light nodes; this implies that lights are not good candidates
// for being instance roots...
enum class NodePriority { Skeleton, Other, ModelWithInstanceRoot, Lights, Count };
enum class ResourcePriority { TextureData, Texture, Other, Count };
enum class ExtensionPriority { RenderExtension, Count };
static inline size_t resourceListIndex(QSSGRenderGraphObject::Type type)
{
Q_ASSERT(!QSSGRenderGraphObject::isNodeType(type));
if (QSSGRenderGraphObject::isTexture(type))
return size_t(ResourcePriority::Texture);
if (type == QSSGRenderGraphObject::Type::TextureData)
return size_t(ResourcePriority::TextureData);
return size_t(ResourcePriority::Other);
}
static inline size_t nodeListIndex(QSSGRenderGraphObject::Type type)
{
Q_ASSERT(QSSGRenderGraphObject::isNodeType(type));
if (QSSGRenderGraphObject::isLight(type))
return size_t(NodePriority::Lights);
if (type == QSSGRenderGraphObject::Type::Skeleton)
return size_t(NodePriority::Skeleton);
return size_t(NodePriority::Other);
}
static constexpr size_t extensionListIndex(QSSGRenderGraphObject::Type type)
{
Q_ASSERT(QSSGRenderGraphObject::isExtension(type));
return size_t(ExtensionPriority::RenderExtension);
}
static QQuick3DWindowAttachment *getOrSetWindowAttachment(QQuickWindow &window);
QQuick3DObject *dirtyResources[size_t(ResourcePriority::Count)] {};
QQuick3DObject *dirtyNodes[size_t(NodePriority::Count)] {};
QQuick3DObject *dirtyExtensions[size_t(ExtensionPriority::Count)] {};
// For exceptions to the norm we create a list of resources that
// we get a second update.
// In the case of the render extensions the resources are update first and for the
// first time the extensions have not been run and therefore have no backend node, which
// we'll need to use connect the render result from the extension with the texture.
QSet<QQuick3DObject *> dirtySecondPassResources;
QList<QQuick3DObject *> dirtyBoundingBoxList;
QSet<QSSGRenderGraphObject *> cleanupNodeList;
QList<QSSGRenderGraphObject *> resourceCleanupQueue;
QSet<QQuick3DObject *> parentlessItems;
QVector<QSGDynamicTexture *> qsgDynamicTextures;
QHash<QSSGRenderGraphObject *, QQuick3DObject *> m_nodeMap;
QSet<QSSGRenderGraphObject *> resourceLoaders;
QList<QSSGRenderExtension *> autoRegisteredExtensions;
QList<QSSGRenderUserPass *> userRenderPasses;
QQuickWindow *m_window = nullptr;
QPointer<QQuick3DWindowAttachment> wattached;
int inputHandlingEnabled = 0; // Holds the count of active item2Ds, input disabled if zero.
bool sharedResourceRemoved = false;
bool autoRegisteredExtensionsDirty = false;
bool userRenderPassesDirty = true;
friend QQuick3DObject;
struct LightmapSourceTracker
{
QString lightmapSource;
bool isDirty = true;
} lightmapSourceTracker;
Q_SIGNALS:
void needsUpdate();
void windowChanged();
private Q_SLOTS:
SyncResult updateResources(QQuick3DObject **listHead);
void updateNodes(QQuick3DObject **listHead);
SyncResult updateExtensions(QQuick3DObject **listHead);
};
class QSSGCleanupObject : public QObject
{
Q_OBJECT
public:
QSSGCleanupObject(std::shared_ptr<QSSGRenderContextInterface> rci,
QList<QSSGRenderGraphObject *> resourceCleanupQueue,
QQuickWindow *window);
~QSSGCleanupObject() override;
Q_INVOKABLE void cleanupResources();
private:
std::shared_ptr<QSSGRenderContextInterface> m_rci;
QPointer<QQuickWindow> m_window;
QList<QSSGRenderGraphObject *> m_resourceCleanupQueue;
};
QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuick3DSceneManager)
#endif // QSSGSCENEMANAGER_P_H