22 qCDebug(lcQsgLeak,
"Number of leaked nodes: %i", qt_node_count);
28
29
30
31
32
33
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
68
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
130
131
132
133
134
135
136
139
140
141
142
145
146
147
148
151
152
153
154
155
156
159
160
161
162
163
164
167
168
169
170
173
174
175
176
177
178
181
182
183
184
185
186
189
190
191
192
193
194
197
198
199
200
203
204
205
206
210
211
213 : m_nodeFlags(OwnedByParent)
219
220
221
222
223QSGNode::QSGNode(NodeType type)
226 , m_firstChild(
nullptr)
227 , m_lastChild(
nullptr)
228 , m_nextSibling(
nullptr)
229 , m_previousSibling(
nullptr)
230 , m_subtreeRenderableCount(type == GeometryNodeType || type == RenderNodeType ? 1 : 0)
231 , m_nodeFlags(OwnedByParent)
237
238
239
240
241QSGNode::QSGNode(QSGNodePrivate &dd, NodeType type)
244 , m_firstChild(
nullptr)
245 , m_lastChild(
nullptr)
246 , m_nextSibling(
nullptr)
247 , m_previousSibling(
nullptr)
248 , m_subtreeRenderableCount(type == GeometryNodeType || type == RenderNodeType ? 1 : 0)
249 , m_nodeFlags(OwnedByParent)
256
257
261 if (lcQsgLeak().isDebugEnabled()) {
263 static bool atexit_registered =
false;
264 if (!atexit_registered) {
265 atexit(qt_print_node_count);
266 atexit_registered =
true;
273 d_ptr.reset(
new QSGNodePrivate());
278
279
280
281
282
286 if (lcQsgLeak().isDebugEnabled()) {
288 if (qt_node_count < 0)
289 qCDebug(lcQsgLeak,
"Node destroyed after qt_print_node_count() was called.");
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
317
318
319
320
321
322
323
324
326bool QSGNode::isSubtreeBlocked()
const
332
333
334
335
336
337
338
339
340
341
343void QSGNode::destroy()
346 m_parent->removeChildNode(
this);
347 Q_ASSERT(m_parent ==
nullptr);
349 while (m_firstChild) {
350 QSGNode *child = m_firstChild;
351 removeChildNode(child);
352 Q_ASSERT(child->m_parent ==
nullptr);
353 if (child->flags() & OwnedByParent)
357 Q_ASSERT(m_firstChild ==
nullptr && m_lastChild ==
nullptr);
362
363
364
365
366
368void QSGNode::prependChildNode(QSGNode *node)
371 Q_ASSERT_X(!node->m_parent,
"QSGNode::prependChildNode",
"QSGNode already has a parent");
374 if (node->type() == QSGNode::GeometryNodeType) {
375 QSGGeometryNode *g =
static_cast<QSGGeometryNode *>(node);
376 Q_ASSERT_X(g->material(),
"QSGNode::prependChildNode",
"QSGGeometryNode is missing material");
377 Q_ASSERT_X(g->geometry(),
"QSGNode::prependChildNode",
"QSGGeometryNode is missing geometry");
382 m_firstChild->m_previousSibling = node;
385 node->m_nextSibling = m_firstChild;
387 node->m_parent =
this;
389 node->markDirty(DirtyNodeAdded);
393
394
395
396
397
399void QSGNode::appendChildNode(QSGNode *node)
402 Q_ASSERT_X(!node->m_parent,
"QSGNode::appendChildNode",
"QSGNode already has a parent");
405 if (node->type() == QSGNode::GeometryNodeType) {
406 QSGGeometryNode *g =
static_cast<QSGGeometryNode *>(node);
407 Q_ASSERT_X(g->material(),
"QSGNode::appendChildNode",
"QSGGeometryNode is missing material");
408 Q_ASSERT_X(g->geometry(),
"QSGNode::appendChildNode",
"QSGGeometryNode is missing geometry");
413 m_lastChild->m_nextSibling = node;
416 node->m_previousSibling = m_lastChild;
418 node->m_parent =
this;
420 node->markDirty(DirtyNodeAdded);
426
427
428
429
430
432void QSGNode::insertChildNodeBefore(QSGNode *node, QSGNode *before)
435 Q_ASSERT_X(!node->m_parent,
"QSGNode::insertChildNodeBefore",
"QSGNode already has a parent");
436 Q_ASSERT_X(before && before->m_parent ==
this,
"QSGNode::insertChildNodeBefore",
"The parent of \'before\' is wrong");
439 if (node->type() == QSGNode::GeometryNodeType) {
440 QSGGeometryNode *g =
static_cast<QSGGeometryNode *>(node);
441 Q_ASSERT_X(g->material(),
"QSGNode::insertChildNodeBefore",
"QSGGeometryNode is missing material");
442 Q_ASSERT_X(g->geometry(),
"QSGNode::insertChildNodeBefore",
"QSGGeometryNode is missing geometry");
446 QSGNode *previous = before->m_previousSibling;
448 previous->m_nextSibling = node;
451 node->m_previousSibling = previous;
452 node->m_nextSibling = before;
453 before->m_previousSibling = node;
454 node->m_parent =
this;
456 node->markDirty(DirtyNodeAdded);
462
463
464
465
466
468void QSGNode::insertChildNodeAfter(QSGNode *node, QSGNode *after)
471 Q_ASSERT_X(!node->m_parent,
"QSGNode::insertChildNodeAfter",
"QSGNode already has a parent");
472 Q_ASSERT_X(after && after->m_parent ==
this,
"QSGNode::insertChildNodeAfter",
"The parent of \'after\' is wrong");
475 if (node->type() == QSGNode::GeometryNodeType) {
476 QSGGeometryNode *g =
static_cast<QSGGeometryNode *>(node);
477 Q_ASSERT_X(g->material(),
"QSGNode::insertChildNodeAfter",
"QSGGeometryNode is missing material");
478 Q_ASSERT_X(g->geometry(),
"QSGNode::insertChildNodeAfter",
"QSGGeometryNode is missing geometry");
482 QSGNode *next = after->m_nextSibling;
484 next->m_previousSibling = node;
487 node->m_nextSibling = next;
488 node->m_previousSibling = after;
489 after->m_nextSibling = node;
490 node->m_parent =
this;
492 node->markDirty(DirtyNodeAdded);
498
499
501void QSGNode::removeChildNode(QSGNode *node)
504 Q_ASSERT(node->parent() ==
this);
506 QSGNode *previous = node->m_previousSibling;
507 QSGNode *next = node->m_nextSibling;
509 previous->m_nextSibling = next;
513 next->m_previousSibling = previous;
515 m_lastChild = previous;
516 node->m_previousSibling =
nullptr;
517 node->m_nextSibling =
nullptr;
519 node->markDirty(DirtyNodeRemoved);
520 node->m_parent =
nullptr;
525
526
528void QSGNode::removeAllChildNodes()
530 while (m_firstChild) {
531 QSGNode *node = m_firstChild;
532 m_firstChild = node->m_nextSibling;
533 node->m_nextSibling =
nullptr;
535 m_firstChild->m_previousSibling =
nullptr;
537 m_lastChild =
nullptr;
538 node->markDirty(DirtyNodeRemoved);
539 node->m_parent =
nullptr;
544
545
546
547
548void QSGNode::reparentChildNodesTo(QSGNode *newParent)
550 for (QSGNode *c = firstChild(); c; c = firstChild()) {
552 newParent->appendChildNode(c);
557int QSGNode::childCount()
const
560 QSGNode *n = m_firstChild;
563 n = n->m_nextSibling;
569QSGNode *QSGNode::childAtIndex(
int i)
const
571 QSGNode *n = m_firstChild;
574 n = n->m_nextSibling;
581
582
583
584
585
587void QSGNode::setFlag(Flag f,
bool enabled)
589 if (
bool(m_nodeFlags & f) == enabled)
592 Q_ASSERT(
int(UsePreprocess) ==
int(DirtyUsePreprocess));
593 int changedFlag = f & UsePreprocess;
595 markDirty(DirtyState(changedFlag));
600
601
602
603
604
606void QSGNode::setFlags(Flags f,
bool enabled)
608 Flags oldFlags = m_nodeFlags;
613 Q_ASSERT(
int(UsePreprocess) ==
int(DirtyUsePreprocess));
614 int changedFlags = (oldFlags ^ m_nodeFlags) & UsePreprocess;
616 markDirty(DirtyState(changedFlags));
622
623
625void QSGNode::markDirty(DirtyState bits)
627 int renderableCountDiff = 0;
628 if (bits & DirtyNodeAdded)
629 renderableCountDiff += m_subtreeRenderableCount;
630 if (bits & DirtyNodeRemoved)
631 renderableCountDiff -= m_subtreeRenderableCount;
633 QSGNode *p = m_parent;
635 p->m_subtreeRenderableCount += renderableCountDiff;
636 if (p->type() == RootNodeType)
637 static_cast<QSGRootNode *>(p)->notifyNodeChange(
this, bits);
645 QSGNodePrivate::setDescription(node, description);
648 Q_UNUSED(description);
653
654
655
656
657
658
659
660
661
662
663
667
668
669
670
671QSGBasicGeometryNode::QSGBasicGeometryNode(NodeType type)
673 , m_geometry(
nullptr)
675 , m_clip_list(
nullptr)
681
682
683QSGBasicGeometryNode::QSGBasicGeometryNode(QSGBasicGeometryNodePrivate &dd, NodeType type)
685 , m_geometry(
nullptr)
687 , m_clip_list(
nullptr)
693
694
695
696
697
699QSGBasicGeometryNode::~QSGBasicGeometryNode()
701 if (flags() & OwnsGeometry)
707
708
709
710
711
712
715
716
717
718
719
720
723
724
725
726
727
728
729
732
733
734
735
736
737
738
741
742
743
744
747
748
749
750
754
755
756
757
758
759
760
761
762
763
765void QSGBasicGeometryNode::setGeometry(QSGGeometry *geometry)
767 if ((flags() & OwnsGeometry) != 0 && m_geometry != geometry)
769 m_geometry = geometry;
770 markDirty(DirtyGeometry);
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
820
824
825
827QSGGeometryNode::QSGGeometryNode()
828 : QSGBasicGeometryNode(GeometryNodeType)
834
835
836QSGGeometryNode::QSGGeometryNode(QSGGeometryNodePrivate &dd)
837 : QSGBasicGeometryNode(dd, GeometryNodeType)
839 , m_material(
nullptr)
840 , m_opaque_material(
nullptr)
847
848
849
850
851
852
854QSGGeometryNode::~QSGGeometryNode()
856 if (flags() & OwnsMaterial)
858 if (flags() & OwnsOpaqueMaterial)
859 delete m_opaque_material;
865
866
867
868
869
870
873
874
875
876
877
878
881
882
883
884
885
886
889
890
891
892
893
894
895
899
900
901
902
903
904
905
906
907
908
909
910
911void QSGGeometryNode::setRenderOrder(
int order)
913 m_render_order = order;
919
920
921
922
923
924
925
926
927
928void QSGGeometryNode::setMaterial(QSGMaterial *material)
930 if ((flags() & OwnsMaterial) != 0 && m_material != material)
932 m_material = material;
934 if (m_material !=
nullptr && m_opaque_material == m_material)
935 qWarning(
"QSGGeometryNode: using same material for both opaque and translucent");
937 markDirty(DirtyMaterial);
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959void QSGGeometryNode::setOpaqueMaterial(QSGMaterial *material)
961 if ((flags() & OwnsOpaqueMaterial) != 0 && m_opaque_material != m_material)
962 delete m_opaque_material;
963 m_opaque_material = material;
965 if (m_opaque_material !=
nullptr && m_opaque_material == m_material)
966 qWarning(
"QSGGeometryNode: using same material for both opaque and translucent");
969 markDirty(DirtyMaterial);
975
976
977
978
979
980
981
982
983
984
985
986
987
988QSGMaterial *QSGGeometryNode::activeMaterial()
const
990 if (m_opaque_material && m_opacity > 0.999)
991 return m_opaque_material;
997
998
999
1000
1001
1002
1003
1004
1005void QSGGeometryNode::setInheritedOpacity(qreal opacity)
1007 Q_ASSERT(opacity >= 0 && opacity <= 1);
1008 m_opacity = opacity;
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1034
1035
1036
1037
1038
1040QSGClipNode::QSGClipNode()
1041 : QSGBasicGeometryNode(ClipNodeType)
1042 , m_is_rectangular(
false)
1044 Q_UNUSED(m_reserved);
1050
1051
1052
1053
1054
1056QSGClipNode::~QSGClipNode()
1063
1064
1065
1066
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1082void QSGClipNode::setIsRectangular(
bool rectHint)
1084 m_is_rectangular = rectHint;
1090
1091
1092
1093
1097
1098
1099
1100
1101
1102void QSGClipNode::setClipRect(
const QRectF &rect)
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1131
1132
1134QSGTransformNode::QSGTransformNode()
1135 : QSGNode(TransformNodeType)
1142
1143
1145QSGTransformNode::~QSGTransformNode()
1152
1153
1154
1155
1160
1161
1163void QSGTransformNode::setMatrix(
const QMatrix4x4 &matrix)
1166 markDirty(DirtyMatrix);
1170
1171
1172
1173
1174
1175
1176
1181
1182
1183
1184
1185
1186
1187
1188
1189void QSGTransformNode::setCombinedMatrix(
const QMatrix4x4 &matrix)
1191 m_combined_matrix = matrix;
1197
1198
1199
1200
1201
1202
1203
1208
1209
1210
1211
1213QSGRootNode::QSGRootNode()
1214 : QSGNode(RootNodeType)
1220
1221
1222
1223
1224
1226QSGRootNode::~QSGRootNode()
1228 while (!m_renderers.isEmpty())
1229 m_renderers.constLast()->setRootNode(
nullptr);
1236
1237
1238
1240void QSGRootNode::notifyNodeChange(QSGNode *node, DirtyState state)
1242 for (
int i=0; i<m_renderers.size(); ++i) {
1243 m_renderers.at(i)->nodeChanged(node, state);
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1271
1272
1273
1274
1275
1276
1277
1278
1279QSGOpacityNode::QSGOpacityNode()
1280 : QSGNode(OpacityNodeType)
1287
1288
1290QSGOpacityNode::~QSGOpacityNode()
1297
1298
1299
1300
1305
1306
1307
1308
1309
1310
1311
1313void QSGOpacityNode::setOpacity(qreal opacity)
1315 opacity = std::clamp(opacity, qreal(0.0), qreal(1.0));
1316 if (m_opacity == opacity)
1318 DirtyState dirtyState = DirtyOpacity;
1320 if ((m_opacity < OPACITY_THRESHOLD && opacity >= OPACITY_THRESHOLD)
1321 || (m_opacity >= OPACITY_THRESHOLD && opacity < OPACITY_THRESHOLD))
1322 dirtyState |= DirtySubtreeBlocked;
1324 m_opacity = opacity;
1325 markDirty(dirtyState);
1331
1332
1333
1334
1335
1336
1337
1338
1339
1344
1345
1346
1347
1348
1349
1350
1351
1353void QSGOpacityNode::setCombinedOpacity(qreal opacity)
1355 m_combined_opacity = opacity;
1361
1362
1363
1364
1365
1367bool QSGOpacityNode::isSubtreeBlocked()
const
1369 return m_opacity < OPACITY_THRESHOLD;
1374
1375
1376
1377
1378
1380QSGNodeVisitor::~QSGNodeVisitor()
1386void QSGNodeVisitor::visitNode(QSGNode *n)
1388 switch (n->type()) {
1389 case QSGNode::TransformNodeType: {
1390 QSGTransformNode *t =
static_cast<QSGTransformNode *>(n);
1391 enterTransformNode(t);
1393 leaveTransformNode(t);
1395 case QSGNode::GeometryNodeType: {
1396 QSGGeometryNode *g =
static_cast<QSGGeometryNode *>(n);
1397 enterGeometryNode(g);
1399 leaveGeometryNode(g);
1401 case QSGNode::ClipNodeType: {
1402 QSGClipNode *c =
static_cast<QSGClipNode *>(n);
1407 case QSGNode::OpacityNodeType: {
1408 QSGOpacityNode *o =
static_cast<QSGOpacityNode *>(n);
1409 enterOpacityNode(o);
1411 leaveOpacityNode(o);
1419void QSGNodeVisitor::visitChildren(QSGNode *n)
1421 for (QSGNode *c = n->firstChild(); c; c = c->nextSibling())
1425#ifndef QT_NO_DEBUG_STREAM
1429 d <<
"Geometry(null)";
1432 d <<
"GeometryNode(" << Qt::hex << (
const void *) n << Qt::dec;
1434 const QSGGeometry *g = n->geometry();
1440 switch (g->drawingMode()) {
1441 case QSGGeometry::DrawTriangleStrip: d <<
"strip";
break;
1442 case QSGGeometry::DrawTriangleFan: d <<
"fan";
break;
1443 case QSGGeometry::DrawTriangles: d <<
"triangles";
break;
1447 d <<
"#V:" << g->vertexCount() <<
"#I:" << g->indexCount();
1449 if (g->attributeCount() > 0 && g->attributes()->type == QSGGeometry::FloatType) {
1450 float x1 = 1e10, x2 = -1e10, y1=1e10, y2=-1e10;
1451 int stride = g->sizeOfVertex();
1452 for (
int i = 0; i < g->vertexCount(); ++i) {
1453 float x = ((
float *)((
char *)
const_cast<QSGGeometry *>(g)->vertexData() + i * stride))[0];
1454 float y = ((
float *)((
char *)
const_cast<QSGGeometry *>(g)->vertexData() + i * stride))[1];
1462 d <<
"x1=" << x1 <<
"y1=" << y1 <<
"x2=" << x2 <<
"y2=" << y2;
1467 d <<
"materialtype=" << n->material()->type();
1472 d << QSGNodePrivate::description(n);
1480 d <<
"ClipNode(null)";
1483 d <<
"ClipNode(" << Qt::hex << (
const void *) n << Qt::dec;
1485 if (n->childCount())
1486 d <<
"children=" << n->childCount();
1488 d <<
"is rect?" << (n->isRectangular() ?
"yes" :
"no");
1492 d << QSGNodePrivate::description(n);
1494 d << (n->isSubtreeBlocked() ?
"*BLOCKED*" :
"");
1501 d <<
"TransformNode(null)";
1504 const QMatrix4x4 m = n->matrix();
1505 d <<
"TransformNode(";
1506 d << Qt::hex << (
const void *) n << Qt::dec;
1509 else if (m.determinant() == 1 && m(0, 0) == 1 && m(1, 1) == 1 && m(2, 2) == 1)
1510 d <<
"translate" << m(0, 3) << m(1, 3) << m(2, 3);
1512 d <<
"det=" << n->matrix().determinant();
1514 d << QSGNodePrivate::description(n);
1516 d << (n->isSubtreeBlocked() ?
"*BLOCKED*" :
"");
1524 d <<
"OpacityNode(null)";
1527 d <<
"OpacityNode(";
1528 d << Qt::hex << (
const void *) n << Qt::dec;
1529 d <<
"opacity=" << n->opacity()
1530 <<
"combined=" << n->combinedOpacity()
1531 << (n->isSubtreeBlocked() ?
"*BLOCKED*" :
"");
1533 d << QSGNodePrivate::description(n);
1543 d <<
"RootNode(null)";
1546 QDebugStateSaver saver(d);
1547 d <<
"RootNode" << Qt::hex << (
const void *) n << (n->isSubtreeBlocked() ?
"*BLOCKED*" :
"");
1549 d << QSGNodePrivate::description(n);
1563 switch (n->type()) {
1564 case QSGNode::GeometryNodeType:
1565 d <<
static_cast<
const QSGGeometryNode *>(n);
1567 case QSGNode::TransformNodeType:
1568 d <<
static_cast<
const QSGTransformNode *>(n);
1570 case QSGNode::ClipNodeType:
1571 d <<
static_cast<
const QSGClipNode *>(n);
1573 case QSGNode::RootNodeType:
1574 d <<
static_cast<
const QSGRootNode *>(n);
1576 case QSGNode::OpacityNodeType:
1577 d <<
static_cast<
const QSGOpacityNode *>(n);
1579 case QSGNode::RenderNodeType:
1580 d <<
"RenderNode(" << Qt::hex << (
const void *) n << Qt::dec
1581 <<
"flags=" << (
int) n->flags() << Qt::dec
1582 << (n->isSubtreeBlocked() ?
"*BLOCKED*" :
"");
1584 d << QSGNodePrivate::description(n);
1589 d <<
"Node(" << Qt::hex << (
const void *) n << Qt::dec
1590 <<
"flags=" << (
int) n->flags() << Qt::dec
1591 << (n->isSubtreeBlocked() ?
"*BLOCKED*" :
"");
1593 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