1// Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "technique_p.h"
5
6#include <Qt3DRender/qrenderpass.h>
7#include <Qt3DRender/qparameter.h>
8#include <Qt3DRender/qtechnique.h>
9#include <Qt3DRender/qgraphicsapifilter.h>
10#include <Qt3DRender/private/filterkey_p.h>
11#include <Qt3DRender/private/qtechnique_p.h>
12#include <Qt3DRender/private/shader_p.h>
13#include <Qt3DCore/private/qchangearbiter_p.h>
14#include <Qt3DRender/private/managers_p.h>
15#include <Qt3DRender/private/techniquemanager_p.h>
16#include <Qt3DRender/private/nodemanagers_p.h>
17
18#include <QDebug>
19
20QT_BEGIN_NAMESPACE
21
22using namespace Qt3DCore;
23
24namespace Qt3DRender {
25namespace Render {
26
27Technique::Technique()
28 : BackendNode()
29 , m_isCompatibleWithRenderer(false)
30 , m_nodeManager(nullptr)
31{
32}
33
34Technique::~Technique()
35{
36 cleanup();
37}
38
39void Technique::cleanup()
40{
41 QBackendNode::setEnabled(false);
42 m_parameterPack.clear();
43 m_renderPasses.clear();
44 m_filterKeyList.clear();
45 m_isCompatibleWithRenderer = false;
46}
47
48void Technique::syncFromFrontEnd(const QNode *frontEnd, bool firstTime)
49{
50 const QTechnique *node = qobject_cast<const QTechnique *>(object: frontEnd);
51
52 if (!node)
53 return;
54
55 bool dirty = isEnabled() != frontEnd->isEnabled();
56 BackendNode::syncFromFrontEnd(frontEnd, firstTime);
57
58 auto renderPasses = qIdsForNodes(nodes: node->renderPasses());
59 std::sort(first: std::begin(cont&: renderPasses), last: std::end(cont&: renderPasses));
60 if (m_renderPasses != renderPasses) {
61 m_renderPasses = renderPasses;
62 dirty = true;
63 }
64
65 auto parameters = qIdsForNodes(nodes: node->parameters());
66 std::sort(first: std::begin(cont&: parameters), last: std::end(cont&: parameters));
67 if (m_parameterPack.parameters() != parameters) {
68 m_parameterPack.setParameters(parameters);
69 dirty = true;
70 }
71
72 auto filterKeys = qIdsForNodes(nodes: node->filterKeys());
73 std::sort(first: std::begin(cont&: filterKeys), last: std::end(cont&: filterKeys));
74 if (m_filterKeyList != filterKeys) {
75 m_filterKeyList = filterKeys;
76 dirty = true;
77 }
78
79 auto graphicsApiFilterData = QGraphicsApiFilterPrivate::get(q: node->graphicsApiFilter())->m_data;
80 if (m_graphicsApiFilterData != graphicsApiFilterData) {
81 m_graphicsApiFilterData = graphicsApiFilterData;
82 m_isCompatibleWithRenderer = false;
83 dirty = true;
84 }
85
86 if (dirty) {
87 m_nodeManager->techniqueManager()->addDirtyTechnique(techniqueId: peerId());
88 markDirty(changes: AbstractRenderer::TechniquesDirty);
89 }
90}
91
92QList<Qt3DCore::QNodeId> Technique::parameters() const
93{
94 return m_parameterPack.parameters();
95}
96
97void Technique::appendRenderPass(Qt3DCore::QNodeId renderPassId)
98{
99 if (!m_renderPasses.contains(t: renderPassId))
100 m_renderPasses.append(t: renderPassId);
101}
102
103void Technique::removeRenderPass(Qt3DCore::QNodeId renderPassId)
104{
105 m_renderPasses.removeOne(t: renderPassId);
106}
107
108QList<Qt3DCore::QNodeId> Technique::filterKeys() const
109{
110 return m_filterKeyList;
111}
112
113QList<Qt3DCore::QNodeId> Technique::renderPasses() const
114{
115 return m_renderPasses;
116}
117
118const GraphicsApiFilterData *Technique::graphicsApiFilter() const
119{
120 return &m_graphicsApiFilterData;
121}
122
123bool Technique::isCompatibleWithRenderer() const
124{
125 return m_isCompatibleWithRenderer;
126}
127
128void Technique::setCompatibleWithRenderer(bool compatible)
129{
130 m_isCompatibleWithRenderer = compatible;
131}
132
133bool Technique::isCompatibleWithFilters(const QNodeIdVector &filterKeyIds)
134{
135 // There is a technique filter so we need to check for a technique with suitable criteria.
136 // Check for early bail out if the technique doesn't have sufficient number of criteria and
137 // can therefore never satisfy the filter
138 if (m_filterKeyList.size() < filterKeyIds.size())
139 return false;
140
141 // Iterate through the filter criteria and for each one search for a criteria on the
142 // technique that satisfies it
143 for (const QNodeId &filterKeyId : filterKeyIds) {
144 FilterKey *filterKey = m_nodeManager->filterKeyManager()->lookupResource(id: filterKeyId);
145
146 bool foundMatch = false;
147
148 for (const QNodeId &techniqueFilterKeyId : std::as_const(t&: m_filterKeyList)) {
149 FilterKey *techniqueFilterKey = m_nodeManager->filterKeyManager()->lookupResource(id: techniqueFilterKeyId);
150 if ((foundMatch = (*techniqueFilterKey == *filterKey)))
151 break;
152 }
153
154 // No match for TechniqueFilter criterion in any of the technique's criteria.
155 // So no way this can match. Don't bother checking the rest of the criteria.
156 if (!foundMatch)
157 return false;
158 }
159 return true;
160}
161
162void Technique::setNodeManager(NodeManagers *nodeManager)
163{
164 m_nodeManager = nodeManager;
165}
166
167NodeManagers *Technique::nodeManager() const
168{
169 return m_nodeManager;
170}
171
172void Technique::appendFilterKey(Qt3DCore::QNodeId criterionId)
173{
174 if (!m_filterKeyList.contains(t: criterionId))
175 m_filterKeyList.append(t: criterionId);
176}
177
178void Technique::removeFilterKey(Qt3DCore::QNodeId criterionId)
179{
180 m_filterKeyList.removeOne(t: criterionId);
181}
182
183TechniqueFunctor::TechniqueFunctor(AbstractRenderer *renderer, NodeManagers *manager)
184 : m_manager(manager)
185 , m_renderer(renderer)
186{
187}
188
189QBackendNode *TechniqueFunctor::create(Qt3DCore::QNodeId id) const
190{
191 Technique *technique = m_manager->techniqueManager()->getOrCreateResource(id);
192 technique->setNodeManager(m_manager);
193 technique->setRenderer(m_renderer);
194 return technique;
195}
196
197QBackendNode *TechniqueFunctor::get(QNodeId id) const
198{
199 return m_manager->techniqueManager()->lookupResource(id);
200}
201
202void TechniqueFunctor::destroy(QNodeId id) const
203{
204 m_manager->techniqueManager()->releaseResource(id);
205
206}
207
208} // namespace Render
209} // namespace Qt3DRender
210
211QT_END_NAMESPACE
212

source code of qt3d/src/render/materialsystem/technique.cpp