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);
360quint8 QSGNodePrivate::mutabilityGroup(
const QSGNode *node)
362 return !node->d_ptr.isNull()
363 ? node->d_ptr->m_mutabilityGroup
368
369
370
371
372void QSGNodePrivate::setMutabilityGroupOfSubtree(QSGNode *node, quint8 group)
374 Q_ASSERT((group & 0xf) == group);
376 const quint8 currentMutabilityGroup = mutabilityGroup(node);
377 if (currentMutabilityGroup != group) {
378 if (node->d_ptr.isNull())
379 node->d_ptr.reset(
new QSGNodePrivate());
380 node->d_ptr->m_mutabilityGroup = group;
381 node->markDirty(QSGNode::DirtyGeometry);
384 for (
int i = 0; i < node->childCount(); ++i)
385 QSGNodePrivate::setMutabilityGroupOfSubtree(node->childAtIndex(i), group);
389
390
391
392
393
395void QSGNode::prependChildNode(QSGNode *node)
398 Q_ASSERT_X(!node->m_parent,
"QSGNode::prependChildNode",
"QSGNode already has a parent");
401 if (node->type() == QSGNode::GeometryNodeType) {
402 QSGGeometryNode *g =
static_cast<QSGGeometryNode *>(node);
403 Q_ASSERT_X(g->material(),
"QSGNode::prependChildNode",
"QSGGeometryNode is missing material");
404 Q_ASSERT_X(g->geometry(),
"QSGNode::prependChildNode",
"QSGGeometryNode is missing geometry");
409 m_firstChild->m_previousSibling = node;
412 node->m_nextSibling = m_firstChild;
414 node->m_parent =
this;
416 node->markDirty(DirtyNodeAdded);
420
421
422
423
424
426void QSGNode::appendChildNode(QSGNode *node)
429 Q_ASSERT_X(!node->m_parent,
"QSGNode::appendChildNode",
"QSGNode already has a parent");
432 if (node->type() == QSGNode::GeometryNodeType) {
433 QSGGeometryNode *g =
static_cast<QSGGeometryNode *>(node);
434 Q_ASSERT_X(g->material(),
"QSGNode::appendChildNode",
"QSGGeometryNode is missing material");
435 Q_ASSERT_X(g->geometry(),
"QSGNode::appendChildNode",
"QSGGeometryNode is missing geometry");
440 m_lastChild->m_nextSibling = node;
443 node->m_previousSibling = m_lastChild;
445 node->m_parent =
this;
447 node->markDirty(DirtyNodeAdded);
453
454
455
456
457
459void QSGNode::insertChildNodeBefore(QSGNode *node, QSGNode *before)
462 Q_ASSERT_X(!node->m_parent,
"QSGNode::insertChildNodeBefore",
"QSGNode already has a parent");
463 Q_ASSERT_X(before && before->m_parent ==
this,
"QSGNode::insertChildNodeBefore",
"The parent of \'before\' is wrong");
466 if (node->type() == QSGNode::GeometryNodeType) {
467 QSGGeometryNode *g =
static_cast<QSGGeometryNode *>(node);
468 Q_ASSERT_X(g->material(),
"QSGNode::insertChildNodeBefore",
"QSGGeometryNode is missing material");
469 Q_ASSERT_X(g->geometry(),
"QSGNode::insertChildNodeBefore",
"QSGGeometryNode is missing geometry");
473 QSGNode *previous = before->m_previousSibling;
475 previous->m_nextSibling = node;
478 node->m_previousSibling = previous;
479 node->m_nextSibling = before;
480 before->m_previousSibling = node;
481 node->m_parent =
this;
483 node->markDirty(DirtyNodeAdded);
489
490
491
492
493
495void QSGNode::insertChildNodeAfter(QSGNode *node, QSGNode *after)
498 Q_ASSERT_X(!node->m_parent,
"QSGNode::insertChildNodeAfter",
"QSGNode already has a parent");
499 Q_ASSERT_X(after && after->m_parent ==
this,
"QSGNode::insertChildNodeAfter",
"The parent of \'after\' is wrong");
502 if (node->type() == QSGNode::GeometryNodeType) {
503 QSGGeometryNode *g =
static_cast<QSGGeometryNode *>(node);
504 Q_ASSERT_X(g->material(),
"QSGNode::insertChildNodeAfter",
"QSGGeometryNode is missing material");
505 Q_ASSERT_X(g->geometry(),
"QSGNode::insertChildNodeAfter",
"QSGGeometryNode is missing geometry");
509 QSGNode *next = after->m_nextSibling;
511 next->m_previousSibling = node;
514 node->m_nextSibling = next;
515 node->m_previousSibling = after;
516 after->m_nextSibling = node;
517 node->m_parent =
this;
519 node->markDirty(DirtyNodeAdded);
525
526
528void QSGNode::removeChildNode(QSGNode *node)
531 Q_ASSERT(node->parent() ==
this);
533 QSGNode *previous = node->m_previousSibling;
534 QSGNode *next = node->m_nextSibling;
536 previous->m_nextSibling = next;
540 next->m_previousSibling = previous;
542 m_lastChild = previous;
543 node->m_previousSibling =
nullptr;
544 node->m_nextSibling =
nullptr;
546 node->markDirty(DirtyNodeRemoved);
547 node->m_parent =
nullptr;
552
553
555void QSGNode::removeAllChildNodes()
557 while (m_firstChild) {
558 QSGNode *node = m_firstChild;
559 m_firstChild = node->m_nextSibling;
560 node->m_nextSibling =
nullptr;
562 m_firstChild->m_previousSibling =
nullptr;
564 m_lastChild =
nullptr;
565 node->markDirty(DirtyNodeRemoved);
566 node->m_parent =
nullptr;
571
572
573
574
575void QSGNode::reparentChildNodesTo(QSGNode *newParent)
577 for (QSGNode *c = firstChild(); c; c = firstChild()) {
579 newParent->appendChildNode(c);
584int QSGNode::childCount()
const
587 QSGNode *n = m_firstChild;
590 n = n->m_nextSibling;
596QSGNode *QSGNode::childAtIndex(
int i)
const
598 QSGNode *n = m_firstChild;
601 n = n->m_nextSibling;
608
609
610
611
612
614void QSGNode::setFlag(Flag f,
bool enabled)
616 if (
bool(m_nodeFlags & f) == enabled)
619 Q_ASSERT(
int(UsePreprocess) ==
int(DirtyUsePreprocess));
620 int changedFlag = f & UsePreprocess;
622 markDirty(DirtyState(changedFlag));
627
628
629
630
631
633void QSGNode::setFlags(Flags f,
bool enabled)
635 Flags oldFlags = m_nodeFlags;
640 Q_ASSERT(
int(UsePreprocess) ==
int(DirtyUsePreprocess));
641 int changedFlags = (oldFlags ^ m_nodeFlags) & UsePreprocess;
643 markDirty(DirtyState(changedFlags));
649
650
652void QSGNode::markDirty(DirtyState bits)
654 int renderableCountDiff = 0;
655 if (bits & DirtyNodeAdded)
656 renderableCountDiff += m_subtreeRenderableCount;
657 if (bits & DirtyNodeRemoved)
658 renderableCountDiff -= m_subtreeRenderableCount;
660 QSGNode *p = m_parent;
662 p->m_subtreeRenderableCount += renderableCountDiff;
663 if (p->type() == RootNodeType)
664 static_cast<QSGRootNode *>(p)->notifyNodeChange(
this, bits);
672 QSGNodePrivate::setDescription(node, description);
675 Q_UNUSED(description);
680
681
682
683
684
685
686
687
688
689
690
694
695
696
697
698QSGBasicGeometryNode::QSGBasicGeometryNode(NodeType type)
700 , m_geometry(
nullptr)
702 , m_clip_list(
nullptr)
708
709
710QSGBasicGeometryNode::QSGBasicGeometryNode(QSGBasicGeometryNodePrivate &dd, NodeType type)
712 , m_geometry(
nullptr)
714 , m_clip_list(
nullptr)
720
721
722
723
724
726QSGBasicGeometryNode::~QSGBasicGeometryNode()
728 if (flags() & OwnsGeometry)
734
735
736
737
738
739
742
743
744
745
746
747
750
751
752
753
754
755
756
759
760
761
762
763
764
765
768
769
770
771
774
775
776
777
781
782
783
784
785
786
787
788
789
790
792void QSGBasicGeometryNode::setGeometry(QSGGeometry *geometry)
794 if ((flags() & OwnsGeometry) != 0 && m_geometry != geometry)
796 m_geometry = geometry;
797 markDirty(DirtyGeometry);
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
851
852
854QSGGeometryNode::QSGGeometryNode()
855 : QSGBasicGeometryNode(GeometryNodeType)
861
862
863QSGGeometryNode::QSGGeometryNode(QSGGeometryNodePrivate &dd)
864 : QSGBasicGeometryNode(dd, GeometryNodeType)
866 , m_material(
nullptr)
867 , m_opaque_material(
nullptr)
874
875
876
877
878
879
881QSGGeometryNode::~QSGGeometryNode()
883 if (flags() & OwnsMaterial)
885 if (flags() & OwnsOpaqueMaterial)
886 delete m_opaque_material;
892
893
894
895
896
897
900
901
902
903
904
905
908
909
910
911
912
913
916
917
918
919
920
921
922
926
927
928
929
930
931
932
933
934
935
936
937
938void QSGGeometryNode::setRenderOrder(
int order)
940 m_render_order = order;
946
947
948
949
950
951
952
953
954
955void QSGGeometryNode::setMaterial(QSGMaterial *material)
957 if ((flags() & OwnsMaterial) != 0 && m_material != material)
959 m_material = material;
961 if (m_material !=
nullptr && m_opaque_material == m_material)
962 qWarning(
"QSGGeometryNode: using same material for both opaque and translucent");
964 markDirty(DirtyMaterial);
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986void QSGGeometryNode::setOpaqueMaterial(QSGMaterial *material)
988 if ((flags() & OwnsOpaqueMaterial) != 0 && m_opaque_material != m_material)
989 delete m_opaque_material;
990 m_opaque_material = material;
992 if (m_opaque_material !=
nullptr && m_opaque_material == m_material)
993 qWarning(
"QSGGeometryNode: using same material for both opaque and translucent");
996 markDirty(DirtyMaterial);
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015QSGMaterial *QSGGeometryNode::activeMaterial()
const
1017 if (m_opaque_material && m_opacity > 0.999)
1018 return m_opaque_material;
1024
1025
1026
1027
1028
1029
1030
1031
1032void QSGGeometryNode::setInheritedOpacity(qreal opacity)
1034 Q_ASSERT(opacity >= 0 && opacity <= 1);
1035 m_opacity = opacity;
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1061
1062
1063
1064
1065
1067QSGClipNode::QSGClipNode()
1068 : QSGBasicGeometryNode(ClipNodeType)
1069 , m_is_rectangular(
false)
1071 Q_UNUSED(m_reserved);
1077
1078
1079
1080
1081
1083QSGClipNode::~QSGClipNode()
1090
1091
1092
1093
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1109void QSGClipNode::setIsRectangular(
bool rectHint)
1111 m_is_rectangular = rectHint;
1117
1118
1119
1120
1124
1125
1126
1127
1128
1129void QSGClipNode::setClipRect(
const QRectF &rect)
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1158
1159
1161QSGTransformNode::QSGTransformNode()
1162 : QSGNode(TransformNodeType)
1169
1170
1172QSGTransformNode::~QSGTransformNode()
1179
1180
1181
1182
1187
1188
1190void QSGTransformNode::setMatrix(
const QMatrix4x4 &matrix)
1193 markDirty(DirtyMatrix);
1197
1198
1199
1200
1201
1202
1203
1208
1209
1210
1211
1212
1213
1214
1215
1216void QSGTransformNode::setCombinedMatrix(
const QMatrix4x4 &matrix)
1218 m_combined_matrix = matrix;
1224
1225
1226
1227
1228
1229
1230
1235
1236
1237
1238
1240QSGRootNode::QSGRootNode()
1241 : QSGNode(RootNodeType)
1247
1248
1249
1250
1251
1253QSGRootNode::~QSGRootNode()
1255 while (!m_renderers.isEmpty())
1256 m_renderers.constLast()->setRootNode(
nullptr);
1263
1264
1265
1267void QSGRootNode::notifyNodeChange(QSGNode *node, DirtyState state)
1269 for (
int i=0; i<m_renderers.size(); ++i) {
1270 m_renderers.at(i)->nodeChanged(node, state);
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1298
1299
1300
1301
1302
1303
1304
1305
1306QSGOpacityNode::QSGOpacityNode()
1307 : QSGNode(OpacityNodeType)
1314
1315
1317QSGOpacityNode::~QSGOpacityNode()
1324
1325
1326
1327
1332
1333
1334
1335
1336
1337
1338
1340void QSGOpacityNode::setOpacity(qreal opacity)
1342 opacity = std::clamp(opacity, qreal(0.0), qreal(1.0));
1343 if (m_opacity == opacity)
1345 DirtyState dirtyState = DirtyOpacity;
1347 if ((m_opacity < OPACITY_THRESHOLD && opacity >= OPACITY_THRESHOLD)
1348 || (m_opacity >= OPACITY_THRESHOLD && opacity < OPACITY_THRESHOLD))
1349 dirtyState |= DirtySubtreeBlocked;
1351 m_opacity = opacity;
1352 markDirty(dirtyState);
1358
1359
1360
1361
1362
1363
1364
1365
1366
1371
1372
1373
1374
1375
1376
1377
1378
1380void QSGOpacityNode::setCombinedOpacity(qreal opacity)
1382 m_combined_opacity = opacity;
1388
1389
1390
1391
1392
1394bool QSGOpacityNode::isSubtreeBlocked()
const
1396 return m_opacity < OPACITY_THRESHOLD;
1401
1402
1403
1404
1405
1407QSGNodeVisitor::~QSGNodeVisitor()
1413void QSGNodeVisitor::visitNode(QSGNode *n)
1415 switch (n->type()) {
1416 case QSGNode::TransformNodeType: {
1417 QSGTransformNode *t =
static_cast<QSGTransformNode *>(n);
1418 enterTransformNode(t);
1420 leaveTransformNode(t);
1422 case QSGNode::GeometryNodeType: {
1423 QSGGeometryNode *g =
static_cast<QSGGeometryNode *>(n);
1424 enterGeometryNode(g);
1426 leaveGeometryNode(g);
1428 case QSGNode::ClipNodeType: {
1429 QSGClipNode *c =
static_cast<QSGClipNode *>(n);
1434 case QSGNode::OpacityNodeType: {
1435 QSGOpacityNode *o =
static_cast<QSGOpacityNode *>(n);
1436 enterOpacityNode(o);
1438 leaveOpacityNode(o);
1446void QSGNodeVisitor::visitChildren(QSGNode *n)
1448 for (QSGNode *c = n->firstChild(); c; c = c->nextSibling())
1452#ifndef QT_NO_DEBUG_STREAM
1456 d <<
"Geometry(null)";
1459 d <<
"GeometryNode(" << Qt::hex << (
const void *) n << Qt::dec;
1461 const QSGGeometry *g = n->geometry();
1467 switch (g->drawingMode()) {
1468 case QSGGeometry::DrawTriangleStrip: d <<
"strip";
break;
1469 case QSGGeometry::DrawTriangleFan: d <<
"fan";
break;
1470 case QSGGeometry::DrawTriangles: d <<
"triangles";
break;
1474 d <<
"#V:" << g->vertexCount() <<
"#I:" << g->indexCount();
1476 if (g->attributeCount() > 0 && g->attributes()->type == QSGGeometry::FloatType) {
1477 float x1 = 1e10, x2 = -1e10, y1=1e10, y2=-1e10;
1478 int stride = g->sizeOfVertex();
1479 for (
int i = 0; i < g->vertexCount(); ++i) {
1480 float x = ((
float *)((
char *)
const_cast<QSGGeometry *>(g)->vertexData() + i * stride))[0];
1481 float y = ((
float *)((
char *)
const_cast<QSGGeometry *>(g)->vertexData() + i * stride))[1];
1489 d <<
"x1=" << x1 <<
"y1=" << y1 <<
"x2=" << x2 <<
"y2=" << y2;
1494 d <<
"materialtype=" << n->material()->type();
1499 d << QSGNodePrivate::description(n);
1507 d <<
"ClipNode(null)";
1510 d <<
"ClipNode(" << Qt::hex << (
const void *) n << Qt::dec;
1512 if (n->childCount())
1513 d <<
"children=" << n->childCount();
1515 d <<
"is rect?" << (n->isRectangular() ?
"yes" :
"no");
1519 d << QSGNodePrivate::description(n);
1521 d << (n->isSubtreeBlocked() ?
"*BLOCKED*" :
"");
1528 d <<
"TransformNode(null)";
1531 const QMatrix4x4 m = n->matrix();
1532 d <<
"TransformNode(";
1533 d << Qt::hex << (
const void *) n << Qt::dec;
1536 else if (m.determinant() == 1 && m(0, 0) == 1 && m(1, 1) == 1 && m(2, 2) == 1)
1537 d <<
"translate" << m(0, 3) << m(1, 3) << m(2, 3);
1539 d <<
"det=" << n->matrix().determinant();
1541 d << QSGNodePrivate::description(n);
1543 d << (n->isSubtreeBlocked() ?
"*BLOCKED*" :
"");
1551 d <<
"OpacityNode(null)";
1554 d <<
"OpacityNode(";
1555 d << Qt::hex << (
const void *) n << Qt::dec;
1556 d <<
"opacity=" << n->opacity()
1557 <<
"combined=" << n->combinedOpacity()
1558 << (n->isSubtreeBlocked() ?
"*BLOCKED*" :
"");
1560 d << QSGNodePrivate::description(n);
1570 d <<
"RootNode(null)";
1573 QDebugStateSaver saver(d);
1574 d <<
"RootNode" << Qt::hex << (
const void *) n << (n->isSubtreeBlocked() ?
"*BLOCKED*" :
"");
1576 d << QSGNodePrivate::description(n);
1590 switch (n->type()) {
1591 case QSGNode::GeometryNodeType:
1592 d <<
static_cast<
const QSGGeometryNode *>(n);
1594 case QSGNode::TransformNodeType:
1595 d <<
static_cast<
const QSGTransformNode *>(n);
1597 case QSGNode::ClipNodeType:
1598 d <<
static_cast<
const QSGClipNode *>(n);
1600 case QSGNode::RootNodeType:
1601 d <<
static_cast<
const QSGRootNode *>(n);
1603 case QSGNode::OpacityNodeType:
1604 d <<
static_cast<
const QSGOpacityNode *>(n);
1606 case QSGNode::RenderNodeType:
1607 d <<
"RenderNode(" << Qt::hex << (
const void *) n << Qt::dec
1608 <<
"flags=" << (
int) n->flags() << Qt::dec
1609 << (n->isSubtreeBlocked() ?
"*BLOCKED*" :
"");
1611 d << QSGNodePrivate::description(n);
1616 d <<
"Node(" << Qt::hex << (
const void *) n << Qt::dec
1617 <<
"flags=" << (
int) n->flags() << Qt::dec
1618 << (n->isSubtreeBlocked() ?
"*BLOCKED*" :
"");
1620 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