Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qsgsoftwarerenderablenodeupdater.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
6
14
15#include <QtQuick/qsgsimplerectnode.h>
16#include <QtQuick/qsgsimpletexturenode.h>
17#include <QtQuick/qsgrendernode.h>
18
19QT_BEGIN_NAMESPACE
20
22 : m_renderer(renderer)
23{
24 m_opacityState.push(1.0f);
25 // Invalid RectF by default for no clip
26 m_clipState.push(QRegion());
27 m_hasClip = false;
28 m_transformState.push(QTransform());
29}
30
31QSGSoftwareRenderableNodeUpdater::~QSGSoftwareRenderableNodeUpdater()
32{
33
34}
35
36bool QSGSoftwareRenderableNodeUpdater::visit(QSGTransformNode *node)
37{
38 m_transformState.push(node->matrix().toTransform() * m_transformState.top());
39 m_stateMap[node] = currentState(node);
40 return true;
41}
42
43void QSGSoftwareRenderableNodeUpdater::endVisit(QSGTransformNode *)
44{
45 m_transformState.pop();
46}
47
48bool QSGSoftwareRenderableNodeUpdater::visit(QSGClipNode *node)
49{
50 // Make sure to translate the clip rect into world coordinates
51 if (m_clipState.size() == 0 || (m_clipState.size() == 1 && m_clipState.top().isNull())) {
52 m_clipState.push(m_transformState.top().map(QRegion(node->clipRect().toRect())));
53 m_hasClip = true;
54 } else {
55 const QRegion transformedClipRect = m_transformState.top().map(QRegion(node->clipRect().toRect()));
56 m_clipState.push(transformedClipRect.intersected(m_clipState.top()));
57 }
58 m_stateMap[node] = currentState(node);
59 return true;
60}
61
62void QSGSoftwareRenderableNodeUpdater::endVisit(QSGClipNode *)
63{
64 m_clipState.pop();
65 if (m_clipState.size() == 0 || (m_clipState.size() == 1 && m_clipState.top().isNull()))
66 m_hasClip = false;
67}
68
69bool QSGSoftwareRenderableNodeUpdater::visit(QSGGeometryNode *node)
70{
71 if (QSGSimpleRectNode *rectNode = dynamic_cast<QSGSimpleRectNode *>(node)) {
72 return updateRenderableNode(QSGSoftwareRenderableNode::SimpleRect, rectNode);
73 } else if (QSGSimpleTextureNode *tn = dynamic_cast<QSGSimpleTextureNode *>(node)) {
74 return updateRenderableNode(QSGSoftwareRenderableNode::SimpleTexture, tn);
75 } else if (QSGNinePatchNode *nn = dynamic_cast<QSGNinePatchNode *>(node)) {
76 return updateRenderableNode(QSGSoftwareRenderableNode::NinePatch, nn);
77 } else if (QSGRectangleNode *rn = dynamic_cast<QSGRectangleNode *>(node)) {
78 return updateRenderableNode(QSGSoftwareRenderableNode::SimpleRectangle, rn);
79 } else if (QSGImageNode *n = dynamic_cast<QSGImageNode *>(node)) {
80 return updateRenderableNode(QSGSoftwareRenderableNode::SimpleImage, n);
81 } else {
82 // We dont know, so skip
83 return false;
84 }
85}
86
87void QSGSoftwareRenderableNodeUpdater::endVisit(QSGGeometryNode *)
88{
89}
90
91bool QSGSoftwareRenderableNodeUpdater::visit(QSGOpacityNode *node)
92{
93 m_opacityState.push(m_opacityState.top() * node->opacity());
94 m_stateMap[node] = currentState(node);
95 return true;
96}
97
98void QSGSoftwareRenderableNodeUpdater::endVisit(QSGOpacityNode *)
99{
100 m_opacityState.pop();
101}
102
103bool QSGSoftwareRenderableNodeUpdater::visit(QSGInternalImageNode *node)
104{
105 return updateRenderableNode(QSGSoftwareRenderableNode::Image, node);
106}
107
108void QSGSoftwareRenderableNodeUpdater::endVisit(QSGInternalImageNode *)
109{
110}
111
112bool QSGSoftwareRenderableNodeUpdater::visit(QSGPainterNode *node)
113{
114 return updateRenderableNode(QSGSoftwareRenderableNode::Painter, node);
115}
116
117void QSGSoftwareRenderableNodeUpdater::endVisit(QSGPainterNode *)
118{
119}
120
121bool QSGSoftwareRenderableNodeUpdater::visit(QSGInternalRectangleNode *node)
122{
123 return updateRenderableNode(QSGSoftwareRenderableNode::Rectangle, node);
124}
125
126void QSGSoftwareRenderableNodeUpdater::endVisit(QSGInternalRectangleNode *)
127{
128}
129
130bool QSGSoftwareRenderableNodeUpdater::visit(QSGGlyphNode *node)
131{
132 return updateRenderableNode(QSGSoftwareRenderableNode::Glyph, node);
133}
134
135void QSGSoftwareRenderableNodeUpdater::endVisit(QSGGlyphNode *)
136{
137}
138
139bool QSGSoftwareRenderableNodeUpdater::visit(QSGRootNode *node)
140{
141 m_stateMap[node] = currentState(node);
142 return true;
143}
144
145void QSGSoftwareRenderableNodeUpdater::endVisit(QSGRootNode *)
146{
147}
148
149#if QT_CONFIG(quick_sprite)
150bool QSGSoftwareRenderableNodeUpdater::visit(QSGSpriteNode *node)
151{
152 return updateRenderableNode(QSGSoftwareRenderableNode::SpriteNode, node);
153}
154
155void QSGSoftwareRenderableNodeUpdater::endVisit(QSGSpriteNode *)
156{
157
158}
159#endif
160
161bool QSGSoftwareRenderableNodeUpdater::visit(QSGRenderNode *node)
162{
163 return updateRenderableNode(QSGSoftwareRenderableNode::RenderNode, node);
164}
165
166void QSGSoftwareRenderableNodeUpdater::endVisit(QSGRenderNode *)
167{
168}
169
170void QSGSoftwareRenderableNodeUpdater::updateNodes(QSGNode *node, bool isNodeRemoved)
171{
172 m_opacityState.clear();
173 m_clipState.clear();
174 m_transformState.clear();
175
176 auto parentNode = node->parent();
177 // If the node was deleted, it will have no parent
178 // check if the state map has the previous parent
179 if ((!parentNode || isNodeRemoved ) && m_stateMap.contains(node))
180 parentNode = m_stateMap[node].parent;
181
182 // If we find a parent, use its state for updating the new children
183 if (parentNode && m_stateMap.contains(parentNode)) {
184 auto state = m_stateMap[parentNode];
185 m_opacityState.push(state.opacity);
186 m_transformState.push(state.transform);
187 m_clipState.push(state.clip);
188 m_hasClip = state.hasClip;
189 } else {
190 // There is no parent, and no previous parent, so likely a root node
191 m_opacityState.push(1.0f);
192 m_transformState.push(QTransform());
193 m_clipState.push(QRegion());
194 m_hasClip = false;
195 }
196
197 // If the node is being removed, then cleanup the state data
198 // Then just visit the children without visiting the now removed node
199 if (isNodeRemoved) {
200 m_stateMap.remove(node);
201 return;
202 }
203
204 // Visit the current node itself first
205 switch (node->type()) {
206 case QSGNode::ClipNodeType: {
207 QSGClipNode *c = static_cast<QSGClipNode*>(node);
208 if (visit(c))
209 visitChildren(c);
210 endVisit(c);
211 break;
212 }
213 case QSGNode::TransformNodeType: {
214 QSGTransformNode *c = static_cast<QSGTransformNode*>(node);
215 if (visit(c))
216 visitChildren(c);
217 endVisit(c);
218 break;
219 }
220 case QSGNode::OpacityNodeType: {
221 QSGOpacityNode *c = static_cast<QSGOpacityNode*>(node);
222 if (visit(c))
223 visitChildren(c);
224 endVisit(c);
225 break;
226 }
227 case QSGNode::GeometryNodeType: {
228 if (node->flags() & QSGNode::IsVisitableNode) {
229 QSGVisitableNode *v = static_cast<QSGVisitableNode*>(node);
230 v->accept(this);
231 } else {
232 QSGGeometryNode *c = static_cast<QSGGeometryNode*>(node);
233 if (visit(c))
234 visitChildren(c);
235 endVisit(c);
236 }
237 break;
238 }
239 case QSGNode::RootNodeType: {
240 QSGRootNode *root = static_cast<QSGRootNode*>(node);
241 if (visit(root))
242 visitChildren(root);
243 endVisit(root);
244 break;
245 }
246 case QSGNode::BasicNodeType: {
247 visitChildren(node);
248 break;
249 }
250 case QSGNode::RenderNodeType: {
251 QSGRenderNode *r = static_cast<QSGRenderNode*>(node);
252 if (visit(r))
253 visitChildren(r);
254 endVisit(r);
255 break;
256 }
257 default:
258 Q_UNREACHABLE();
259 break;
260 }
261}
262
263QSGSoftwareRenderableNodeUpdater::NodeState QSGSoftwareRenderableNodeUpdater::currentState(QSGNode *node) const
264{
265 NodeState state;
266 state.opacity = m_opacityState.top();
267 state.clip = m_clipState.top();
268 state.hasClip = m_hasClip;
269 state.transform = m_transformState.top();
270 state.parent = node->parent();
271 return state;
272}
273
274QT_END_NAMESPACE