summaryrefslogtreecommitdiffstats
path: root/src/render
diff options
context:
space:
mode:
authorMike Krus <mike.krus@kdab.com>2020-02-17 22:06:33 +0000
committerMike Krus <mike.krus@kdab.com>2020-02-17 22:06:44 +0000
commit67c9d9e9e665bb5754ffcdd5963189d73672f5a7 (patch)
tree2168cae3806c937ce1f1ce8faacdf83fe6c35df1 /src/render
parent8f9a0e499243915aca0e719fef0a5bb075542ea4 (diff)
parentaa7c8a5cb1111d46289e6b370dcd5b1d3f66c80d (diff)
Merge remote-tracking branch 5.15 into dev
Diffstat (limited to 'src/render')
-rw-r--r--src/render/backend/attachmentpack.cpp26
-rw-r--r--src/render/backend/attachmentpack_p.h6
-rw-r--r--src/render/backend/managers_p.h44
-rw-r--r--src/render/backend/rendertarget.cpp28
-rw-r--r--src/render/backend/rendertarget_p.h15
-rw-r--r--src/render/framegraph/qframegraphnode.cpp82
-rw-r--r--src/render/frontend/qrenderaspect.cpp2
-rw-r--r--src/render/jobs/genericlambdajob_p.h8
-rw-r--r--src/render/jobs/pickboundingvolumejob.cpp13
-rw-r--r--src/render/jobs/raycastingjob.cpp14
-rw-r--r--src/render/jobs/updatelevelofdetailjob.cpp14
-rw-r--r--src/render/materialsystem/shader.cpp8
-rw-r--r--src/render/materialsystem/shader_p.h2
-rw-r--r--src/render/texture/qtextureimagedata.h8
14 files changed, 240 insertions, 30 deletions
diff --git a/src/render/backend/attachmentpack.cpp b/src/render/backend/attachmentpack.cpp
index a2ac8c30c..0cd5d8673 100644
--- a/src/render/backend/attachmentpack.cpp
+++ b/src/render/backend/attachmentpack.cpp
@@ -88,6 +88,32 @@ int AttachmentPack::getDrawBufferIndex(QRenderTargetOutput::AttachmentPoint atta
return -1;
}
+bool operator ==(const Attachment &a, const Attachment &b)
+{
+ return (a.m_name == b.m_name &&
+ a.m_mipLevel == b.m_mipLevel &&
+ a.m_layer == b.m_layer &&
+ a.m_textureUuid == b.m_textureUuid &&
+ a.m_point == b.m_point &&
+ a.m_face == b.m_face);
+}
+
+bool operator !=(const Attachment &a, const Attachment &b)
+{
+ return !(a == b);
+}
+
+bool operator ==(const AttachmentPack &packA, const AttachmentPack &packB)
+{
+ return (packA.attachments() == packB.attachments() &&
+ packA.getGlDrawBuffers() == packB.getGlDrawBuffers());
+}
+
+bool operator !=(const AttachmentPack &packA, const AttachmentPack &packB)
+{
+ return !(packA == packB);
+}
+
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/render/backend/attachmentpack_p.h b/src/render/backend/attachmentpack_p.h
index 32ea774b6..7f3733a65 100644
--- a/src/render/backend/attachmentpack_p.h
+++ b/src/render/backend/attachmentpack_p.h
@@ -100,6 +100,12 @@ private:
QVector<int> m_drawBuffers;
};
+Q_3DRENDERSHARED_PRIVATE_EXPORT bool operator ==(const Attachment &a, const Attachment &b);
+Q_3DRENDERSHARED_PRIVATE_EXPORT bool operator !=(const Attachment &a, const Attachment &b);
+
+Q_3DRENDERSHARED_PRIVATE_EXPORT bool operator ==(const AttachmentPack &packA, const AttachmentPack &packB);
+Q_3DRENDERSHARED_PRIVATE_EXPORT bool operator !=(const AttachmentPack &packA, const AttachmentPack &packB);
+
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/render/backend/managers_p.h b/src/render/backend/managers_p.h
index db12a8a7b..a3d42d24a 100644
--- a/src/render/backend/managers_p.h
+++ b/src/render/backend/managers_p.h
@@ -211,6 +211,21 @@ public:
m_shaderIdsToCleanup.push_back(id);
}
+ void removeShaderIdFromIdsToCleanup(Qt3DCore::QNodeId id)
+ {
+ m_shaderIdsToCleanup.removeAll(id);
+ }
+
+ bool hasShaderIdToCleanup(Qt3DCore::QNodeId id) const
+ {
+ return m_shaderIdsToCleanup.contains(id);
+ }
+
+ QVector<Qt3DCore::QNodeId> shaderIdsToCleanup() const
+ {
+ return m_shaderIdsToCleanup;
+ }
+
// Called by RenderThread in updateGLResources (locked)
QVector<Qt3DCore::QNodeId> takeShaderIdsToCleanup()
{
@@ -285,6 +300,35 @@ class Q_3DRENDERSHARED_PRIVATE_EXPORT RenderTargetManager : public Qt3DCore::QRe
{
public:
RenderTargetManager() {}
+
+ // Called in AspectThread by RenderTarget node functor destroy
+ void addRenderTargetIdToCleanup(Qt3DCore::QNodeId id)
+ {
+ m_renderTargetIdsToCleanup.push_back(id);
+ }
+
+ // Called in AspectThread by RenderTarget node functor create
+ void removeRenderTargetToCleanup(Qt3DCore::QNodeId id)
+ {
+ m_renderTargetIdsToCleanup.removeAll(id);
+ }
+
+ // Called by RenderThread in updateGLResources (locked)
+ QVector<Qt3DCore::QNodeId> takeRenderTargetIdsToCleanup()
+ {
+ return std::move(m_renderTargetIdsToCleanup);
+ }
+
+#ifdef QT_BUILD_INTERNAL
+ // For unit testing purposes only
+ QVector<Qt3DCore::QNodeId> renderTargetIdsToCleanup() const
+ {
+ return m_renderTargetIdsToCleanup;
+ }
+#endif
+
+private:
+ QVector<Qt3DCore::QNodeId> m_renderTargetIdsToCleanup;
};
class Q_3DRENDERSHARED_PRIVATE_EXPORT RenderPassManager : public Qt3DCore::QResourceManager<
diff --git a/src/render/backend/rendertarget.cpp b/src/render/backend/rendertarget.cpp
index 088818c94..afe4bc23b 100644
--- a/src/render/backend/rendertarget.cpp
+++ b/src/render/backend/rendertarget.cpp
@@ -41,6 +41,7 @@
#include <Qt3DRender/qrendertarget.h>
#include <Qt3DRender/private/qrendertarget_p.h>
#include <Qt3DRender/qrendertargetoutput.h>
+#include <Qt3DRender/private/managers_p.h>
#include <QVariant>
QT_BEGIN_NAMESPACE
@@ -94,6 +95,33 @@ QVector<Qt3DCore::QNodeId> RenderTarget::renderOutputs() const
return m_renderOutputs;
}
+RenderTargetFunctor::RenderTargetFunctor(AbstractRenderer *renderer, RenderTargetManager *manager)
+ : m_renderer(renderer)
+ , m_renderTargetManager(manager)
+{
+}
+
+QBackendNode *RenderTargetFunctor::create(QNodeId id) const
+{
+ RenderTarget *backend = m_renderTargetManager->getOrCreateResource(id);
+ // Remove from the list of ids to destroy in case we were added to it
+ m_renderTargetManager->removeRenderTargetToCleanup(id);
+ backend->setRenderer(m_renderer);
+ return backend;
+}
+
+QBackendNode *RenderTargetFunctor::get(QNodeId id) const
+{
+ return m_renderTargetManager->lookupResource(id);
+}
+
+void RenderTargetFunctor::destroy(QNodeId id) const
+{
+ // We add ourselves to the dirty list to tell the renderer that this rendertarget has been destroyed
+ m_renderTargetManager->addRenderTargetIdToCleanup(id);
+ m_renderTargetManager->releaseResource(id);
+}
+
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/render/backend/rendertarget_p.h b/src/render/backend/rendertarget_p.h
index eeaf94940..67465cc1e 100644
--- a/src/render/backend/rendertarget_p.h
+++ b/src/render/backend/rendertarget_p.h
@@ -82,6 +82,21 @@ private:
QVector<Qt3DCore::QNodeId> m_renderOutputs;
};
+class Q_AUTOTEST_EXPORT RenderTargetFunctor : public Qt3DCore::QBackendNodeMapper
+{
+public:
+ explicit RenderTargetFunctor(AbstractRenderer *renderer,
+ RenderTargetManager *manager);
+ Qt3DCore::QBackendNode *create(Qt3DCore::QNodeId id) const final;
+ Qt3DCore::QBackendNode *get(Qt3DCore::QNodeId id) const final;
+ void destroy(Qt3DCore::QNodeId id) const final;
+
+private:
+ AbstractRenderer *m_renderer;
+ RenderTargetManager *m_renderTargetManager;
+};
+
+
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/render/framegraph/qframegraphnode.cpp b/src/render/framegraph/qframegraphnode.cpp
index 797e24324..489fa03b4 100644
--- a/src/render/framegraph/qframegraphnode.cpp
+++ b/src/render/framegraph/qframegraphnode.cpp
@@ -41,7 +41,7 @@
#include "qframegraphnode_p.h"
#include <Qt3DCore/QNode>
-
+#include <QVector>
#include <QQueue>
using namespace Qt3DCore;
@@ -59,35 +59,87 @@ QString dumpNode(const Qt3DRender::QFrameGraphNode *n) {
return res;
}
-QStringList dumpFG(const Qt3DRender::QFrameGraphNode *n, int level = 0)
+QStringList dumpFG(const Qt3DCore::QNode *n, int level = 0)
{
QStringList reply;
- QString res = dumpNode(n);
- reply += res.rightJustified(res.length() + level * 2, ' ');
+
+ const Qt3DRender::QFrameGraphNode *fgNode = qobject_cast<const Qt3DRender::QFrameGraphNode *>(n);
+ if (fgNode) {
+ QString res = dumpNode(fgNode);
+ reply += res.rightJustified(res.length() + level * 2, ' ');
+ }
const auto children = n->childNodes();
+ const int inc = fgNode ? 1 : 0;
for (auto *child: children) {
- auto *childFGNode = qobject_cast<Qt3DRender::QFrameGraphNode *>(child);
+ auto *childFGNode = qobject_cast<Qt3DCore::QNode *>(child);
if (childFGNode != nullptr)
- reply += dumpFG(childFGNode, level + 1);
+ reply += dumpFG(childFGNode, level + inc);
}
return reply;
}
-void dumpFGPaths(const Qt3DRender::QFrameGraphNode *n, QStringList &result, QStringList parents = {})
+struct HierarchyFGNode
+{
+ const Qt3DRender::QFrameGraphNode *root;
+ QVector<QSharedPointer<HierarchyFGNode>> children;
+};
+using HierarchyFGNodePtr = QSharedPointer<HierarchyFGNode>;
+
+HierarchyFGNodePtr buildFGHierarchy(const Qt3DCore::QNode *n, HierarchyFGNodePtr lastFGParent = HierarchyFGNodePtr())
{
- parents += dumpNode(n);
+ const Qt3DRender::QFrameGraphNode *fgNode = qobject_cast<const Qt3DRender::QFrameGraphNode *>(n);
+
+ // Only happens for the root case
+ if (!lastFGParent) {
+ lastFGParent = HierarchyFGNodePtr::create();
+ lastFGParent->root = fgNode;
+ } else {
+ if (fgNode != nullptr) {
+ HierarchyFGNodePtr hN = HierarchyFGNodePtr::create();
+ hN->root = fgNode;
+ if (lastFGParent)
+ lastFGParent->children.push_back(hN);
+ lastFGParent = hN;
+ }
+ }
const auto children = n->childNodes();
- if (children.length()) {
- for (auto *child: children) {
- auto *childFGNode = qobject_cast<Qt3DRender::QFrameGraphNode *>(child);
- if (childFGNode != nullptr)
- dumpFGPaths(childFGNode, result, parents);
+ for (auto *child: children)
+ buildFGHierarchy(child, lastFGParent);
+
+ return lastFGParent;
+}
+
+void findFGLeaves(const HierarchyFGNodePtr root, QVector<const Qt3DRender::QFrameGraphNode *> &fgLeaves)
+{
+ const auto children = root->children;
+ for (const auto &child : children)
+ findFGLeaves(child, fgLeaves);
+
+ if (children.empty())
+ fgLeaves.push_back(root->root);
+}
+
+void dumpFGPaths(const Qt3DRender::QFrameGraphNode *n, QStringList &result)
+{
+ // Build FG node hierarchy
+ const HierarchyFGNodePtr rootHFg = buildFGHierarchy(n);
+
+ // Gather FG leaves
+ QVector<const Qt3DRender::QFrameGraphNode *> fgLeaves;
+ findFGLeaves(rootHFg, fgLeaves);
+
+ // Traverse back to root
+ for (const Qt3DRender::QFrameGraphNode *fgNode : fgLeaves) {
+ QStringList parents;
+ while (fgNode != nullptr) {
+ parents.prepend(dumpNode(fgNode));
+ fgNode = fgNode->parentFrameGraphNode();
}
- } else {
- result << QLatin1String("[ ") + parents.join(QLatin1String(", ")) + QLatin1String(" ]");
+ if (parents.size())
+ result << QLatin1String("[ ") + parents.join(QLatin1String(", ")) + QLatin1String(" ]");
}
}
diff --git a/src/render/frontend/qrenderaspect.cpp b/src/render/frontend/qrenderaspect.cpp
index fa6416199..e929f532f 100644
--- a/src/render/frontend/qrenderaspect.cpp
+++ b/src/render/frontend/qrenderaspect.cpp
@@ -283,7 +283,7 @@ void QRenderAspectPrivate::registerBackendTypes()
q->registerBackendType<QLevelOfDetail>(QSharedPointer<Render::NodeFunctor<Render::LevelOfDetail, Render::LevelOfDetailManager> >::create(m_renderer));
q->registerBackendType<QLevelOfDetailSwitch>(QSharedPointer<Render::NodeFunctor<Render::LevelOfDetail, Render::LevelOfDetailManager> >::create(m_renderer));
q->registerBackendType<QSceneLoader>(QSharedPointer<Render::RenderSceneFunctor>::create(m_renderer, m_nodeManagers->sceneManager()));
- q->registerBackendType<QRenderTarget>(QSharedPointer<Render::NodeFunctor<Render::RenderTarget, Render::RenderTargetManager> >::create(m_renderer));
+ q->registerBackendType<QRenderTarget>(QSharedPointer<Render::RenderTargetFunctor>::create(m_renderer, m_nodeManagers->renderTargetManager()));
q->registerBackendType<QRenderTargetOutput>(QSharedPointer<Render::NodeFunctor<Render::RenderTargetOutput, Render::AttachmentManager> >::create(m_renderer));
q->registerBackendType<QRenderSettings>(QSharedPointer<Render::RenderSettingsFunctor>::create(m_renderer));
q->registerBackendType<QRenderState>(QSharedPointer<Render::NodeFunctor<Render::RenderStateNode, Render::RenderStateManager> >::create(m_renderer));
diff --git a/src/render/jobs/genericlambdajob_p.h b/src/render/jobs/genericlambdajob_p.h
index 8cf4276f6..994cd3a14 100644
--- a/src/render/jobs/genericlambdajob_p.h
+++ b/src/render/jobs/genericlambdajob_p.h
@@ -64,11 +64,11 @@ template<typename T>
class GenericLambdaJob : public Qt3DCore::QAspectJob
{
public:
- explicit GenericLambdaJob(T callable, JobTypes::JobType type = JobTypes::GenericLambda)
+ explicit GenericLambdaJob(T callable, JobTypes::JobType type = JobTypes::GenericLambda, const char *name = "GenericLambda")
: Qt3DCore::QAspectJob()
, m_callable(callable)
{
- SET_JOB_RUN_STAT_TYPE(this, type, 0)
+ SET_JOB_RUN_STAT_TYPE_AND_NAME(this, type, name, 0)
}
// QAspectJob interface
@@ -107,11 +107,11 @@ template<typename T, typename U>
class GenericLambdaJobAndPostFrame : public Qt3DCore::QAspectJob
{
public:
- explicit GenericLambdaJobAndPostFrame(T runCallable, U postFrameCallable, JobTypes::JobType type = JobTypes::GenericLambda)
+ explicit GenericLambdaJobAndPostFrame(T runCallable, U postFrameCallable, JobTypes::JobType type = JobTypes::GenericLambda, const char *name = "GenericLambda")
: Qt3DCore::QAspectJob(*new GenericLambdaJobAndPostFramePrivate<T, U>(postFrameCallable))
, m_runCallable(runCallable)
{
- SET_JOB_RUN_STAT_TYPE(this, type, 0)
+ SET_JOB_RUN_STAT_TYPE_AND_NAME(this, type, name, 0)
}
// QAspectJob interface
diff --git a/src/render/jobs/pickboundingvolumejob.cpp b/src/render/jobs/pickboundingvolumejob.cpp
index dce184f46..96610f9f7 100644
--- a/src/render/jobs/pickboundingvolumejob.cpp
+++ b/src/render/jobs/pickboundingvolumejob.cpp
@@ -71,9 +71,10 @@ namespace Render {
class PickBoundingVolumeJobPrivate : public Qt3DCore::QAspectJobPrivate
{
public:
- PickBoundingVolumeJobPrivate() = default;
+ PickBoundingVolumeJobPrivate(PickBoundingVolumeJob *q) : q_ptr(q) { }
~PickBoundingVolumeJobPrivate() override = default;
+ bool isRequired() override;
void postFrame(Qt3DCore::QAspectManager *manager) override;
enum CustomEventType {
@@ -88,9 +89,17 @@ public:
};
QVector<EventDetails> dispatches;
+ PickBoundingVolumeJob *q_ptr;
+ Q_DECLARE_PUBLIC(PickBoundingVolumeJob)
};
+bool PickBoundingVolumeJobPrivate::isRequired()
+{
+ Q_Q(PickBoundingVolumeJob);
+ return !q->m_pendingMouseEvents.isEmpty() || q->m_pickersDirty || q->m_oneEnabledAtLeast;
+}
+
void PickBoundingVolumeJobPrivate::postFrame(Qt3DCore::QAspectManager *manager)
{
using namespace Qt3DCore;
@@ -188,7 +197,7 @@ void setEventButtonAndModifiers(const QMouseEvent &event, QPickEvent::Buttons &e
} // anonymous
PickBoundingVolumeJob::PickBoundingVolumeJob()
- : AbstractPickingJob(*new PickBoundingVolumeJobPrivate)
+ : AbstractPickingJob(*new PickBoundingVolumeJobPrivate(this))
, m_pickersDirty(true)
{
SET_JOB_RUN_STAT_TYPE(this, JobTypes::PickBoundingVolume, 0)
diff --git a/src/render/jobs/raycastingjob.cpp b/src/render/jobs/raycastingjob.cpp
index 50dcaecde..df01213f0 100644
--- a/src/render/jobs/raycastingjob.cpp
+++ b/src/render/jobs/raycastingjob.cpp
@@ -86,15 +86,25 @@ public:
class Qt3DRender::Render::RayCastingJobPrivate : public Qt3DCore::QAspectJobPrivate
{
public:
- RayCastingJobPrivate() { }
+ RayCastingJobPrivate(RayCastingJob *q) : q_ptr(q) { }
~RayCastingJobPrivate() override { Q_ASSERT(dispatches.isEmpty()); }
+ bool isRequired() override;
void postFrame(Qt3DCore::QAspectManager *manager) override;
QVector<QPair<RayCaster *, QAbstractRayCaster::Hits>> dispatches;
+
+ RayCastingJob *q_ptr;
+ Q_DECLARE_PUBLIC(RayCastingJob)
};
+bool RayCastingJobPrivate::isRequired()
+{
+ Q_Q(RayCastingJob);
+ return q->m_castersDirty || q->m_oneEnabledAtLeast;
+}
+
void RayCastingJobPrivate::postFrame(Qt3DCore::QAspectManager *manager)
{
for (auto res: qAsConst(dispatches)) {
@@ -116,7 +126,7 @@ void RayCastingJobPrivate::postFrame(Qt3DCore::QAspectManager *manager)
RayCastingJob::RayCastingJob()
- : AbstractPickingJob(*new RayCastingJobPrivate())
+ : AbstractPickingJob(*new RayCastingJobPrivate(this))
, m_castersDirty(true)
{
SET_JOB_RUN_STAT_TYPE(this, JobTypes::RayCasting, 0)
diff --git a/src/render/jobs/updatelevelofdetailjob.cpp b/src/render/jobs/updatelevelofdetailjob.cpp
index 0a28b7628..946d3bca8 100644
--- a/src/render/jobs/updatelevelofdetailjob.cpp
+++ b/src/render/jobs/updatelevelofdetailjob.cpp
@@ -210,15 +210,19 @@ namespace Render {
class UpdateLevelOfDetailJobPrivate : public Qt3DCore::QAspectJobPrivate
{
public:
- UpdateLevelOfDetailJobPrivate() { }
+ UpdateLevelOfDetailJobPrivate(UpdateLevelOfDetailJob *q) : q_ptr(q) { }
+ bool isRequired() override;
void postFrame(Qt3DCore::QAspectManager *manager) override;
QVector<QPair<Qt3DCore::QNodeId, int>> m_updatedIndices;
+
+ UpdateLevelOfDetailJob *q_ptr;
+ Q_DECLARE_PUBLIC(UpdateLevelOfDetailJob)
};
UpdateLevelOfDetailJob::UpdateLevelOfDetailJob()
- : Qt3DCore::QAspectJob(*new UpdateLevelOfDetailJobPrivate)
+ : Qt3DCore::QAspectJob(*new UpdateLevelOfDetailJobPrivate(this))
, m_manager(nullptr)
, m_frameGraphRoot(nullptr)
, m_root(nullptr)
@@ -262,6 +266,12 @@ void UpdateLevelOfDetailJob::run()
d->m_updatedIndices = visitor.updatedIndices();
}
+bool UpdateLevelOfDetailJobPrivate::isRequired()
+{
+ Q_Q(UpdateLevelOfDetailJob);
+ return q->m_manager->levelOfDetailManager()->count() > 0;
+}
+
void UpdateLevelOfDetailJobPrivate::postFrame(Qt3DCore::QAspectManager *manager)
{
for (const auto &updatedNode: qAsConst(m_updatedIndices)) {
diff --git a/src/render/materialsystem/shader.cpp b/src/render/materialsystem/shader.cpp
index ff56a74e9..d0e2e9a76 100644
--- a/src/render/materialsystem/shader.cpp
+++ b/src/render/materialsystem/shader.cpp
@@ -189,15 +189,21 @@ ShaderFunctor::ShaderFunctor(AbstractRenderer *renderer, ShaderManager *manager)
{
}
-QBackendNode *ShaderFunctor::create(const QNodeId id) const
+QBackendNode *ShaderFunctor::create(QNodeId id) const
{
Shader *backend = m_shaderManager->getOrCreateResource(id);
+ // Remove from the list of ids to destroy in case we were added to it
+ m_shaderManager->removeShaderIdFromIdsToCleanup(id);
backend->setRenderer(m_renderer);
return backend;
}
QBackendNode *ShaderFunctor::get(QNodeId id) const
{
+ // If we are marked for destruction, return nullptr so that
+ // if we were to be recreated, create would be called again
+ if (m_shaderManager->hasShaderIdToCleanup(id))
+ return nullptr;
return m_shaderManager->lookupResource(id);
}
diff --git a/src/render/materialsystem/shader_p.h b/src/render/materialsystem/shader_p.h
index 8f78163be..31603bcf7 100644
--- a/src/render/materialsystem/shader_p.h
+++ b/src/render/materialsystem/shader_p.h
@@ -140,7 +140,7 @@ inline QDebug operator<<(QDebug dbg, const Shader &shader)
}
#endif
-class ShaderFunctor : public Qt3DCore::QBackendNodeMapper
+class Q_AUTOTEST_EXPORT ShaderFunctor : public Qt3DCore::QBackendNodeMapper
{
public:
explicit ShaderFunctor(AbstractRenderer *renderer,
diff --git a/src/render/texture/qtextureimagedata.h b/src/render/texture/qtextureimagedata.h
index 5bc71480e..8daf1becb 100644
--- a/src/render/texture/qtextureimagedata.h
+++ b/src/render/texture/qtextureimagedata.h
@@ -40,10 +40,14 @@
#ifndef QT3DRENDER_TEXTUREIMAGEDATA_H
#define QT3DRENDER_TEXTUREIMAGEDATA_H
-#include <QOpenGLTexture>
+#include <Qt3DRender/qt3drender_global.h>
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+# include <QOpenGLTexture>
+#else
+# include <QtGui/qopengltexture.h>
+#endif
#include <QtGui/QImage>
#include <QtCore/QSharedPointer>
-#include <Qt3DRender/qt3drender_global.h>
QT_BEGIN_NAMESPACE