21 qCDebug(lcQsgLeak,
"Number of leaked nodes: %i", qt_node_count);
27
28
29
30
31
32
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
129
130
131
132
133
134
135
138
139
140
141
144
145
146
147
150
151
152
153
154
155
158
159
160
161
162
163
166
167
168
169
172
173
174
175
176
177
180
181
182
183
184
185
188
189
190
191
192
193
196
197
198
199
202
203
204
205
209
210
212 : m_nodeFlags(OwnedByParent)
218
219
220
221
222QSGNode::QSGNode(NodeType type)
225 , m_firstChild(
nullptr)
226 , m_lastChild(
nullptr)
227 , m_nextSibling(
nullptr)
228 , m_previousSibling(
nullptr)
229 , m_subtreeRenderableCount(type == GeometryNodeType || type == RenderNodeType ? 1 : 0)
230 , m_nodeFlags(OwnedByParent)
236
237
238
239
240QSGNode::QSGNode(QSGNodePrivate &dd, NodeType type)
243 , m_firstChild(
nullptr)
244 , m_lastChild(
nullptr)
245 , m_nextSibling(
nullptr)
246 , m_previousSibling(
nullptr)
247 , m_subtreeRenderableCount(type == GeometryNodeType || type == RenderNodeType ? 1 : 0)
248 , m_nodeFlags(OwnedByParent)
255
256
260 if (lcQsgLeak().isDebugEnabled()) {
262 static bool atexit_registered =
false;
263 if (!atexit_registered) {
264 atexit(qt_print_node_count);
265 atexit_registered =
true;
272 d_ptr.reset(
new QSGNodePrivate());
277
278
279
280
281
285 if (lcQsgLeak().isDebugEnabled()) {
287 if (qt_node_count < 0)
288 qCDebug(lcQsgLeak,
"Node destroyed after qt_print_node_count() was called.");
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
316
317
318
319
320
321
322
323
325bool QSGNode::isSubtreeBlocked()
const
331
332
333
334
335
336
337
338
339
340
342void QSGNode::destroy()
345 m_parent->removeChildNode(
this);
346 Q_ASSERT(m_parent ==
nullptr);
348 while (m_firstChild) {
349 QSGNode *child = m_firstChild;
350 removeChildNode(child);
351 Q_ASSERT(child->m_parent ==
nullptr);
352 if (child->flags() & OwnedByParent)
356 Q_ASSERT(m_firstChild ==
nullptr && m_lastChild ==
nullptr);
361
362
363
364
365
367void QSGNode::prependChildNode(QSGNode *node)
370 Q_ASSERT_X(!node->m_parent,
"QSGNode::prependChildNode",
"QSGNode already has a parent");
373 if (node->type() == QSGNode::GeometryNodeType) {
374 QSGGeometryNode *g =
static_cast<QSGGeometryNode *>(node);
375 Q_ASSERT_X(g->material(),
"QSGNode::prependChildNode",
"QSGGeometryNode is missing material");
376 Q_ASSERT_X(g->geometry(),
"QSGNode::prependChildNode",
"QSGGeometryNode is missing geometry");
381 m_firstChild->m_previousSibling = node;
384 node->m_nextSibling = m_firstChild;
386 node->m_parent =
this;
388 node->markDirty(DirtyNodeAdded);
392
393
394
395
396
398void QSGNode::appendChildNode(QSGNode *node)
401 Q_ASSERT_X(!node->m_parent,
"QSGNode::appendChildNode",
"QSGNode already has a parent");
404 if (node->type() == QSGNode::GeometryNodeType) {
405 QSGGeometryNode *g =
static_cast<QSGGeometryNode *>(node);
406 Q_ASSERT_X(g->material(),
"QSGNode::appendChildNode",
"QSGGeometryNode is missing material");
407 Q_ASSERT_X(g->geometry(),
"QSGNode::appendChildNode",
"QSGGeometryNode is missing geometry");
412 m_lastChild->m_nextSibling = node;
415 node->m_previousSibling = m_lastChild;
417 node->m_parent =
this;
419 node->markDirty(DirtyNodeAdded);
425
426
427
428
429
431void QSGNode::insertChildNodeBefore(QSGNode *node, QSGNode *before)
434 Q_ASSERT_X(!node->m_parent,
"QSGNode::insertChildNodeBefore",
"QSGNode already has a parent");
435 Q_ASSERT_X(before && before->m_parent ==
this,
"QSGNode::insertChildNodeBefore",
"The parent of \'before\' is wrong");
438 if (node->type() == QSGNode::GeometryNodeType) {
439 QSGGeometryNode *g =
static_cast<QSGGeometryNode *>(node);
440 Q_ASSERT_X(g->material(),
"QSGNode::insertChildNodeBefore",
"QSGGeometryNode is missing material");
441 Q_ASSERT_X(g->geometry(),
"QSGNode::insertChildNodeBefore",
"QSGGeometryNode is missing geometry");
445 QSGNode *previous = before->m_previousSibling;
447 previous->m_nextSibling = node;
450 node->m_previousSibling = previous;
451 node->m_nextSibling = before;
452 before->m_previousSibling = node;
453 node->m_parent =
this;
455 node->markDirty(DirtyNodeAdded);
461
462
463
464
465
467void QSGNode::insertChildNodeAfter(QSGNode *node, QSGNode *after)
470 Q_ASSERT_X(!node->m_parent,
"QSGNode::insertChildNodeAfter",
"QSGNode already has a parent");
471 Q_ASSERT_X(after && after->m_parent ==
this,
"QSGNode::insertChildNodeAfter",
"The parent of \'after\' is wrong");
474 if (node->type() == QSGNode::GeometryNodeType) {
475 QSGGeometryNode *g =
static_cast<QSGGeometryNode *>(node);
476 Q_ASSERT_X(g->material(),
"QSGNode::insertChildNodeAfter",
"QSGGeometryNode is missing material");
477 Q_ASSERT_X(g->geometry(),
"QSGNode::insertChildNodeAfter",
"QSGGeometryNode is missing geometry");
481 QSGNode *next = after->m_nextSibling;
483 next->m_previousSibling = node;
486 node->m_nextSibling = next;
487 node->m_previousSibling = after;
488 after->m_nextSibling = node;
489 node->m_parent =
this;
491 node->markDirty(DirtyNodeAdded);
497
498
500void QSGNode::removeChildNode(QSGNode *node)
503 Q_ASSERT(node->parent() ==
this);
505 QSGNode *previous = node->m_previousSibling;
506 QSGNode *next = node->m_nextSibling;
508 previous->m_nextSibling = next;
512 next->m_previousSibling = previous;
514 m_lastChild = previous;
515 node->m_previousSibling =
nullptr;
516 node->m_nextSibling =
nullptr;
518 node->markDirty(DirtyNodeRemoved);
519 node->m_parent =
nullptr;
524
525
527void QSGNode::removeAllChildNodes()
529 while (m_firstChild) {
530 QSGNode *node = m_firstChild;
531 m_firstChild = node->m_nextSibling;
532 node->m_nextSibling =
nullptr;
534 m_firstChild->m_previousSibling =
nullptr;
536 m_lastChild =
nullptr;
537 node->markDirty(DirtyNodeRemoved);
538 node->m_parent =
nullptr;
543
544
545
546
547void QSGNode::reparentChildNodesTo(QSGNode *newParent)
549 for (QSGNode *c = firstChild(); c; c = firstChild()) {
551 newParent->appendChildNode(c);
556int QSGNode::childCount()
const
559 QSGNode *n = m_firstChild;
562 n = n->m_nextSibling;
568QSGNode *QSGNode::childAtIndex(
int i)
const
570 QSGNode *n = m_firstChild;
573 n = n->m_nextSibling;
580
581
582
583
584
586void QSGNode::setFlag(Flag f,
bool enabled)
588 if (
bool(m_nodeFlags & f) == enabled)
591 Q_ASSERT(
int(UsePreprocess) ==
int(DirtyUsePreprocess));
592 int changedFlag = f & UsePreprocess;
594 markDirty(DirtyState(changedFlag));
599
600
601
602
603
605void QSGNode::setFlags(Flags f,
bool enabled)
607 Flags oldFlags = m_nodeFlags;
612 Q_ASSERT(
int(UsePreprocess) ==
int(DirtyUsePreprocess));
613 int changedFlags = (oldFlags ^ m_nodeFlags) & UsePreprocess;
615 markDirty(DirtyState(changedFlags));
621
622
624void QSGNode::markDirty(DirtyState bits)
626 int renderableCountDiff = 0;
627 if (bits & DirtyNodeAdded)
628 renderableCountDiff += m_subtreeRenderableCount;
629 if (bits & DirtyNodeRemoved)
630 renderableCountDiff -= m_subtreeRenderableCount;
632 QSGNode *p = m_parent;
634 p->m_subtreeRenderableCount += renderableCountDiff;
635 if (p->type() == RootNodeType)
636 static_cast<QSGRootNode *>(p)->notifyNodeChange(
this, bits);
644 QSGNodePrivate::setDescription(node, description);
647 Q_UNUSED(description);
652
653
654
655
656
657
658
659
660
661
662
666
667
668
669
670QSGBasicGeometryNode::QSGBasicGeometryNode(NodeType type)
672 , m_geometry(
nullptr)
674 , m_clip_list(
nullptr)
680
681
682QSGBasicGeometryNode::QSGBasicGeometryNode(QSGBasicGeometryNodePrivate &dd, NodeType type)
684 , m_geometry(
nullptr)
686 , m_clip_list(
nullptr)
692
693
694
695
696
698QSGBasicGeometryNode::~QSGBasicGeometryNode()
700 if (flags() & OwnsGeometry)
706
707
708
709
710
711
714
715
716
717
718
719
722
723
724
725
726
727
728
731
732
733
734
735
736
737
740
741
742
743
746
747
748
749
753
754
755
756
757
758
759
760
761
762
764void QSGBasicGeometryNode::setGeometry(QSGGeometry *geometry)
766 if ((flags() & OwnsGeometry) != 0 && m_geometry != geometry)
768 m_geometry = geometry;
769 markDirty(DirtyGeometry);
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
823
824
826QSGGeometryNode::QSGGeometryNode()
827 : QSGBasicGeometryNode(GeometryNodeType)
833
834
835QSGGeometryNode::QSGGeometryNode(QSGGeometryNodePrivate &dd)
836 : QSGBasicGeometryNode(dd, GeometryNodeType)
838 , m_material(
nullptr)
839 , m_opaque_material(
nullptr)
846
847
848
849
850
851
853QSGGeometryNode::~QSGGeometryNode()
855 if (flags() & OwnsMaterial)
857 if (flags() & OwnsOpaqueMaterial)
858 delete m_opaque_material;
864
865
866
867
868
869
872
873
874
875
876
877
880
881
882
883
884
885
888
889
890
891
892
893
894
898
899
900
901
902
903
904
905
906
907
908
909
910void QSGGeometryNode::setRenderOrder(
int order)
912 m_render_order = order;
918
919
920
921
922
923
924
925
926
927void QSGGeometryNode::setMaterial(QSGMaterial *material)
929 if ((flags() & OwnsMaterial) != 0 && m_material != material)
931 m_material = material;
933 if (m_material !=
nullptr && m_opaque_material == m_material)
934 qWarning(
"QSGGeometryNode: using same material for both opaque and translucent");
936 markDirty(DirtyMaterial);
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958void QSGGeometryNode::setOpaqueMaterial(QSGMaterial *material)
960 if ((flags() & OwnsOpaqueMaterial) != 0 && m_opaque_material != m_material)
961 delete m_opaque_material;
962 m_opaque_material = material;
964 if (m_opaque_material !=
nullptr && m_opaque_material == m_material)
965 qWarning(
"QSGGeometryNode: using same material for both opaque and translucent");
968 markDirty(DirtyMaterial);
974
975
976
977
978
979
980
981
982
983
984
985
986
987QSGMaterial *QSGGeometryNode::activeMaterial()
const
989 if (m_opaque_material && m_opacity > 0.999)
990 return m_opaque_material;
996
997
998
999
1000
1001
1002
1003
1004void QSGGeometryNode::setInheritedOpacity(qreal opacity)
1006 Q_ASSERT(opacity >= 0 && opacity <= 1);
1007 m_opacity = opacity;
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1033
1034
1035
1036
1037
1039QSGClipNode::QSGClipNode()
1040 : QSGBasicGeometryNode(ClipNodeType)
1041 , m_is_rectangular(
false)
1043 Q_UNUSED(m_reserved);
1049
1050
1051
1052
1053
1055QSGClipNode::~QSGClipNode()
1062
1063
1064
1065
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1081void QSGClipNode::setIsRectangular(
bool rectHint)
1083 m_is_rectangular = rectHint;
1089
1090
1091
1092
1096
1097
1098
1099
1100
1101void QSGClipNode::setClipRect(
const QRectF &rect)
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1130
1131
1133QSGTransformNode::QSGTransformNode()
1134 : QSGNode(TransformNodeType)
1141
1142
1144QSGTransformNode::~QSGTransformNode()
1151
1152
1153
1154
1159
1160
1162void QSGTransformNode::setMatrix(
const QMatrix4x4 &matrix)
1165 markDirty(DirtyMatrix);
1169
1170
1171
1172
1173
1174
1175
1180
1181
1182
1183
1184
1185
1186
1187
1188void QSGTransformNode::setCombinedMatrix(
const QMatrix4x4 &matrix)
1190 m_combined_matrix = matrix;
1196
1197
1198
1199
1200
1201
1202
1207
1208
1209
1210
1212QSGRootNode::QSGRootNode()
1213 : QSGNode(RootNodeType)
1219
1220
1221
1222
1223
1225QSGRootNode::~QSGRootNode()
1227 while (!m_renderers.isEmpty())
1228 m_renderers.constLast()->setRootNode(
nullptr);
1235
1236
1237
1239void QSGRootNode::notifyNodeChange(QSGNode *node, DirtyState state)
1241 for (
int i=0; i<m_renderers.size(); ++i) {
1242 m_renderers.at(i)->nodeChanged(node, state);
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1270
1271
1272
1273
1274
1275
1276
1277
1278QSGOpacityNode::QSGOpacityNode()
1279 : QSGNode(OpacityNodeType)
1286
1287
1289QSGOpacityNode::~QSGOpacityNode()
1296
1297
1298
1299
1304
1305
1306
1307
1308
1309
1310
1312void QSGOpacityNode::setOpacity(qreal opacity)
1314 opacity = std::clamp(opacity, qreal(0.0), qreal(1.0));
1315 if (m_opacity == opacity)
1317 DirtyState dirtyState = DirtyOpacity;
1319 if ((m_opacity < OPACITY_THRESHOLD && opacity >= OPACITY_THRESHOLD)
1320 || (m_opacity >= OPACITY_THRESHOLD && opacity < OPACITY_THRESHOLD))
1321 dirtyState |= DirtySubtreeBlocked;
1323 m_opacity = opacity;
1324 markDirty(dirtyState);
1330
1331
1332
1333
1334
1335
1336
1337
1338
1343
1344
1345
1346
1347
1348
1349
1350
1352void QSGOpacityNode::setCombinedOpacity(qreal opacity)
1354 m_combined_opacity = opacity;
1360
1361
1362
1363
1364
1366bool QSGOpacityNode::isSubtreeBlocked()
const
1368 return m_opacity < OPACITY_THRESHOLD;
1373
1374
1375
1376
1377
1379QSGNodeVisitor::~QSGNodeVisitor()
1385void QSGNodeVisitor::visitNode(QSGNode *n)
1387 switch (n->type()) {
1388 case QSGNode::TransformNodeType: {
1389 QSGTransformNode *t =
static_cast<QSGTransformNode *>(n);
1390 enterTransformNode(t);
1392 leaveTransformNode(t);
1394 case QSGNode::GeometryNodeType: {
1395 QSGGeometryNode *g =
static_cast<QSGGeometryNode *>(n);
1396 enterGeometryNode(g);
1398 leaveGeometryNode(g);
1400 case QSGNode::ClipNodeType: {
1401 QSGClipNode *c =
static_cast<QSGClipNode *>(n);
1406 case QSGNode::OpacityNodeType: {
1407 QSGOpacityNode *o =
static_cast<QSGOpacityNode *>(n);
1408 enterOpacityNode(o);
1410 leaveOpacityNode(o);
1418void QSGNodeVisitor::visitChildren(QSGNode *n)
1420 for (QSGNode *c = n->firstChild(); c; c = c->nextSibling())
1424#ifndef QT_NO_DEBUG_STREAM
1428 d <<
"Geometry(null)";
1431 d <<
"GeometryNode(" << Qt::hex << (
const void *) n << Qt::dec;
1433 const QSGGeometry *g = n->geometry();
1439 switch (g->drawingMode()) {
1440 case QSGGeometry::DrawTriangleStrip: d <<
"strip";
break;
1441 case QSGGeometry::DrawTriangleFan: d <<
"fan";
break;
1442 case QSGGeometry::DrawTriangles: d <<
"triangles";
break;
1446 d <<
"#V:" << g->vertexCount() <<
"#I:" << g->indexCount();
1448 if (g->attributeCount() > 0 && g->attributes()->type == QSGGeometry::FloatType) {
1449 float x1 = 1e10, x2 = -1e10, y1=1e10, y2=-1e10;
1450 int stride = g->sizeOfVertex();
1451 for (
int i = 0; i < g->vertexCount(); ++i) {
1452 float x = ((
float *)((
char *)
const_cast<QSGGeometry *>(g)->vertexData() + i * stride))[0];
1453 float y = ((
float *)((
char *)
const_cast<QSGGeometry *>(g)->vertexData() + i * stride))[1];
1461 d <<
"x1=" << x1 <<
"y1=" << y1 <<
"x2=" << x2 <<
"y2=" << y2;
1466 d <<
"materialtype=" << n->material()->type();
1471 d << QSGNodePrivate::description(n);
1479 d <<
"ClipNode(null)";
1482 d <<
"ClipNode(" << Qt::hex << (
const void *) n << Qt::dec;
1484 if (n->childCount())
1485 d <<
"children=" << n->childCount();
1487 d <<
"is rect?" << (n->isRectangular() ?
"yes" :
"no");
1491 d << QSGNodePrivate::description(n);
1493 d << (n->isSubtreeBlocked() ?
"*BLOCKED*" :
"");
1500 d <<
"TransformNode(null)";
1503 const QMatrix4x4 m = n->matrix();
1504 d <<
"TransformNode(";
1505 d << Qt::hex << (
const void *) n << Qt::dec;
1508 else if (m.determinant() == 1 && m(0, 0) == 1 && m(1, 1) == 1 && m(2, 2) == 1)
1509 d <<
"translate" << m(0, 3) << m(1, 3) << m(2, 3);
1511 d <<
"det=" << n->matrix().determinant();
1513 d << QSGNodePrivate::description(n);
1515 d << (n->isSubtreeBlocked() ?
"*BLOCKED*" :
"");
1523 d <<
"OpacityNode(null)";
1526 d <<
"OpacityNode(";
1527 d << Qt::hex << (
const void *) n << Qt::dec;
1528 d <<
"opacity=" << n->opacity()
1529 <<
"combined=" << n->combinedOpacity()
1530 << (n->isSubtreeBlocked() ?
"*BLOCKED*" :
"");
1532 d << QSGNodePrivate::description(n);
1542 d <<
"RootNode(null)";
1545 QDebugStateSaver saver(d);
1546 d <<
"RootNode" << Qt::hex << (
const void *) n << (n->isSubtreeBlocked() ?
"*BLOCKED*" :
"");
1548 d << QSGNodePrivate::description(n);
1562 switch (n->type()) {
1563 case QSGNode::GeometryNodeType:
1564 d <<
static_cast<
const QSGGeometryNode *>(n);
1566 case QSGNode::TransformNodeType:
1567 d <<
static_cast<
const QSGTransformNode *>(n);
1569 case QSGNode::ClipNodeType:
1570 d <<
static_cast<
const QSGClipNode *>(n);
1572 case QSGNode::RootNodeType:
1573 d <<
static_cast<
const QSGRootNode *>(n);
1575 case QSGNode::OpacityNodeType:
1576 d <<
static_cast<
const QSGOpacityNode *>(n);
1578 case QSGNode::RenderNodeType:
1579 d <<
"RenderNode(" << Qt::hex << (
const void *) n << Qt::dec
1580 <<
"flags=" << (
int) n->flags() << Qt::dec
1581 << (n->isSubtreeBlocked() ?
"*BLOCKED*" :
"");
1583 d << QSGNodePrivate::description(n);
1588 d <<
"Node(" << Qt::hex << (
const void *) n << Qt::dec
1589 <<
"flags=" << (
int) n->flags() << Qt::dec
1590 << (n->isSubtreeBlocked() ?
"*BLOCKED*" :
"");
1592 d << QSGNodePrivate::description(n);
QDebug operator<<(QDebug d, const QSGRootNode *n)
QDebug operator<<(QDebug d, const QSGClipNode *n)
QDebug operator<<(QDebug d, const QSGNode *n)
QDebug operator<<(QDebug d, const QSGTransformNode *n)
void qsgnode_set_description(QSGNode *node, const QString &description)
QDebug operator<<(QDebug d, const QSGOpacityNode *n)
static void qt_print_node_count()
static QT_BEGIN_NAMESPACE int qt_node_count
QDebug operator<<(QDebug d, const QSGGeometryNode *n)
const qreal OPACITY_THRESHOLD
#define QSG_RUNTIME_DESCRIPTION