Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qsgnode.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
5
#
include
"qsgnode.h"
6
#
include
"qsgnode_p.h"
7
#
include
"qsgrenderer_p.h"
8
#
include
"qsgnodeupdater_p.h"
9
#
include
"qsgmaterial.h"
10
11
#
include
<
algorithm
>
12
13
#
include
"limits.h"
14
15
QT_BEGIN_NAMESPACE
16
17
#
ifndef
QT_NO_DEBUG
18
static
int
qt_node_count
= 0;
19
20
static
void
qt_print_node_count
()
21
{
22
qCDebug(lcQsgLeak,
"Number of leaked nodes: %i"
, qt_node_count);
23
qt_node_count
= -1;
24
}
25
#
endif
26
27
/*!
28
\group qtquick-scenegraph-nodes
29
\title Qt Quick Scene Graph Node classes
30
\brief Nodes that can be used as part of the scene graph.
31
32
This page lists the nodes in \l {Qt Quick}'s \l {Qt Quick Scene Graph}{scene graph}.
33
*/
34
35
/*!
36
\class QSGNode
37
\brief The QSGNode class is the base class for all nodes in the scene graph.
38
39
\inmodule QtQuick
40
\ingroup qtquick-scenegraph-nodes
41
42
The QSGNode class can be used as a child container. Children are added with
43
the appendChildNode(), prependChildNode(), insertChildNodeBefore() and
44
insertChildNodeAfter(). The order of nodes is important as geometry nodes
45
are rendered according to their ordering in the scene graph.
46
47
The scene graph nodes contain a mechanism that describes which
48
parts of the scene have changed. This includes the combined matrices,
49
accumulated opacity, changes to the node hierarchy, and so on. This
50
information can be used for optimizations inside the scene graph renderer.
51
For the renderer to properly render the nodes, it is important that users
52
call QSGNode::markDirty() with the correct flags when nodes are changed.
53
Most of the functions on the node classes will implicitly call markDirty().
54
For example, QSGNode::appendChildNode() will call markDirty() passing in
55
QSGNode::DirtyNodeAdded.
56
57
If nodes change every frame, the preprocess() function can be used to
58
apply changes to a node for every frame it is rendered. The use of
59
preprocess() must be explicitly enabled by setting the
60
QSGNode::UsePreprocess flag on the node.
61
62
The virtual isSubtreeBlocked() function can be used to disable a subtree all
63
together. Nodes in a blocked subtree will not be preprocessed() and not
64
rendered.
65
66
\note All classes with QSG prefix should be used solely on the scene graph's
67
rendering thread. See \l {Scene Graph and Rendering} for more information.
68
*/
69
70
/*!
71
\enum QSGNode::DirtyStateBit
72
73
Used in QSGNode::markDirty() to indicate how the scene graph has changed.
74
75
\value DirtyMatrix The matrix in a QSGTransformNode has changed.
76
\value DirtyNodeAdded A node was added.
77
\value DirtyNodeRemoved A node was removed.
78
\value DirtyGeometry The geometry of a QSGGeometryNode has changed.
79
\value DirtyMaterial The material of a QSGGeometryNode has changed.
80
\value DirtyOpacity The opacity of a QSGOpacityNode has changed.
81
\value DirtySubtreeBlocked The subtree has been blocked.
82
83
\omitvalue DirtyForceUpdate
84
\omitvalue DirtyUsePreprocess
85
\omitvalue DirtyPropagationMask
86
87
\sa QSGNode::markDirty()
88
*/
89
90
/*!
91
\enum QSGNode::Flag
92
93
The QSGNode::Flag enum describes flags on the QSGNode
94
95
\value OwnedByParent The node is owned by its parent and will be deleted
96
when the parent is deleted.
97
\value UsePreprocess The node's virtual preprocess() function will be called
98
before rendering starts.
99
\value OwnsGeometry Only valid for QSGGeometryNode and QSGClipNode.
100
The node has ownership over the QSGGeometry instance and will
101
delete it when the node is destroyed or a geometry is assigned.
102
\value OwnsMaterial Only valid for QSGGeometryNode. The node has ownership
103
over the material and will delete it when the node is destroyed or a material is assigned.
104
\value OwnsOpaqueMaterial Only valid for QSGGeometryNode. The node has
105
ownership over the opaque material and will delete it when the node is
106
destroyed or a material is assigned.
107
\value InternalReserved Reserved for internal use.
108
109
\omitvalue IsVisitableNode
110
\omitvalue IsNodeBlocked
111
*/
112
113
/*!
114
\enum QSGNode::NodeType
115
116
Can be used to figure out the type of node.
117
118
\value BasicNodeType The type of QSGNode
119
\value GeometryNodeType The type of QSGGeometryNode
120
\value TransformNodeType The type of QSGTransformNode
121
\value ClipNodeType The type of QSGClipNode
122
\value OpacityNodeType The type of QSGOpacityNode
123
\value RenderNodeType The type of QSGRenderNode
124
125
\omitvalue RootNodeType
126
127
\sa type()
128
*/
129
130
/*!
131
\fn QSGNode *QSGNode::childAtIndex(int i) const
132
133
Returns the child at index \a i.
134
135
Children are stored internally as a linked list, so iterating
136
over the children via the index is suboptimal.
137
*/
138
139
/*!
140
\fn int QSGNode::childCount() const
141
142
Returns the number of child nodes.
143
*/
144
145
/*!
146
\fn void QSGNode::clearDirty()
147
148
\internal
149
*/
150
151
/*!
152
\fn QSGNode *QSGNode::firstChild() const
153
154
Returns the first child of this node.
155
156
The children are stored in a linked list.
157
*/
158
159
/*!
160
\fn QSGNode *QSGNode::lastChild() const
161
162
Returns the last child of this node.
163
164
The children are stored as a linked list.
165
*/
166
167
/*!
168
\fn QSGNode::Flags QSGNode::flags() const
169
170
Returns the set of flags for this node.
171
*/
172
173
/*!
174
\fn QSGNode *QSGNode::nextSibling() const
175
176
Returns the node after this in the parent's list of children.
177
178
The children are stored as a linked list.
179
*/
180
181
/*!
182
\fn QSGNode *QSGNode::previousSibling() const
183
184
Returns the node before this in the parent's list of children.
185
186
The children are stored as a linked list.
187
*/
188
189
/*!
190
\fn QSGNode::Type QSGNode::type() const
191
192
Returns the type of this node. The node type must be one of the
193
predefined types defined in QSGNode::NodeType and can safely be
194
used to cast to the corresponding class.
195
*/
196
197
/*!
198
\fn QSGNode::DirtyState QSGNode::dirtyState() const
199
200
\internal
201
*/
202
203
/*!
204
\fn QSGNode *QSGNode::parent() const
205
206
Returns the parent node of this node.
207
*/
208
209
210
/*!
211
* Constructs a new node
212
*/
213
QSGNode::QSGNode()
214
: m_nodeFlags(OwnedByParent)
215
{
216
init();
217
}
218
219
/*!
220
* Constructs a new node with the given node type.
221
*
222
* \internal
223
*/
224
QSGNode::QSGNode(NodeType type)
225
: m_parent(
nullptr
)
226
, m_type(type)
227
, m_firstChild(
nullptr
)
228
, m_lastChild(
nullptr
)
229
, m_nextSibling(
nullptr
)
230
, m_previousSibling(
nullptr
)
231
, m_subtreeRenderableCount(type == GeometryNodeType || type == RenderNodeType ? 1 : 0)
232
, m_nodeFlags(OwnedByParent)
233
{
234
init();
235
}
236
237
/*!
238
* Constructs a new node with the given node type.
239
*
240
* \internal
241
*/
242
QSGNode::QSGNode(QSGNodePrivate &dd, NodeType type)
243
: m_parent(
nullptr
)
244
, m_type(type)
245
, m_firstChild(
nullptr
)
246
, m_lastChild(
nullptr
)
247
, m_nextSibling(
nullptr
)
248
, m_previousSibling(
nullptr
)
249
, m_subtreeRenderableCount(type == GeometryNodeType || type == RenderNodeType ? 1 : 0)
250
, m_nodeFlags(OwnedByParent)
251
, d_ptr(&dd)
252
{
253
init();
254
}
255
256
/*!
257
* \internal
258
*/
259
void
QSGNode::init()
260
{
261
#
ifndef
QT_NO_DEBUG
262
if
(lcQsgLeak().isDebugEnabled()) {
263
++qt_node_count;
264
static
bool
atexit_registered =
false
;
265
if
(!atexit_registered) {
266
atexit(qt_print_node_count);
267
atexit_registered =
true
;
268
}
269
}
270
#
endif
271
272
#
ifdef
QSG_RUNTIME_DESCRIPTION
273
if
(d_ptr.isNull())
274
d_ptr.reset(
new
QSGNodePrivate());
275
#
endif
276
}
277
278
/*!
279
* Destroys the node.
280
*
281
* Every child of this node that has the flag QSGNode::OwnedByParent set,
282
* will also be deleted.
283
*/
284
QSGNode::~QSGNode()
285
{
286
#
ifndef
QT_NO_DEBUG
287
if
(lcQsgLeak().isDebugEnabled()) {
288
--qt_node_count;
289
if
(qt_node_count < 0)
290
qCDebug(lcQsgLeak,
"Node destroyed after qt_print_node_count() was called."
);
291
}
292
#
endif
293
destroy();
294
}
295
296
297
/*!
298
\fn void QSGNode::preprocess()
299
300
Override this function to do processing on the node before it is rendered.
301
302
Preprocessing needs to be explicitly enabled by setting the flag
303
QSGNode::UsePreprocess. The flag needs to be set before the node is added
304
to the scene graph and will cause the preprocess() function to be called
305
for every frame the node is rendered.
306
307
\warning Beware of deleting nodes while they are being preprocessed. It is
308
possible, with a small performance hit, to delete a single node during its
309
own preprocess call. Deleting a subtree which has nodes that also use
310
preprocessing may result in a segmentation fault. This is done for
311
performance reasons.
312
*/
313
314
315
316
317
/*!
318
Returns whether this node and its subtree is available for use.
319
320
Blocked subtrees will not get their dirty states updated and they
321
will not be rendered.
322
323
The QSGOpacityNode will return a blocked subtree when accumulated opacity
324
is 0, for instance.
325
*/
326
327
bool
QSGNode::isSubtreeBlocked()
const
328
{
329
return
flags().testFlag(IsNodeBlocked);
330
}
331
332
/*!
333
\internal
334
Detaches the node from the scene graph and deletes any children it owns.
335
336
This function is called from QSGNode's and QSGRootNode's destructor. It
337
should not be called explicitly in user code. QSGRootNode needs to call
338
destroy() because destroy() calls removeChildNode() which in turn calls
339
markDirty() which type-casts the node to QSGRootNode. This type-cast is not
340
valid at the time QSGNode's destructor is called because the node will
341
already be partially destroyed at that point.
342
*/
343
344
void
QSGNode::destroy()
345
{
346
if
(m_parent) {
347
m_parent->removeChildNode(
this
);
348
Q_ASSERT(m_parent ==
nullptr
);
349
}
350
while
(m_firstChild) {
351
QSGNode *child = m_firstChild;
352
removeChildNode(child);
353
Q_ASSERT(child->m_parent ==
nullptr
);
354
if
(child->flags() & OwnedByParent)
355
delete
child;
356
}
357
358
Q_ASSERT(m_firstChild ==
nullptr
&& m_lastChild ==
nullptr
);
359
}
360
361
quint8 QSGNodePrivate::mutabilityGroup(
const
QSGNode *node)
362
{
363
return
!node->d_ptr.isNull()
364
? node->d_ptr->m_mutabilityGroup
365
: 0;
366
}
367
368
/*!
369
\internal
370
371
Sets the mutability group of this node. Recurses to children.
372
*/
373
void
QSGNodePrivate::setMutabilityGroupOfSubtree(QSGNode *node, quint8 group)
374
{
375
Q_ASSERT((group & 0xf) == group);
376
377
const
quint8 currentMutabilityGroup = mutabilityGroup(node);
378
if
(currentMutabilityGroup != group) {
379
if
(node->d_ptr.isNull())
380
node->d_ptr.reset(
new
QSGNodePrivate());
381
node->d_ptr->m_mutabilityGroup = group;
382
node->markDirty(QSGNode::DirtyGeometry);
383
}
384
385
for
(
int
i = 0; i < node->childCount(); ++i)
386
QSGNodePrivate::setMutabilityGroupOfSubtree(node->childAtIndex(i), group);
387
}
388
389
/*!
390
Prepends \a node to this node's the list of children.
391
392
Ordering of nodes is important as geometry nodes will be rendered in the
393
order they are added to the scene graph.
394
*/
395
396
void
QSGNode::prependChildNode(QSGNode *node)
397
{
398
//Q_ASSERT_X(!m_children.contains(node), "QSGNode::prependChildNode", "QSGNode is already a child!");
399
Q_ASSERT_X(!node->m_parent,
"QSGNode::prependChildNode"
,
"QSGNode already has a parent"
);
400
401
#
ifndef
QT_NO_DEBUG
402
if
(node->type() == QSGNode::GeometryNodeType) {
403
QSGGeometryNode *g =
static_cast
<QSGGeometryNode *>(node);
404
Q_ASSERT_X(g->material(),
"QSGNode::prependChildNode"
,
"QSGGeometryNode is missing material"
);
405
Q_ASSERT_X(g->geometry(),
"QSGNode::prependChildNode"
,
"QSGGeometryNode is missing geometry"
);
406
}
407
#
endif
408
409
if
(m_firstChild)
410
m_firstChild->m_previousSibling = node;
411
else
412
m_lastChild = node;
413
node->m_nextSibling = m_firstChild;
414
m_firstChild = node;
415
node->m_parent =
this
;
416
417
node->markDirty(DirtyNodeAdded);
418
}
419
420
/*!
421
Appends \a node to this node's list of children.
422
423
Ordering of nodes is important as geometry nodes will be rendered in the
424
order they are added to the scene graph.
425
*/
426
427
void
QSGNode::appendChildNode(QSGNode *node)
428
{
429
//Q_ASSERT_X(!m_children.contains(node), "QSGNode::appendChildNode", "QSGNode is already a child!");
430
Q_ASSERT_X(!node->m_parent,
"QSGNode::appendChildNode"
,
"QSGNode already has a parent"
);
431
432
#
ifndef
QT_NO_DEBUG
433
if
(node->type() == QSGNode::GeometryNodeType) {
434
QSGGeometryNode *g =
static_cast
<QSGGeometryNode *>(node);
435
Q_ASSERT_X(g->material(),
"QSGNode::appendChildNode"
,
"QSGGeometryNode is missing material"
);
436
Q_ASSERT_X(g->geometry(),
"QSGNode::appendChildNode"
,
"QSGGeometryNode is missing geometry"
);
437
}
438
#
endif
439
440
if
(m_lastChild)
441
m_lastChild->m_nextSibling = node;
442
else
443
m_firstChild = node;
444
node->m_previousSibling = m_lastChild;
445
m_lastChild = node;
446
node->m_parent =
this
;
447
448
node->markDirty(DirtyNodeAdded);
449
}
450
451
452
453
/*!
454
Inserts \a node to this node's list of children before the node specified with \a before.
455
456
Ordering of nodes is important as geometry nodes will be rendered in the
457
order they are added to the scene graph.
458
*/
459
460
void
QSGNode::insertChildNodeBefore(QSGNode *node, QSGNode *before)
461
{
462
//Q_ASSERT_X(!m_children.contains(node), "QSGNode::insertChildNodeBefore", "QSGNode is already a child!");
463
Q_ASSERT_X(!node->m_parent,
"QSGNode::insertChildNodeBefore"
,
"QSGNode already has a parent"
);
464
Q_ASSERT_X(before && before->m_parent ==
this
,
"QSGNode::insertChildNodeBefore"
,
"The parent of \'before\' is wrong"
);
465
466
#
ifndef
QT_NO_DEBUG
467
if
(node->type() == QSGNode::GeometryNodeType) {
468
QSGGeometryNode *g =
static_cast
<QSGGeometryNode *>(node);
469
Q_ASSERT_X(g->material(),
"QSGNode::insertChildNodeBefore"
,
"QSGGeometryNode is missing material"
);
470
Q_ASSERT_X(g->geometry(),
"QSGNode::insertChildNodeBefore"
,
"QSGGeometryNode is missing geometry"
);
471
}
472
#
endif
473
474
QSGNode *previous = before->m_previousSibling;
475
if
(previous)
476
previous->m_nextSibling = node;
477
else
478
m_firstChild = node;
479
node->m_previousSibling = previous;
480
node->m_nextSibling = before;
481
before->m_previousSibling = node;
482
node->m_parent =
this
;
483
484
node->markDirty(DirtyNodeAdded);
485
}
486
487
488
489
/*!
490
Inserts \a node to this node's list of children after the node specified with \a after.
491
492
Ordering of nodes is important as geometry nodes will be rendered in the
493
order they are added to the scene graph.
494
*/
495
496
void
QSGNode::insertChildNodeAfter(QSGNode *node, QSGNode *after)
497
{
498
//Q_ASSERT_X(!m_children.contains(node), "QSGNode::insertChildNodeAfter", "QSGNode is already a child!");
499
Q_ASSERT_X(!node->m_parent,
"QSGNode::insertChildNodeAfter"
,
"QSGNode already has a parent"
);
500
Q_ASSERT_X(after && after->m_parent ==
this
,
"QSGNode::insertChildNodeAfter"
,
"The parent of \'after\' is wrong"
);
501
502
#
ifndef
QT_NO_DEBUG
503
if
(node->type() == QSGNode::GeometryNodeType) {
504
QSGGeometryNode *g =
static_cast
<QSGGeometryNode *>(node);
505
Q_ASSERT_X(g->material(),
"QSGNode::insertChildNodeAfter"
,
"QSGGeometryNode is missing material"
);
506
Q_ASSERT_X(g->geometry(),
"QSGNode::insertChildNodeAfter"
,
"QSGGeometryNode is missing geometry"
);
507
}
508
#
endif
509
510
QSGNode *next = after->m_nextSibling;
511
if
(next)
512
next->m_previousSibling = node;
513
else
514
m_lastChild = node;
515
node->m_nextSibling = next;
516
node->m_previousSibling = after;
517
after->m_nextSibling = node;
518
node->m_parent =
this
;
519
520
node->markDirty(DirtyNodeAdded);
521
}
522
523
524
525
/*!
526
Removes \a node from this node's list of children.
527
*/
528
529
void
QSGNode::removeChildNode(QSGNode *node)
530
{
531
//Q_ASSERT(m_children.contains(node));
532
Q_ASSERT(node->parent() ==
this
);
533
534
QSGNode *previous = node->m_previousSibling;
535
QSGNode *next = node->m_nextSibling;
536
if
(previous)
537
previous->m_nextSibling = next;
538
else
539
m_firstChild = next;
540
if
(next)
541
next->m_previousSibling = previous;
542
else
543
m_lastChild = previous;
544
node->m_previousSibling =
nullptr
;
545
node->m_nextSibling =
nullptr
;
546
547
node->markDirty(DirtyNodeRemoved);
548
node->m_parent =
nullptr
;
549
}
550
551
552
/*!
553
Removes all child nodes from this node's list of children.
554
*/
555
556
void
QSGNode::removeAllChildNodes()
557
{
558
while
(m_firstChild) {
559
QSGNode *node = m_firstChild;
560
m_firstChild = node->m_nextSibling;
561
node->m_nextSibling =
nullptr
;
562
if
(m_firstChild)
563
m_firstChild->m_previousSibling =
nullptr
;
564
else
565
m_lastChild =
nullptr
;
566
node->markDirty(DirtyNodeRemoved);
567
node->m_parent =
nullptr
;
568
}
569
}
570
571
/*!
572
* \internal
573
*
574
* Reparents all nodes of this node to \a newParent.
575
*/
576
void
QSGNode::reparentChildNodesTo(QSGNode *newParent)
577
{
578
for
(QSGNode *c = firstChild(); c; c = firstChild()) {
579
removeChildNode(c);
580
newParent->appendChildNode(c);
581
}
582
}
583
584
585
int
QSGNode::childCount()
const
586
{
587
int
count = 0;
588
QSGNode *n = m_firstChild;
589
while
(n) {
590
++count;
591
n = n->m_nextSibling;
592
}
593
return
count;
594
}
595
596
597
QSGNode *QSGNode::childAtIndex(
int
i)
const
598
{
599
QSGNode *n = m_firstChild;
600
while
(i && n) {
601
--i;
602
n = n->m_nextSibling;
603
}
604
return
n;
605
}
606
607
608
/*!
609
Sets the flag \a f on this node if \a enabled is true;
610
otherwise clears the flag.
611
612
\sa flags()
613
*/
614
615
void
QSGNode::setFlag(Flag f,
bool
enabled)
616
{
617
if
(
bool
(m_nodeFlags & f) == enabled)
618
return
;
619
m_nodeFlags ^= f;
620
Q_ASSERT(
int
(UsePreprocess) ==
int
(DirtyUsePreprocess));
621
int
changedFlag = f & UsePreprocess;
622
if
(changedFlag)
623
markDirty(DirtyState(changedFlag));
624
}
625
626
627
/*!
628
Sets the flags \a f on this node if \a enabled is true;
629
otherwise clears the flags.
630
631
\sa flags()
632
*/
633
634
void
QSGNode::setFlags(Flags f,
bool
enabled)
635
{
636
Flags oldFlags = m_nodeFlags;
637
if
(enabled)
638
m_nodeFlags |= f;
639
else
640
m_nodeFlags &= ~f;
641
Q_ASSERT(
int
(UsePreprocess) ==
int
(DirtyUsePreprocess));
642
int
changedFlags = (oldFlags ^ m_nodeFlags) & UsePreprocess;
643
if
(changedFlags)
644
markDirty(DirtyState(changedFlags));
645
}
646
647
648
649
/*!
650
Notifies all connected renderers that the node has dirty \a bits.
651
*/
652
653
void
QSGNode::markDirty(DirtyState bits)
654
{
655
int
renderableCountDiff = 0;
656
if
(bits & DirtyNodeAdded)
657
renderableCountDiff += m_subtreeRenderableCount;
658
if
(bits & DirtyNodeRemoved)
659
renderableCountDiff -= m_subtreeRenderableCount;
660
661
QSGNode *p = m_parent;
662
while
(p) {
663
p->m_subtreeRenderableCount += renderableCountDiff;
664
if
(p->type() == RootNodeType)
665
static_cast
<QSGRootNode *>(p)->notifyNodeChange(
this
, bits);
666
p = p->m_parent;
667
}
668
}
669
670
void
qsgnode_set_description
(QSGNode *node,
const
QString &description)
671
{
672
#
ifdef
QSG_RUNTIME_DESCRIPTION
673
QSGNodePrivate::setDescription(node, description);
674
#
else
675
Q_UNUSED(node);
676
Q_UNUSED(description);
677
#
endif
678
}
679
680
/*!
681
\class QSGBasicGeometryNode
682
\brief The QSGBasicGeometryNode class serves as a baseclass for geometry based nodes.
683
684
\inmodule QtQuick
685
686
The QSGBasicGeometryNode class should not be used by itself. It is only encapsulates
687
shared functionality between the QSGGeometryNode and QSGClipNode classes.
688
689
\note All classes with QSG prefix should be used solely on the scene graph's
690
rendering thread. See \l {Scene Graph and Rendering} for more information.
691
*/
692
693
694
/*!
695
Creates a new basic geometry node of type \a type
696
697
\internal
698
*/
699
QSGBasicGeometryNode::QSGBasicGeometryNode(NodeType type)
700
: QSGNode(type)
701
, m_geometry(
nullptr
)
702
, m_matrix(
nullptr
)
703
, m_clip_list(
nullptr
)
704
{
705
}
706
707
708
/*!
709
\internal
710
*/
711
QSGBasicGeometryNode::QSGBasicGeometryNode(QSGBasicGeometryNodePrivate &dd, NodeType type)
712
: QSGNode(dd, type)
713
, m_geometry(
nullptr
)
714
, m_matrix(
nullptr
)
715
, m_clip_list(
nullptr
)
716
{
717
}
718
719
720
/*!
721
Deletes this QSGBasicGeometryNode.
722
723
If the node has the flag QSGNode::OwnsGeometry set, it will also delete the
724
geometry object it is pointing to. This flag is not set by default.
725
*/
726
727
QSGBasicGeometryNode::~QSGBasicGeometryNode()
728
{
729
if
(flags() & OwnsGeometry)
730
delete
m_geometry;
731
}
732
733
734
/*!
735
\fn QSGGeometry *QSGBasicGeometryNode::geometry()
736
737
Returns this node's geometry.
738
739
The geometry is null by default.
740
*/
741
742
/*!
743
\fn const QSGGeometry *QSGBasicGeometryNode::geometry() const
744
745
Returns this node's geometry.
746
747
The geometry is null by default.
748
*/
749
750
/*!
751
\fn QMatrix4x4 *QSGBasicGeometryNode::matrix() const
752
753
Will be set during rendering to contain transformation of the geometry
754
for that rendering pass.
755
756
\internal
757
*/
758
759
/*!
760
\fn QSGClipNode *QSGBasicGeometryNode::clipList() const
761
762
Will be set during rendering to contain the clip of the geometry
763
for that rendering pass.
764
765
\internal
766
*/
767
768
/*!
769
\fn void QSGBasicGeometryNode::setRendererMatrix(const QMatrix4x4 *m)
770
771
\internal
772
*/
773
774
/*!
775
\fn void QSGBasicGeometryNode::setRendererClipList(const QSGClipNode *c)
776
777
\internal
778
*/
779
780
781
/*!
782
Sets the geometry of this node to \a geometry.
783
784
If the node has the flag QSGNode::OwnsGeometry set, it will also delete the
785
geometry object it is pointing to. This flag is not set by default.
786
787
If the geometry is changed without calling setGeometry() again, the user
788
must also mark the geometry as dirty using QSGNode::markDirty().
789
790
\sa markDirty()
791
*/
792
793
void
QSGBasicGeometryNode::setGeometry(QSGGeometry *geometry)
794
{
795
if
((flags() & OwnsGeometry) != 0 && m_geometry != geometry)
796
delete
m_geometry;
797
m_geometry = geometry;
798
markDirty(DirtyGeometry);
799
}
800
801
802
803
/*!
804
\class QSGGeometryNode
805
\brief The QSGGeometryNode class is used for all rendered content in the scene graph.
806
807
\inmodule QtQuick
808
\ingroup qtquick-scenegraph-nodes
809
810
The QSGGeometryNode consists of geometry and material. The geometry defines the mesh,
811
the vertices and their structure, to be drawn. The Material defines how the shape is
812
filled.
813
814
The following is a code snippet illustrating how to create a red
815
line using a QSGGeometryNode:
816
\code
817
QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 2);
818
geometry->setDrawingMode(QSGGeometry::DrawLines);
819
geometry->setLineWidth(3);
820
geometry->vertexDataAsPoint2D()[0].set(0, 0);
821
geometry->vertexDataAsPoint2D()[1].set(width(), height());
822
823
QSGFlatColorMaterial *material = new QSGFlatColorMaterial;
824
material->setColor(QColor(255, 0, 0));
825
826
QSGGeometryNode *node = new QSGGeometryNode;
827
node->setGeometry(geometry);
828
node->setFlag(QSGNode::OwnsGeometry);
829
node->setMaterial(material);
830
node->setFlag(QSGNode::OwnsMaterial);
831
\endcode
832
833
A geometry node must have both geometry and a normal material before it is added to
834
the scene graph. When the geometry and materials are changed after the node has
835
been added to the scene graph, the user should also mark them as dirty using
836
QSGNode::markDirty().
837
838
The geometry node supports two types of materials, the opaqueMaterial and the normal
839
material. The opaqueMaterial is used when the accumulated scene graph opacity at the
840
time of rendering is 1. The primary use case is to special case opaque rendering
841
to avoid an extra operation in the fragment shader can have significant performance
842
impact on embedded graphics chips. The opaque material is optional.
843
844
\note All classes with QSG prefix should be used solely on the scene graph's
845
rendering thread. See \l {Scene Graph and Rendering} for more information.
846
847
\sa QSGGeometry, QSGMaterial
848
*/
849
850
851
/*!
852
Creates a new geometry node without geometry and material.
853
*/
854
855
QSGGeometryNode::QSGGeometryNode()
856
: QSGBasicGeometryNode(GeometryNodeType)
857
{
858
}
859
860
861
/*!
862
\internal
863
*/
864
QSGGeometryNode::QSGGeometryNode(QSGGeometryNodePrivate &dd)
865
: QSGBasicGeometryNode(dd, GeometryNodeType)
866
, m_render_order(0)
867
, m_material(
nullptr
)
868
, m_opaque_material(
nullptr
)
869
, m_opacity(1)
870
{
871
}
872
873
874
/*!
875
Deletes this geometry node.
876
877
The flags QSGNode::OwnsMaterial, QSGNode::OwnsOpaqueMaterial and
878
QSGNode::OwnsGeometry decides whether the geometry node should also
879
delete the materials and geometry. By default, these flags are disabled.
880
*/
881
882
QSGGeometryNode::~QSGGeometryNode()
883
{
884
if
(flags() & OwnsMaterial)
885
delete
m_material;
886
if
(flags() & OwnsOpaqueMaterial)
887
delete
m_opaque_material;
888
}
889
890
891
892
/*!
893
\fn int QSGGeometryNode::renderOrder() const
894
895
Returns the render order of this geometry node.
896
897
\internal
898
*/
899
900
/*!
901
\fn QSGMaterial *QSGGeometryNode::material() const
902
903
Returns the material of the QSGGeometryNode.
904
905
\sa setMaterial()
906
*/
907
908
/*!
909
\fn QSGMaterial *QSGGeometryNode::opaqueMaterial() const
910
911
Returns the opaque material of the QSGGeometryNode.
912
913
\sa setOpaqueMaterial()
914
*/
915
916
/*!
917
\fn qreal QSGGeometryNode::inheritedOpacity() const
918
919
Set during rendering to specify the inherited opacity for that
920
rendering pass.
921
922
\internal
923
*/
924
925
926
/*!
927
Sets the render order of this node to be \a order.
928
929
Geometry nodes are rendered in an order that visually looks like
930
low order nodes are rendered prior to high order nodes. For opaque
931
geometry there is little difference as z-testing will handle
932
the discard, but for translucent objects, the rendering should
933
normally be specified in the order of back-to-front.
934
935
The default render order is \c 0.
936
937
\internal
938
*/
939
void
QSGGeometryNode::setRenderOrder(
int
order)
940
{
941
m_render_order = order;
942
}
943
944
945
946
/*!
947
Sets the material of this geometry node to \a material.
948
949
Geometry nodes must have a material before they can be added to the
950
scene graph.
951
952
If the material is changed without calling setMaterial() again, the user
953
must also mark the material as dirty using QSGNode::markDirty().
954
955
*/
956
void
QSGGeometryNode::setMaterial(QSGMaterial *material)
957
{
958
if
((flags() & OwnsMaterial) != 0 && m_material != material)
959
delete
m_material;
960
m_material = material;
961
#
ifndef
QT_NO_DEBUG
962
if
(m_material !=
nullptr
&& m_opaque_material == m_material)
963
qWarning(
"QSGGeometryNode: using same material for both opaque and translucent"
);
964
#
endif
965
markDirty(DirtyMaterial);
966
}
967
968
969
970
/*!
971
Sets the opaque material of this geometry to \a material.
972
973
The opaque material will be preferred by the renderer over the
974
default material, as returned by the material() function, if
975
it is not null and the geometry item has an inherited opacity of
976
1.
977
978
The opaqueness refers to scene graph opacity, the material is still
979
allowed to set QSGMaterial::Blending to true and draw transparent
980
pixels.
981
982
If the material is changed without calling setOpaqueMaterial()
983
again, the user must also mark the opaque material as dirty using
984
QSGNode::markDirty().
985
986
*/
987
void
QSGGeometryNode::setOpaqueMaterial(QSGMaterial *material)
988
{
989
if
((flags() & OwnsOpaqueMaterial) != 0 && m_opaque_material != m_material)
990
delete
m_opaque_material;
991
m_opaque_material = material;
992
#
ifndef
QT_NO_DEBUG
993
if
(m_opaque_material !=
nullptr
&& m_opaque_material == m_material)
994
qWarning(
"QSGGeometryNode: using same material for both opaque and translucent"
);
995
#
endif
996
997
markDirty(DirtyMaterial);
998
}
999
1000
1001
1002
/*!
1003
Returns the material which should currently be used for geometry node.
1004
1005
If the inherited opacity of the node is 1 and there is an opaque material
1006
set on this node, it will be returned; otherwise, the default material
1007
will be returned.
1008
1009
\warning This function requires the scene graph above this item to be
1010
completely free of dirty states, so it can only be called during rendering
1011
1012
\internal
1013
1014
\sa setMaterial, setOpaqueMaterial
1015
*/
1016
QSGMaterial *QSGGeometryNode::activeMaterial()
const
1017
{
1018
if
(m_opaque_material && m_opacity > 0.999)
1019
return
m_opaque_material;
1020
return
m_material;
1021
}
1022
1023
1024
/*!
1025
Sets the inherited opacity of this geometry to \a opacity.
1026
1027
This function is meant to be called by the node preprocessing
1028
prior to rendering the tree, so it will not mark the tree as
1029
dirty.
1030
1031
\internal
1032
*/
1033
void
QSGGeometryNode::setInheritedOpacity(qreal opacity)
1034
{
1035
Q_ASSERT(opacity >= 0 && opacity <= 1);
1036
m_opacity = opacity;
1037
}
1038
1039
1040
/*!
1041
\class QSGClipNode
1042
\brief The QSGClipNode class implements the clipping functionality in the scene graph.
1043
1044
\inmodule QtQuick
1045
\ingroup qtquick-scenegraph-nodes
1046
1047
Clipping applies to the node's subtree and can be nested. Multiple clip nodes will be
1048
accumulated by intersecting all their geometries. The accumulation happens
1049
as part of the rendering.
1050
1051
Clip nodes must have a geometry before they can be added to the scene graph.
1052
1053
Clipping is usually implemented by using the stencil buffer.
1054
1055
\note All classes with QSG prefix should be used solely on the scene graph's
1056
rendering thread. See \l {Scene Graph and Rendering} for more information.
1057
*/
1058
1059
1060
1061
/*!
1062
Creates a new QSGClipNode without a geometry.
1063
1064
The clip node must have a geometry before it can be added to the
1065
scene graph.
1066
*/
1067
1068
QSGClipNode::QSGClipNode()
1069
: QSGBasicGeometryNode(ClipNodeType)
1070
, m_is_rectangular(
false
)
1071
{
1072
Q_UNUSED(m_reserved);
1073
}
1074
1075
1076
1077
/*!
1078
Deletes this QSGClipNode.
1079
1080
If the flag QSGNode::OwnsGeometry is set, the geometry will also be
1081
deleted.
1082
*/
1083
1084
QSGClipNode::~QSGClipNode()
1085
{
1086
}
1087
1088
1089
1090
/*!
1091
\fn bool QSGClipNode::isRectangular() const
1092
1093
Returns if this clip node has a rectangular clip.
1094
*/
1095
1096
1097
1098
/*!
1099
Sets whether this clip node has a rectangular clip to \a rectHint.
1100
1101
This is an optimization hint which means that the renderer can
1102
use scissoring instead of stencil, which is significantly faster.
1103
1104
When this hint is set and it is applicable, the clip region will be
1105
generated from clipRect() rather than geometry().
1106
1107
By default this property is \c false.
1108
*/
1109
1110
void
QSGClipNode::setIsRectangular(
bool
rectHint)
1111
{
1112
m_is_rectangular = rectHint;
1113
}
1114
1115
1116
1117
/*!
1118
\fn QRectF QSGClipNode::clipRect() const
1119
1120
Returns the clip rect of this node.
1121
*/
1122
1123
1124
/*!
1125
Sets the clip rect of this clip node to \a rect.
1126
1127
When a rectangular clip is set in combination with setIsRectangular
1128
the renderer may in some cases use a more optimal clip method.
1129
*/
1130
void
QSGClipNode::setClipRect(
const
QRectF &rect)
1131
{
1132
m_clip_rect = rect;
1133
}
1134
1135
1136
/*!
1137
\class QSGTransformNode
1138
\brief The QSGTransformNode class implements transformations in the scene graph.
1139
1140
\inmodule QtQuick
1141
\ingroup qtquick-scenegraph-nodes
1142
1143
Transformations apply the node's subtree and can be nested. Multiple transform nodes
1144
will be accumulated by intersecting all their matrices. The accumulation happens
1145
as part of the rendering.
1146
1147
The transform nodes implement a 4x4 matrix which in theory supports full 3D
1148
transformations. However, because the renderer optimizes for 2D use-cases rather
1149
than 3D use-cases, rendering a scene with full 3D transformations needs to
1150
be done with some care.
1151
1152
\note All classes with QSG prefix should be used solely on the scene graph's
1153
rendering thread. See \l {Scene Graph and Rendering} for more information.
1154
1155
*/
1156
1157
1158
/*!
1159
Create a new QSGTransformNode with its matrix set to the identity matrix.
1160
*/
1161
1162
QSGTransformNode::QSGTransformNode()
1163
: QSGNode(TransformNodeType)
1164
{
1165
}
1166
1167
1168
1169
/*!
1170
Deletes this transform node.
1171
*/
1172
1173
QSGTransformNode::~QSGTransformNode()
1174
{
1175
}
1176
1177
1178
1179
/*!
1180
\fn QMatrix4x4 QSGTransformNode::matrix() const
1181
1182
Returns this transform node's matrix.
1183
*/
1184
1185
1186
1187
/*!
1188
Sets this transform node's matrix to \a matrix.
1189
*/
1190
1191
void
QSGTransformNode::setMatrix(
const
QMatrix4x4 &matrix)
1192
{
1193
m_matrix = matrix;
1194
markDirty(DirtyMatrix);
1195
}
1196
1197
/*!
1198
\fn const QMatrix4x4 &QSGTransformNode::combinedMatrix() const
1199
1200
Set during rendering to the combination of all parent matrices for
1201
that rendering pass.
1202
1203
\internal
1204
*/
1205
1206
1207
1208
/*!
1209
Sets the combined matrix of this matrix to \a transform.
1210
1211
This function is meant to be called by the node preprocessing
1212
prior to rendering the tree, so it will not mark the tree as
1213
dirty.
1214
1215
\internal
1216
*/
1217
void
QSGTransformNode::setCombinedMatrix(
const
QMatrix4x4 &matrix)
1218
{
1219
m_combined_matrix = matrix;
1220
}
1221
1222
1223
1224
/*!
1225
\class QSGRootNode
1226
\brief The QSGRootNode is the toplevel root of any scene graph.
1227
1228
The root node is used to attach a scene graph to a renderer.
1229
1230
\internal
1231
*/
1232
1233
1234
1235
/*!
1236
\fn QSGRootNode::QSGRootNode()
1237
1238
Creates a new root node.
1239
*/
1240
1241
QSGRootNode::QSGRootNode()
1242
: QSGNode(RootNodeType)
1243
{
1244
}
1245
1246
1247
/*!
1248
Deletes the root node.
1249
1250
When a root node is deleted it removes itself from all of renderers
1251
that are referencing it.
1252
*/
1253
1254
QSGRootNode::~QSGRootNode()
1255
{
1256
while
(!m_renderers.isEmpty())
1257
m_renderers.constLast()->setRootNode(
nullptr
);
1258
destroy();
// Must call destroy() here because markDirty() casts this to QSGRootNode.
1259
}
1260
1261
1262
1263
/*!
1264
Called to notify all renderers that \a node has been marked as dirty
1265
with \a flags.
1266
*/
1267
1268
void
QSGRootNode::notifyNodeChange(QSGNode *node, DirtyState state)
1269
{
1270
for
(
int
i=0; i<m_renderers.size(); ++i) {
1271
m_renderers.at(i)->nodeChanged(node, state);
1272
}
1273
}
1274
1275
1276
1277
/*!
1278
\class QSGOpacityNode
1279
\brief The QSGOpacityNode class is used to change opacity of nodes.
1280
1281
\inmodule QtQuick
1282
\ingroup qtquick-scenegraph-nodes
1283
1284
Opacity applies to its subtree and can be nested. Multiple opacity nodes
1285
will be accumulated by multiplying their opacity. The accumulation happens
1286
as part of the rendering.
1287
1288
When nested opacity gets below a certain threshold, the subtree might
1289
be marked as blocked, causing isSubtreeBlocked() to return true. This
1290
is done for performance reasons.
1291
1292
\note All classes with QSG prefix should be used solely on the scene graph's
1293
rendering thread. See \l {Scene Graph and Rendering} for more information.
1294
*/
1295
1296
1297
1298
/*!
1299
Constructs an opacity node with a default opacity of 1.
1300
1301
Opacity accumulates downwards in the scene graph so a node with two
1302
QSGOpacityNode instances above it, both with opacity of 0.5, will have
1303
effective opacity of 0.25.
1304
1305
The default opacity of nodes is 1.
1306
*/
1307
QSGOpacityNode::QSGOpacityNode()
1308
: QSGNode(OpacityNodeType)
1309
{
1310
}
1311
1312
1313
1314
/*!
1315
Deletes the opacity node.
1316
*/
1317
1318
QSGOpacityNode::~QSGOpacityNode()
1319
{
1320
}
1321
1322
1323
1324
/*!
1325
\fn qreal QSGOpacityNode::opacity() const
1326
1327
Returns this opacity node's opacity.
1328
*/
1329
1330
const
qreal
OPACITY_THRESHOLD
= 0.001;
1331
1332
/*!
1333
Sets the opacity of this node to \a opacity.
1334
1335
Before rendering the graph, the renderer will do an update pass
1336
over the subtree to propagate the opacity to its children.
1337
1338
The value will be bounded to the range 0 to 1.
1339
*/
1340
1341
void
QSGOpacityNode::setOpacity(qreal opacity)
1342
{
1343
opacity = std::clamp(opacity, qreal(0.0), qreal(1.0));
1344
if
(m_opacity == opacity)
1345
return
;
1346
DirtyState dirtyState = DirtyOpacity;
1347
1348
if
((m_opacity < OPACITY_THRESHOLD && opacity >= OPACITY_THRESHOLD)
// blocked to unblocked
1349
|| (m_opacity >= OPACITY_THRESHOLD && opacity < OPACITY_THRESHOLD))
// unblocked to blocked
1350
dirtyState |= DirtySubtreeBlocked;
1351
1352
m_opacity = opacity;
1353
markDirty(dirtyState);
1354
}
1355
1356
1357
1358
/*!
1359
\fn qreal QSGOpacityNode::combinedOpacity() const
1360
1361
Returns this node's accumulated opacity.
1362
1363
This value is calculated during rendering and only stored
1364
in the opacity node temporarily.
1365
1366
\internal
1367
*/
1368
1369
1370
1371
/*!
1372
Sets the combined opacity of this node to \a opacity.
1373
1374
This function is meant to be called by the node preprocessing
1375
prior to rendering the tree, so it will not mark the tree as
1376
dirty.
1377
1378
\internal
1379
*/
1380
1381
void
QSGOpacityNode::setCombinedOpacity(qreal opacity)
1382
{
1383
m_combined_opacity = opacity;
1384
}
1385
1386
1387
1388
/*!
1389
For performance reasons, we block the subtree when the opacity
1390
is below a certain threshold.
1391
1392
\internal
1393
*/
1394
1395
bool
QSGOpacityNode::isSubtreeBlocked()
const
1396
{
1397
// IsNodeBlocked is deliberately not checked: it is only ever set on the
1398
// transform nodes of items.
1399
return
m_opacity < OPACITY_THRESHOLD;
1400
}
1401
1402
1403
/*!
1404
\class QSGNodeVisitor
1405
\brief The QSGNodeVisitor class is a helper class for traversing the scene graph.
1406
1407
\internal
1408
*/
1409
1410
QSGNodeVisitor::~QSGNodeVisitor()
1411
{
1412
1413
}
1414
1415
1416
void
QSGNodeVisitor::visitNode(QSGNode *n)
1417
{
1418
switch
(n->type()) {
1419
case
QSGNode::TransformNodeType: {
1420
QSGTransformNode *t =
static_cast
<QSGTransformNode *>(n);
1421
enterTransformNode(t);
1422
visitChildren(t);
1423
leaveTransformNode(t);
1424
break
; }
1425
case
QSGNode::GeometryNodeType: {
1426
QSGGeometryNode *g =
static_cast
<QSGGeometryNode *>(n);
1427
enterGeometryNode(g);
1428
visitChildren(g);
1429
leaveGeometryNode(g);
1430
break
; }
1431
case
QSGNode::ClipNodeType: {
1432
QSGClipNode *c =
static_cast
<QSGClipNode *>(n);
1433
enterClipNode(c);
1434
visitChildren(c);
1435
leaveClipNode(c);
1436
break
; }
1437
case
QSGNode::OpacityNodeType: {
1438
QSGOpacityNode *o =
static_cast
<QSGOpacityNode *>(n);
1439
enterOpacityNode(o);
1440
visitChildren(o);
1441
leaveOpacityNode(o);
1442
break
; }
1443
default
:
1444
visitChildren(n);
1445
break
;
1446
}
1447
}
1448
1449
void
QSGNodeVisitor::visitChildren(QSGNode *n)
1450
{
1451
for
(QSGNode *c = n->firstChild(); c; c = c->nextSibling())
1452
visitNode(c);
1453
}
1454
1455
#
ifndef
QT_NO_DEBUG_STREAM
1456
QDebug
operator
<<(QDebug d,
const
QSGGeometryNode *n)
1457
{
1458
if
(!n) {
1459
d <<
"Geometry(null)"
;
1460
return
d;
1461
}
1462
d <<
"GeometryNode("
<< Qt::hex << (
const
void
*) n << Qt::dec;
1463
1464
const
QSGGeometry *g = n->geometry();
1465
1466
if
(!g) {
1467
d <<
"no geometry"
;
1468
}
else
{
1469
1470
switch
(g->drawingMode()) {
1471
case
QSGGeometry::DrawTriangleStrip: d <<
"strip"
;
break
;
1472
case
QSGGeometry::DrawTriangleFan: d <<
"fan"
;
break
;
1473
case
QSGGeometry::DrawTriangles: d <<
"triangles"
;
break
;
1474
default
:
break
;
1475
}
1476
1477
d <<
"#V:"
<< g->vertexCount() <<
"#I:"
<< g->indexCount();
1478
1479
if
(g->attributeCount() > 0 && g->attributes()->type == QSGGeometry::FloatType) {
1480
float
x1 = 1e10, x2 = -1e10, y1=1e10, y2=-1e10;
1481
int
stride = g->sizeOfVertex();
1482
for
(
int
i = 0; i < g->vertexCount(); ++i) {
1483
float
x = ((
float
*)((
char
*)
const_cast
<QSGGeometry *>(g)->vertexData() + i * stride))[0];
1484
float
y = ((
float
*)((
char
*)
const_cast
<QSGGeometry *>(g)->vertexData() + i * stride))[1];
1485
1486
x1 = qMin(x1, x);
1487
x2 = qMax(x2, x);
1488
y1 = qMin(y1, y);
1489
y2 = qMax(y2, y);
1490
}
1491
1492
d <<
"x1="
<< x1 <<
"y1="
<< y1 <<
"x2="
<< x2 <<
"y2="
<< y2;
1493
}
1494
}
1495
1496
if
(n->material())
1497
d <<
"materialtype="
<< n->material()->type();
1498
1499
1500
d <<
')'
;
1501
#
ifdef
QSG_RUNTIME_DESCRIPTION
1502
d << QSGNodePrivate::description(n);
1503
#
endif
1504
return
d;
1505
}
1506
1507
QDebug
operator
<<(QDebug d,
const
QSGClipNode *n)
1508
{
1509
if
(!n) {
1510
d <<
"ClipNode(null)"
;
1511
return
d;
1512
}
1513
d <<
"ClipNode("
<< Qt::hex << (
const
void
*) n << Qt::dec;
1514
1515
if
(n->childCount())
1516
d <<
"children="
<< n->childCount();
1517
1518
d <<
"is rect?"
<< (n->isRectangular() ?
"yes"
:
"no"
);
1519
1520
d <<
')'
;
1521
#
ifdef
QSG_RUNTIME_DESCRIPTION
1522
d << QSGNodePrivate::description(n);
1523
#
endif
1524
d << (n->isSubtreeBlocked() ?
"*BLOCKED*"
:
""
);
1525
return
d;
1526
}
1527
1528
QDebug
operator
<<(QDebug d,
const
QSGTransformNode *n)
1529
{
1530
if
(!n) {
1531
d <<
"TransformNode(null)"
;
1532
return
d;
1533
}
1534
const
QMatrix4x4 m = n->matrix();
1535
d <<
"TransformNode("
;
1536
d << Qt::hex << (
const
void
*) n << Qt::dec;
1537
if
(m.isIdentity())
1538
d <<
"identity"
;
1539
else
if
(m.determinant() == 1 && m(0, 0) == 1 && m(1, 1) == 1 && m(2, 2) == 1)
1540
d <<
"translate"
<< m(0, 3) << m(1, 3) << m(2, 3);
1541
else
1542
d <<
"det="
<< n->matrix().determinant();
1543
#
ifdef
QSG_RUNTIME_DESCRIPTION
1544
d << QSGNodePrivate::description(n);
1545
#
endif
1546
d << (n->isSubtreeBlocked() ?
"*BLOCKED*"
:
""
);
1547
d <<
')'
;
1548
return
d;
1549
}
1550
1551
QDebug
operator
<<(QDebug d,
const
QSGOpacityNode *n)
1552
{
1553
if
(!n) {
1554
d <<
"OpacityNode(null)"
;
1555
return
d;
1556
}
1557
d <<
"OpacityNode("
;
1558
d << Qt::hex << (
const
void
*) n << Qt::dec;
1559
d <<
"opacity="
<< n->opacity()
1560
<<
"combined="
<< n->combinedOpacity()
1561
<< (n->isSubtreeBlocked() ?
"*BLOCKED*"
:
""
);
1562
#
ifdef
QSG_RUNTIME_DESCRIPTION
1563
d << QSGNodePrivate::description(n);
1564
#
endif
1565
d <<
')'
;
1566
return
d;
1567
}
1568
1569
1570
QDebug
operator
<<(QDebug d,
const
QSGRootNode *n)
1571
{
1572
if
(!n) {
1573
d <<
"RootNode(null)"
;
1574
return
d;
1575
}
1576
QDebugStateSaver saver(d);
1577
d <<
"RootNode"
<< Qt::hex << (
const
void
*) n << (n->isSubtreeBlocked() ?
"*BLOCKED*"
:
""
);
1578
#
ifdef
QSG_RUNTIME_DESCRIPTION
1579
d << QSGNodePrivate::description(n);
1580
#
endif
1581
d <<
')'
;
1582
return
d;
1583
}
1584
1585
1586
1587
QDebug
operator
<<(QDebug d,
const
QSGNode *n)
1588
{
1589
if
(!n) {
1590
d <<
"Node(null)"
;
1591
return
d;
1592
}
1593
switch
(n->type()) {
1594
case
QSGNode::GeometryNodeType:
1595
d <<
static_cast
<
const
QSGGeometryNode *>(n);
1596
break
;
1597
case
QSGNode::TransformNodeType:
1598
d <<
static_cast
<
const
QSGTransformNode *>(n);
1599
break
;
1600
case
QSGNode::ClipNodeType:
1601
d <<
static_cast
<
const
QSGClipNode *>(n);
1602
break
;
1603
case
QSGNode::RootNodeType:
1604
d <<
static_cast
<
const
QSGRootNode *>(n);
1605
break
;
1606
case
QSGNode::OpacityNodeType:
1607
d <<
static_cast
<
const
QSGOpacityNode *>(n);
1608
break
;
1609
case
QSGNode::RenderNodeType:
1610
d <<
"RenderNode("
<< Qt::hex << (
const
void
*) n << Qt::dec
1611
<<
"flags="
<< (
int
) n->flags() << Qt::dec
1612
<< (n->isSubtreeBlocked() ?
"*BLOCKED*"
:
""
);
1613
#
ifdef
QSG_RUNTIME_DESCRIPTION
1614
d << QSGNodePrivate::description(n);
1615
#
endif
1616
d <<
')'
;
1617
break
;
1618
default
:
1619
d <<
"Node("
<< Qt::hex << (
const
void
*) n << Qt::dec
1620
<<
"flags="
<< (
int
) n->flags() << Qt::dec
1621
<< (n->isSubtreeBlocked() ?
"*BLOCKED*"
:
""
);
1622
#
ifdef
QSG_RUNTIME_DESCRIPTION
1623
d << QSGNodePrivate::description(n);
1624
#
endif
1625
d <<
')'
;
1626
break
;
1627
}
1628
return
d;
1629
}
1630
1631
#
endif
1632
1633
QT_END_NAMESPACE
operator<<
QDebug operator<<(QDebug d, const QSGRootNode *n)
Definition
qsgnode.cpp:1570
operator<<
QDebug operator<<(QDebug d, const QSGClipNode *n)
Definition
qsgnode.cpp:1507
operator<<
QDebug operator<<(QDebug d, const QSGNode *n)
Definition
qsgnode.cpp:1587
operator<<
QDebug operator<<(QDebug d, const QSGTransformNode *n)
Definition
qsgnode.cpp:1528
qsgnode_set_description
void qsgnode_set_description(QSGNode *node, const QString &description)
Definition
qsgnode.cpp:670
operator<<
QDebug operator<<(QDebug d, const QSGOpacityNode *n)
Definition
qsgnode.cpp:1551
qt_print_node_count
static void qt_print_node_count()
Definition
qsgnode.cpp:20
qt_node_count
static QT_BEGIN_NAMESPACE int qt_node_count
Definition
qsgnode.cpp:18
operator<<
QDebug operator<<(QDebug d, const QSGGeometryNode *n)
Definition
qsgnode.cpp:1456
OPACITY_THRESHOLD
const qreal OPACITY_THRESHOLD
Definition
qsgnode.cpp:1330
QSG_RUNTIME_DESCRIPTION
#define QSG_RUNTIME_DESCRIPTION
Definition
qsgnode.h:17
qtdeclarative
src
quick
scenegraph
coreapi
qsgnode.cpp
Generated on
for Qt by
1.18.0