Remove "All rights reserved" line from license headers.
[profile/ivi/qtdeclarative.git] / src / quick / scenegraph / coreapi / qsgnode.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtDeclarative module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qsgnode.h"
43 #include "qsgrenderer_p.h"
44 #include "qsgnodeupdater_p.h"
45 #include "qsgmaterial.h"
46
47 #include "limits.h"
48
49 QT_BEGIN_NAMESPACE
50
51 #ifndef QT_NO_DEBUG
52 static int qt_node_count = 0;
53
54 static void qt_print_node_count()
55 {
56     qDebug("Number of leaked nodes: %i", qt_node_count);
57     qt_node_count = -1;
58 }
59 #endif
60
61 /*!
62     \class QSGNode
63     \brief The QSGNode class is the base class for all nodes in the scene graph.
64
65     \inmodule QtQuick
66
67     The QSGNode class can be used as a child container. Children are added with
68     the appendChildNode(), prependChildNode(), insertChildNodeBefore() and
69     insertChildNodeAfter(). Ordering of nodes is important as geometry nodes
70     will be rendered in the order they are added to the scene graph.
71     Actually, the scene may reorder nodes freely, but the resulting visual
72     order is still guaranteed.
73
74     If nodes change every frame, the preprocess() function can be used to
75     apply changes to a node for every frame its rendered. The use of preprocess()
76     must be explicitly enabled by setting the QSGNode::UsePreprocess flag
77     on the node.
78
79     The virtual isSubtreeBlocked() function can be used to disable a subtree all
80     together. Nodes in a blocked subtree will not be preprocessed() and not
81     rendered.
82
83     Anything related to QSGNode should happen on the scene graph rendering thread.
84  */
85
86 QSGNode::QSGNode()
87     : m_parent(0)
88     , m_type(BasicNodeType)
89     , m_firstChild(0)
90     , m_lastChild(0)
91     , m_nextSibling(0)
92     , m_previousSibling(0)
93     , m_subtreeGeometryCount(0)
94     , m_nodeFlags(OwnedByParent)
95     , m_dirtyState(0)
96 {
97     init();
98 }
99
100 QSGNode::QSGNode(NodeType type)
101     : m_parent(0)
102     , m_type(type)
103     , m_firstChild(0)
104     , m_lastChild(0)
105     , m_nextSibling(0)
106     , m_previousSibling(0)
107     , m_subtreeGeometryCount(type == GeometryNodeType ? 1 : 0)
108     , m_nodeFlags(OwnedByParent)
109     , m_dirtyState(0)
110 {
111     init();
112 }
113
114 void QSGNode::init()
115 {
116 #ifndef QT_NO_DEBUG
117     ++qt_node_count;
118     static bool atexit_registered = false;
119     if (!atexit_registered) {
120         atexit(qt_print_node_count);
121         atexit_registered = true;
122     }
123 #endif
124 }
125
126 QSGNode::~QSGNode()
127 {
128 #ifndef QT_NO_DEBUG
129     --qt_node_count;
130     if (qt_node_count < 0)
131         qDebug("Node destroyed after qt_print_node_count() was called.");
132 #endif
133     destroy();
134 }
135
136
137 /*!
138     \fn void QSGNode::preprocess()
139
140     Override this function to do processing on the node before it is rendered.
141
142     Preprocessing needs to be explicitly enabled by setting the flag
143     QSGNode::UsePreprocess. The flag needs to be set before the node is added
144     to the scene graph and will cause the preprocess() function to be called
145     for every frame the node is rendered.
146
147     The preprocess function is called before the update pass that propegates
148     opacity and transformations through the scene graph. That means that
149     functions like QSGOpacityNode::combinedOpacity() and
150     QSGTransformNode::combinedMatrix() will not contain up-to-date values.
151     If such values are changed during the preprocess, these changes will be
152     propegated through the scene graph before it is rendered.
153
154     \warning Beware of deleting nodes while they are being preprocessed. It is
155     possible, with a small performance hit, to delete a single node during its
156     own preprocess call. Deleting a subtree which has nodes that also use
157     preprocessing may result in a segmentation fault. This is done for
158     performance reasons.
159  */
160
161
162
163
164 /*!
165     Returns whether this node and its subtree is available for use.
166
167     Blocked subtrees will not get their dirty states updated and they
168     will not be rendered.
169
170     The QSGOpacityNode will return a blocked subtree when accumulated opacity
171     is 0, for instance.
172  */
173
174 bool QSGNode::isSubtreeBlocked() const
175 {
176     return m_subtreeGeometryCount == 0;
177 }
178
179 /*!
180     \internal
181     Detaches the node from the scene graph and deletes any children it owns.
182
183     This function is called from QSGNode's and QSGRootNode's destructor. It
184     should not be called explicitly in user code. QSGRootNode needs to call
185     destroy() because destroy() calls removeChildNode() which in turn calls
186     markDirty() which type-casts the node to QSGRootNode. This type-cast is not
187     valid at the time QSGNode's destructor is called because the node will
188     already be partially destroyed at that point.
189 */
190
191 void QSGNode::destroy()
192 {
193     if (m_parent) {
194         m_parent->removeChildNode(this);
195         Q_ASSERT(m_parent == 0);
196     }
197     while (m_firstChild) {
198         QSGNode *child = m_firstChild;
199         removeChildNode(child);
200         Q_ASSERT(child->m_parent == 0);
201         if (child->flags() & OwnedByParent)
202             delete child;
203     }
204
205     Q_ASSERT(m_firstChild == 0 && m_lastChild == 0);
206 }
207
208
209 /*!
210     Prepends \a node to this node's the list of children.
211
212     Ordering of nodes is important as geometry nodes will be rendered in the
213     order they are added to the scene graph.
214  */
215
216 void QSGNode::prependChildNode(QSGNode *node)
217 {
218     //Q_ASSERT_X(!m_children.contains(node), "QSGNode::prependChildNode", "QSGNode is already a child!");
219     Q_ASSERT_X(!node->m_parent, "QSGNode::prependChildNode", "QSGNode already has a parent");
220
221 #ifndef QT_NO_DEBUG
222     if (node->type() == QSGNode::GeometryNodeType) {
223         QSGGeometryNode *g = static_cast<QSGGeometryNode *>(node);
224         Q_ASSERT_X(g->material(), "QSGNode::prependChildNode", "QSGGeometryNode is missing material");
225         Q_ASSERT_X(g->geometry(), "QSGNode::prependChildNode", "QSGGeometryNode is missing geometry");
226     }
227 #endif
228
229     if (m_firstChild)
230         m_firstChild->m_previousSibling = node;
231     else
232         m_lastChild = node;
233     node->m_nextSibling = m_firstChild;
234     m_firstChild = node;
235     node->m_parent = this;
236
237     node->markDirty(DirtyNodeAdded);
238 }
239
240 /*!
241     Appends \a node to this node's list of children.
242
243     Ordering of nodes is important as geometry nodes will be rendered in the
244     order they are added to the scene graph.
245  */
246
247 void QSGNode::appendChildNode(QSGNode *node)
248 {
249     //Q_ASSERT_X(!m_children.contains(node), "QSGNode::appendChildNode", "QSGNode is already a child!");
250     Q_ASSERT_X(!node->m_parent, "QSGNode::appendChildNode", "QSGNode already has a parent");
251
252 #ifndef QT_NO_DEBUG
253     if (node->type() == QSGNode::GeometryNodeType) {
254         QSGGeometryNode *g = static_cast<QSGGeometryNode *>(node);
255         Q_ASSERT_X(g->material(), "QSGNode::appendChildNode", "QSGGeometryNode is missing material");
256         Q_ASSERT_X(g->geometry(), "QSGNode::appendChildNode", "QSGGeometryNode is missing geometry");
257     }
258 #endif
259
260     if (m_lastChild)
261         m_lastChild->m_nextSibling = node;
262     else
263         m_firstChild = node;
264     node->m_previousSibling = m_lastChild;
265     m_lastChild = node;
266     node->m_parent = this;
267
268     node->markDirty(DirtyNodeAdded);
269 }
270
271
272
273 /*!
274     Inserts \a node to this node's list of children before the node specified with \a before.
275
276     Ordering of nodes is important as geometry nodes will be rendered in the
277     order they are added to the scene graph.
278  */
279
280 void QSGNode::insertChildNodeBefore(QSGNode *node, QSGNode *before)
281 {
282     //Q_ASSERT_X(!m_children.contains(node), "QSGNode::insertChildNodeBefore", "QSGNode is already a child!");
283     Q_ASSERT_X(!node->m_parent, "QSGNode::insertChildNodeBefore", "QSGNode already has a parent");
284     Q_ASSERT_X(before && before->m_parent == this, "QSGNode::insertChildNodeBefore", "The parent of \'before\' is wrong");
285
286 #ifndef QT_NO_DEBUG
287     if (node->type() == QSGNode::GeometryNodeType) {
288         QSGGeometryNode *g = static_cast<QSGGeometryNode *>(node);
289         Q_ASSERT_X(g->material(), "QSGNode::insertChildNodeBefore", "QSGGeometryNode is missing material");
290         Q_ASSERT_X(g->geometry(), "QSGNode::insertChildNodeBefore", "QSGGeometryNode is missing geometry");
291     }
292 #endif
293
294     QSGNode *previous = before->m_previousSibling;
295     if (previous)
296         previous->m_nextSibling = node;
297     else
298         m_firstChild = node;
299     node->m_previousSibling = previous;
300     node->m_nextSibling = before;
301     before->m_previousSibling = node;
302     node->m_parent = this;
303
304     node->markDirty(DirtyNodeAdded);
305 }
306
307
308
309 /*!
310     Inserts \a node to this node's list of children after the node specified with \a after.
311
312     Ordering of nodes is important as geometry nodes will be rendered in the
313     order they are added to the scene graph.
314  */
315
316 void QSGNode::insertChildNodeAfter(QSGNode *node, QSGNode *after)
317 {
318     //Q_ASSERT_X(!m_children.contains(node), "QSGNode::insertChildNodeAfter", "QSGNode is already a child!");
319     Q_ASSERT_X(!node->m_parent, "QSGNode::insertChildNodeAfter", "QSGNode already has a parent");
320     Q_ASSERT_X(after && after->m_parent == this, "QSGNode::insertChildNodeBefore", "The parent of \'before\' is wrong");
321
322 #ifndef QT_NO_DEBUG
323     if (node->type() == QSGNode::GeometryNodeType) {
324         QSGGeometryNode *g = static_cast<QSGGeometryNode *>(node);
325         Q_ASSERT_X(g->material(), "QSGNode::insertChildNodeAfter", "QSGGeometryNode is missing material");
326         Q_ASSERT_X(g->geometry(), "QSGNode::insertChildNodeAfter", "QSGGeometryNode is missing geometry");
327     }
328 #endif
329
330     QSGNode *next = after->m_nextSibling;
331     if (next)
332         next->m_previousSibling = node;
333     else
334         m_lastChild = node;
335     node->m_nextSibling = next;
336     node->m_previousSibling = after;
337     after->m_nextSibling = node;
338     node->m_parent = this;
339
340     node->markDirty(DirtyNodeAdded);
341 }
342
343
344
345 /*!
346     Removes \a node from this node's list of children.
347  */
348
349 void QSGNode::removeChildNode(QSGNode *node)
350 {
351     //Q_ASSERT(m_children.contains(node));
352     Q_ASSERT(node->parent() == this);
353
354     QSGNode *previous = node->m_previousSibling;
355     QSGNode *next = node->m_nextSibling;
356     if (previous)
357         previous->m_nextSibling = next;
358     else
359         m_firstChild = next;
360     if (next)
361         next->m_previousSibling = previous;
362     else
363         m_lastChild = previous;
364     node->m_previousSibling = 0;
365     node->m_nextSibling = 0;
366
367     node->markDirty(DirtyNodeRemoved);
368     node->m_parent = 0;
369 }
370
371
372 /*!
373     Removes all child nodes from this node's list of children.
374  */
375
376 void QSGNode::removeAllChildNodes()
377 {
378     while (m_firstChild) {
379         QSGNode *node = m_firstChild;
380         m_firstChild = node->m_nextSibling;
381         node->m_nextSibling = 0;
382         if (m_firstChild)
383             m_firstChild->m_previousSibling = 0;
384         else
385             m_lastChild = 0;
386         node->markDirty(DirtyNodeRemoved);
387         node->m_parent = 0;
388     }
389 }
390
391
392 int QSGNode::childCount() const
393 {
394     int count = 0;
395     QSGNode *n = m_firstChild;
396     while (n) {
397         ++count;
398         n = n->m_nextSibling;
399     }
400     return count;
401 }
402
403
404 QSGNode *QSGNode::childAtIndex(int i) const
405 {
406     QSGNode *n = m_firstChild;
407     while (i && n) {
408         --i;
409         n = n->m_nextSibling;
410     }
411     return n;
412 }
413
414
415 /*!
416     Sets the flag \a f on this node if \a enabled is true;
417     otherwise clears the flag.
418
419     \sa flags()
420 */
421
422 void QSGNode::setFlag(Flag f, bool enabled)
423 {
424     if (bool(m_nodeFlags & f) == enabled)
425         return;
426     m_nodeFlags ^= f;
427     Q_ASSERT(int(UsePreprocess) == int(DirtyUsePreprocess));
428     Q_ASSERT(int(ChildrenDoNotOverlap) == int(DirtyChildrenDoNotOverlap));
429     Q_ASSERT(int(StaticSubtreeGeometry) == int(DirtyStaticSubtreeGeometry));
430     int changedFlag = f & (UsePreprocess | ChildrenDoNotOverlap | StaticSubtreeGeometry);
431     if (changedFlag)
432         markDirty(DirtyState(changedFlag));
433 }
434
435
436 /*!
437     Sets the flags \a f on this node if \a enabled is true;
438     otherwise clears the flags.
439
440     \sa flags()
441 */
442
443 void QSGNode::setFlags(Flags f, bool enabled)
444 {
445     Flags oldFlags = m_nodeFlags;
446     if (enabled)
447         m_nodeFlags |= f;
448     else
449         m_nodeFlags &= ~f;
450     Q_ASSERT(int(UsePreprocess) == int(DirtyUsePreprocess));
451     Q_ASSERT(int(ChildrenDoNotOverlap) == int(DirtyChildrenDoNotOverlap));
452     Q_ASSERT(int(StaticSubtreeGeometry) == int(DirtyStaticSubtreeGeometry));
453     int changedFlags = (oldFlags ^ m_nodeFlags)
454                        & (UsePreprocess | ChildrenDoNotOverlap | StaticSubtreeGeometry);
455     if (changedFlags)
456         markDirty(DirtyState(changedFlags));
457 }
458
459
460
461 /*!
462     Marks this node with the states in \a flags as dirty.
463
464     When a node is marked dirty, it recursively mark the parent chain
465     as dirty and notify all connected renderers that the has dirty states.
466  */
467
468 void QSGNode::markDirty(DirtyState bits)
469 {
470     m_dirtyState |= (bits & DirtyPropagationMask);
471
472     DirtyState subtreeBits = DirtyState((bits & DirtyPropagationMask) << 16);
473
474     int geometryCountDiff = 0;
475     if (bits & DirtyNodeAdded)
476         geometryCountDiff += m_subtreeGeometryCount;
477     if (bits & DirtyNodeRemoved)
478         geometryCountDiff -= m_subtreeGeometryCount;
479
480     QSGNode *p = m_parent;
481     while (p) {
482         p->m_dirtyState |= subtreeBits;
483         p->m_subtreeGeometryCount += geometryCountDiff;
484         if (p->type() == RootNodeType)
485             static_cast<QSGRootNode *>(p)->notifyNodeChange(this, bits);
486         p = p->m_parent;
487     }
488 }
489
490
491
492 /*!
493     \class QSGBasicGeometryNode
494     \brief The QSGBasicGeometryNode class serves as a baseclass for geometry based nodes
495
496     \inmodule QtQuick
497
498     The QSGBasicGeometryNode class should not be used by itself. It is only encapsulates
499     shared functionality between the QSGGeometryNode and QSGClipNode classes.
500   */
501
502
503 /*!
504     Creates a new basic geometry node.
505  */
506 QSGBasicGeometryNode::QSGBasicGeometryNode(NodeType type)
507     : QSGNode(type)
508     , m_geometry(0)
509     , m_matrix(0)
510     , m_clip_list(0)
511 {
512 }
513
514
515 /*!
516     Deletes this QSGBasicGeometryNode.
517
518     If the node has the flag QSGNode::OwnsGeometry set, it will also delete the
519     geometry object it is pointing to. This flag is not set by default.
520   */
521
522 QSGBasicGeometryNode::~QSGBasicGeometryNode()
523 {
524     if (flags() & OwnsGeometry)
525         delete m_geometry;
526 }
527
528
529 /*!
530     \fn QSGGeometry *QSGBasicGeometryNode::geometry() const
531
532     Returns this node's geometry.
533
534     The geometry is null by default.
535  */
536
537
538 /*!
539     Sets the geometry of this node to \a geometry.
540
541     If the node has the flag QSGNode::OwnsGeometry set, it will also delete the
542     geometry object it is pointing to. This flag is not set by default.
543  */
544
545 void QSGBasicGeometryNode::setGeometry(QSGGeometry *geometry)
546 {
547     if (flags() & OwnsGeometry)
548         delete m_geometry;
549     m_geometry = geometry;
550     markDirty(DirtyGeometry);
551 }
552
553
554
555 /*!
556     \class QSGGeometryNode
557     \brief The QSGGeometryNode class is used for all rendered content in the scene graph.
558
559     \inmodule QtQuick
560
561     The QSGGeometryNode consists of geometry and material. The geometry defines the mesh,
562     the vertices and their structure, to be drawn. The Material defines how the shape is
563     filled.
564
565     A geometry node must have both geometry and a normal material before it is added to
566     the scene graph.
567
568     The geometry node supports two types of materials, the opaqueMaterial and the normal
569     material. The opaqueMaterial is used when the accumulated scene graph opacity at the
570     time of rendering is 1. The primary usecase is to special case opaque rendering
571     to avoid an extra operation in the fragment shader can have significant performance
572     impact on embedded graphics chips. The opaque material is optional.
573
574  */
575
576
577 /*!
578     Creates a new geometry node without geometry and material.
579  */
580
581 QSGGeometryNode::QSGGeometryNode()
582     : QSGBasicGeometryNode(GeometryNodeType)
583     , m_render_order(0)
584     , m_material(0)
585     , m_opaque_material(0)
586     , m_opacity(1)
587 {
588 }
589
590
591 /*!
592     Deletes this geometry node.
593
594     The flags QSGNode::OwnsMaterial, QSGNode::OwnsOpaqueMaterial and
595     QSGNode::OwnsGeometry decides weither the geometry node should also
596     delete the materials and geometry. By default, these flags are disabled.
597  */
598
599 QSGGeometryNode::~QSGGeometryNode()
600 {
601     if (flags() & OwnsMaterial)
602         delete m_material;
603     if (flags() & OwnsOpaqueMaterial)
604         delete m_opaque_material;
605 }
606
607
608
609 /*!
610     \fn int QSGGeometryNode::renderOrder() const
611
612     Returns the render order of this geometry node.
613
614     \internal
615  */
616
617
618 /*!
619     Sets the render order of this node to be \a order.
620
621     GeometryNodes are rendered in an order that visually looks like
622     low order nodes are rendered prior to high order nodes. For opaque
623     geometry there is little difference as z-testing will handle
624     the discard, but for translucent objects, the rendering should
625     normally be specified in the order of back-to-front.
626
627     The default render order is 0.
628
629     \internal
630   */
631 void QSGGeometryNode::setRenderOrder(int order)
632 {
633     m_render_order = order;
634 }
635
636
637
638 /*!
639     Sets the material of this geometry node to \a material.
640
641     Geometry nodes must have a material before they can be added to the
642     scene graph.
643  */
644 void QSGGeometryNode::setMaterial(QSGMaterial *material)
645 {
646     if (flags() & OwnsMaterial)
647         delete m_material;
648     m_material = material;
649 #ifndef QT_NO_DEBUG
650     if (m_material != 0 && m_opaque_material == m_material)
651         qWarning("QSGGeometryNode: using same material for both opaque and translucent");
652 #endif
653     markDirty(DirtyMaterial);
654 }
655
656
657
658 /*!
659     Sets the opaque material of this geometry to \a material.
660
661     The opaque material will be preferred by the renderer over the
662     default material, as returned by the material() function, if
663     it is not null and the geometry item has an inherited opacity of
664     1.
665
666     The opaqueness refers to scene graph opacity, the material is still
667     allowed to set QSGMaterial::Blending to true and draw transparent
668     pixels.
669  */
670 void QSGGeometryNode::setOpaqueMaterial(QSGMaterial *material)
671 {
672     if (flags() & OwnsOpaqueMaterial)
673         delete m_opaque_material;
674     m_opaque_material = material;
675 #ifndef QT_NO_DEBUG
676     if (m_opaque_material != 0 && m_opaque_material == m_material)
677         qWarning("QSGGeometryNode: using same material for both opaque and translucent");
678 #endif
679
680     markDirty(DirtyMaterial);
681 }
682
683
684
685 /*!
686     Returns the material which should currently be used for geometry node.
687
688     If the inherited opacity of the node is 1 and there is an opaque material
689     set on this node, it will be returned; otherwise, the default material
690     will be returned.
691
692     \warning This function requires the scene graph above this item to be
693     completely free of dirty states, so it can only be called during rendering
694
695     \internal
696
697     \sa setMaterial, setOpaqueMaterial
698  */
699 QSGMaterial *QSGGeometryNode::activeMaterial() const
700 {
701     Q_ASSERT_X(dirtyState() == 0, "QSGGeometryNode::activeMaterial()", "function assumes that all dirty states are cleaned up");
702     if (m_opaque_material && m_opacity > 0.999)
703         return m_opaque_material;
704     return m_material;
705 }
706
707
708 /*!
709     Sets the inherited opacity of this geometry to \a opacity.
710
711     This function is meant to be called by the node preprocessing
712     prior to rendering the tree, so it will not mark the tree as
713     dirty.
714
715     \internal
716   */
717 void QSGGeometryNode::setInheritedOpacity(qreal opacity)
718 {
719     Q_ASSERT(opacity >= 0 && opacity <= 1);
720     m_opacity = opacity;
721 }
722
723
724 /*!
725     \class QSGClipNode
726     \brief The QSGClipNode class implements the clipping functionality in the scene graph.
727
728     \inmodule QtQuick
729
730     Clipping applies to the node's subtree and can be nested. Multiple clip nodes will be
731     accumulated by intersecting all their geometries. The accumulation happens
732     as part of the rendering.
733
734     Clip nodes must have a geometry before they can be added to the scene graph.
735
736     Clipping is usually implemented by using the stencil buffer.
737  */
738
739
740
741 /*!
742     Creates a new QSGClipNode without a geometry.
743
744     The clip node must have a geometry before it can be added to the
745     scene graph.
746  */
747
748 QSGClipNode::QSGClipNode()
749     : QSGBasicGeometryNode(ClipNodeType)
750 {
751 }
752
753
754
755 /*!
756     Deletes this QSGClipNode.
757
758     If the flag QSGNode::OwnsGeometry is set, the geometry will also be
759     deleted.
760  */
761
762 QSGClipNode::~QSGClipNode()
763 {
764 }
765
766
767
768 /*!
769     \fn bool QSGClipNode::isRectangular() const
770
771     Returns if this clip node has a rectangular clip.
772  */
773
774
775
776 /*!
777     Sets whether this clip node has a rectangular clip to \a rectHint.
778
779     This is an optimization hint which means that the renderer can
780     use scissoring instead of stencil, which is significnatly faster.
781
782     When this hint is and it is applicable, the clip region will be
783     generated from clipRect() rather than geometry().
784  */
785
786 void QSGClipNode::setIsRectangular(bool rectHint)
787 {
788     m_is_rectangular = rectHint;
789 }
790
791
792
793 /*!
794     \fn void QSGClipNode::clipRect() const
795
796     Returns the clip rect of this node.
797  */
798
799
800 /*!
801     Sets the clip rect of this clip node to \a rect.
802
803     When a rectangular clip is set in combination with setIsRectangular
804     the renderer may in some cases use a more optimal clip method.
805  */
806 void QSGClipNode::setClipRect(const QRectF &rect)
807 {
808     m_clip_rect = rect;
809 }
810
811
812 /*!
813     \class QSGTransformNode
814     \brief The QSGTransformNode class implements transformations in the scene graph
815
816     \inmodule QtQuick
817
818     Transformations apply the node's subtree and can be nested. Multiple transform nodes
819     will be accumulated by intersecting all their matrices. The accumulation happens
820     as part of the rendering.
821
822     The transform nodes implement a 4x4 matrix which in theory supports full 3D
823     transformations. However, because the renderer optimizes for 2D use-cases rather
824     than 3D use-cases, rendering a scene with full 3D transformations needs to
825     be done with some care.
826  */
827
828 QSGTransformNode::QSGTransformNode()
829     : QSGNode(TransformNodeType)
830 {
831 }
832
833
834
835 /*!
836     Deletes this transform node.
837  */
838
839 QSGTransformNode::~QSGTransformNode()
840 {
841 }
842
843
844
845 /*!
846     \fn QMatrix4x4 QSGTransformNode::matrix() const
847
848     Returns this transform node's matrix.
849  */
850
851
852
853 /*!
854     Sets this transform node's matrix to \a matrix.
855  */
856
857 void QSGTransformNode::setMatrix(const QMatrix4x4 &matrix)
858 {
859     m_matrix = matrix;
860     markDirty(DirtyMatrix);
861 }
862
863
864 /*!
865     Sets the combined matrix of this matrix to \a transform.
866
867     This function is meant to be called by the node preprocessing
868     prior to rendering the tree, so it will not mark the tree as
869     dirty.
870
871     \internal
872   */
873 void QSGTransformNode::setCombinedMatrix(const QMatrix4x4 &matrix)
874 {
875     m_combined_matrix = matrix;
876 }
877
878
879
880 /*!
881     \class QSGRootNode
882     \brief The QSGRootNode is the toplevel root of any scene graph.
883
884     The root node is used to attach a scene graph to a renderer.
885
886     \internal
887  */
888
889
890
891 /*!
892     \fn QSGRootNode::QSGRootNode()
893
894     Creates a new root node.
895  */
896
897 QSGRootNode::QSGRootNode()
898     : QSGNode(RootNodeType)
899 {
900 }
901
902
903 /*!
904     Deletes the root node.
905
906     When a root node is deleted it removes itself from all of renderers
907     that are referencing it.
908  */
909
910 QSGRootNode::~QSGRootNode()
911 {
912     while (!m_renderers.isEmpty())
913         m_renderers.last()->setRootNode(0);
914     destroy(); // Must call destroy() here because markDirty() casts this to QSGRootNode.
915 }
916
917
918
919 /*!
920     Called to notify all renderers that \a node has been marked as dirty
921     with \a flags.
922  */
923
924 void QSGRootNode::notifyNodeChange(QSGNode *node, DirtyState state)
925 {
926     for (int i=0; i<m_renderers.size(); ++i) {
927         m_renderers.at(i)->nodeChanged(node, state);
928     }
929 }
930
931
932
933 /*!
934     \class QSGOpacityNode
935     \brief The QSGOpacityNode class is used to change opacity of nodes.
936
937     \inmodule QtQuick
938
939     Opacity applies to its subtree and can be nested. Multiple opacity nodes
940     will be accumulated by multiplying their opacity. The accumulation happens
941     as part of the rendering.
942
943     When nested opacity gets below a certain threshold, the subtree might
944     be marked as blocked, causing isSubtreeBlocked() to return true. This
945     is done for performance reasons.
946
947  */
948
949
950
951 /*!
952     Constructs an opacity node with a default opacity of 1.
953
954     Opacity accumulates downwards in the scene graph so a node with two
955     QSGOpacityNode instances above it, both with opacity of 0.5, will have
956     effective opacity of 0.25.
957
958     The default opacity of nodes is 1.
959   */
960 QSGOpacityNode::QSGOpacityNode()
961     : QSGNode(OpacityNodeType)
962     , m_opacity(1)
963     , m_combined_opacity(1)
964 {
965 }
966
967
968
969 /*!
970     Deletes the opacity node.
971  */
972
973 QSGOpacityNode::~QSGOpacityNode()
974 {
975 }
976
977
978
979 /*!
980     \fn qreal QSGOpacityNode::opacity() const
981
982     Returns this opacity node's opacity.
983  */
984
985
986
987 /*!
988     Sets the opacity of this node to \a opacity.
989
990     Before rendering the graph, the renderer will do an update pass
991     over the subtree to propegate the opacity to its children.
992
993     The value will be bounded to the range 0 to 1.
994  */
995
996 void QSGOpacityNode::setOpacity(qreal opacity)
997 {
998     opacity = qBound<qreal>(0, opacity, 1);
999     if (m_opacity == opacity)
1000         return;
1001     m_opacity = opacity;
1002     markDirty(DirtyOpacity);
1003 }
1004
1005
1006
1007 /*!
1008     \fn qreal QSGOpacityNode::combinedOpacity() const
1009
1010     Returns this node's accumulated opacity.
1011
1012     This vaule is calculated during rendering and only stored
1013     in the opacity node temporarily.
1014
1015     \internal
1016  */
1017
1018
1019
1020 /*!
1021     Sets the combined opacity of this node to \a opacity.
1022
1023     This function is meant to be called by the node preprocessing
1024     prior to rendering the tree, so it will not mark the tree as
1025     dirty.
1026
1027     \internal
1028  */
1029
1030 void QSGOpacityNode::setCombinedOpacity(qreal opacity)
1031 {
1032     m_combined_opacity = opacity;
1033 }
1034
1035
1036
1037 /*!
1038     For performance reasons, we block the subtree when the opacity
1039     is below a certain threshold.
1040
1041     \internal
1042  */
1043
1044 bool QSGOpacityNode::isSubtreeBlocked() const
1045 {
1046     return QSGNode::isSubtreeBlocked() || m_opacity < 0.001;
1047 }
1048
1049
1050 /*!
1051     \class QSGNodeVisitor
1052     \brief The QSGNodeVisitor class is a helper class for traversing the scene graph.
1053
1054     \internal
1055  */
1056
1057 QSGNodeVisitor::~QSGNodeVisitor()
1058 {
1059
1060 }
1061
1062
1063 void QSGNodeVisitor::visitNode(QSGNode *n)
1064 {
1065     switch (n->type()) {
1066     case QSGNode::TransformNodeType: {
1067         QSGTransformNode *t = static_cast<QSGTransformNode *>(n);
1068         enterTransformNode(t);
1069         visitChildren(t);
1070         leaveTransformNode(t);
1071         break; }
1072     case QSGNode::GeometryNodeType: {
1073         QSGGeometryNode *g = static_cast<QSGGeometryNode *>(n);
1074         enterGeometryNode(g);
1075         visitChildren(g);
1076         leaveGeometryNode(g);
1077         break; }
1078     case QSGNode::ClipNodeType: {
1079         QSGClipNode *c = static_cast<QSGClipNode *>(n);
1080         enterClipNode(c);
1081         visitChildren(c);
1082         leaveClipNode(c);
1083         break; }
1084     case QSGNode::OpacityNodeType: {
1085         QSGOpacityNode *o = static_cast<QSGOpacityNode *>(n);
1086         enterOpacityNode(o);
1087         visitChildren(o);
1088         leaveOpacityNode(o);
1089         break; }
1090     default:
1091         visitChildren(n);
1092         break;
1093     }
1094 }
1095
1096 void QSGNodeVisitor::visitChildren(QSGNode *n)
1097 {
1098     for (QSGNode *c = n->firstChild(); c; c = c->nextSibling())
1099         visitNode(c);
1100 }
1101
1102
1103
1104 #ifndef QT_NO_DEBUG_STREAM
1105 QDebug operator<<(QDebug d, const QSGGeometryNode *n)
1106 {
1107     if (!n) {
1108         d << "QSGGeometryNode(null)";
1109         return d;
1110     }
1111     d << "QSGGeometryNode(" << hex << (void *) n << dec;
1112
1113     const QSGGeometry *g = n->geometry();
1114
1115     if (!g) {
1116         d << "no geometry";
1117     } else {
1118
1119         switch (g->drawingMode()) {
1120         case GL_TRIANGLE_STRIP: d << "strip"; break;
1121         case GL_TRIANGLE_FAN: d << "fan"; break;
1122         case GL_TRIANGLES: d << "triangles"; break;
1123         default: break;
1124         }
1125
1126          d << g->vertexCount();
1127
1128          if (g->attributeCount() > 0 && g->attributes()->type == GL_FLOAT) {
1129              float x1 = 1e10, x2 = -1e10, y1=1e10, y2=-1e10;
1130              int stride = g->sizeOfVertex();
1131              for (int i = 0; i < g->vertexCount(); ++i) {
1132                  float x = ((float *)((char *)const_cast<QSGGeometry *>(g)->vertexData() + i * stride))[0];
1133                  float y = ((float *)((char *)const_cast<QSGGeometry *>(g)->vertexData() + i * stride))[1];
1134
1135                  x1 = qMin(x1, x);
1136                  x2 = qMax(x2, x);
1137                  y1 = qMin(y1, y);
1138                  y2 = qMax(y2, y);
1139              }
1140
1141              d << "x1=" << x1 << "y1=" << y1 << "x2=" << x2 << "y2=" << y2;
1142          }
1143     }
1144
1145     d << "order=" << n->renderOrder();
1146     if (n->material())
1147         d << "effect=" << n->material() << "type=" << n->material()->type();
1148
1149
1150     d << ")";
1151 #ifdef QML_RUNTIME_TESTING
1152     d << n->description;
1153 #endif
1154     d << "dirty=" << hex << (int) n->dirtyState() << dec;
1155     return d;
1156 }
1157
1158 QDebug operator<<(QDebug d, const QSGClipNode *n)
1159 {
1160     if (!n) {
1161         d << "QSGClipNode(null)";
1162         return d;
1163     }
1164     d << "QSGClipNode(" << hex << (void *) n << dec;
1165
1166     if (n->childCount())
1167         d << "children=" << n->childCount();
1168
1169     d << "is rect?" << (n->isRectangular() ? "yes" : "no");
1170
1171     d << ")";
1172 #ifdef QML_RUNTIME_TESTING
1173     d << n->description;
1174 #endif
1175     d << "dirty=" << hex << (int) n->dirtyState() << dec << (n->isSubtreeBlocked() ? "*BLOCKED*" : "");
1176     return d;
1177 }
1178
1179 QDebug operator<<(QDebug d, const QSGTransformNode *n)
1180 {
1181     if (!n) {
1182         d << "QSGTransformNode(null)";
1183         return d;
1184     }
1185     const QMatrix4x4 m = n->matrix();
1186     d << "QSGTransformNode(";
1187     d << hex << (void *) n << dec;
1188     if (m.isIdentity())
1189         d << "identity";
1190     else if (m.determinant() == 1 && m(0, 0) == 1 && m(1, 1) == 1 && m(2, 2) == 1)
1191         d << "translate" << m(0, 3) << m(1, 3) << m(2, 3);
1192     else
1193         d << "det=" << n->matrix().determinant();
1194 #ifdef QML_RUNTIME_TESTING
1195     d << n->description;
1196 #endif
1197     d << "dirty=" << hex << (int) n->dirtyState() << dec << (n->isSubtreeBlocked() ? "*BLOCKED*" : "");
1198     d << ")";
1199     return d;
1200 }
1201
1202 QDebug operator<<(QDebug d, const QSGOpacityNode *n)
1203 {
1204     if (!n) {
1205         d << "QSGOpacityNode(null)";
1206         return d;
1207     }
1208     d << "QSGOpacityNode(";
1209     d << hex << (void *) n << dec;
1210     d << "opacity=" << n->opacity()
1211       << "combined=" << n->combinedOpacity()
1212       << (n->isSubtreeBlocked() ? "*BLOCKED*" : "");
1213 #ifdef QML_RUNTIME_TESTING
1214     d << n->description;
1215 #endif
1216     d << "dirty=" << hex << (int) n->dirtyState() << dec;
1217     d << ")";
1218     return d;
1219 }
1220
1221
1222 QDebug operator<<(QDebug d, const QSGRootNode *n)
1223 {
1224     if (!n) {
1225         d << "QSGRootNode(null)";
1226         return d;
1227     }
1228     d << "QSGRootNode" << hex << (void *) n << "dirty=" << (int) n->dirtyState() << dec
1229       << (n->isSubtreeBlocked() ? "*BLOCKED*" : "");
1230 #ifdef QML_RUNTIME_TESTING
1231     d << n->description;
1232 #endif
1233     d << ")";
1234     return d;
1235 }
1236
1237
1238
1239 QDebug operator<<(QDebug d, const QSGNode *n)
1240 {
1241     if (!n) {
1242         d << "QSGNode(null)";
1243         return d;
1244     }
1245     switch (n->type()) {
1246     case QSGNode::GeometryNodeType:
1247         d << static_cast<const QSGGeometryNode *>(n);
1248         break;
1249     case QSGNode::TransformNodeType:
1250         d << static_cast<const QSGTransformNode *>(n);
1251         break;
1252     case QSGNode::ClipNodeType:
1253         d << static_cast<const QSGClipNode *>(n);
1254         break;
1255     case QSGNode::RootNodeType:
1256         d << static_cast<const QSGRootNode *>(n);
1257         break;
1258     case QSGNode::OpacityNodeType:
1259         d << static_cast<const QSGOpacityNode *>(n);
1260         break;
1261     default:
1262         d << "QSGNode(" << hex << (void *) n << dec
1263           << "dirty=" << hex << (int) n->dirtyState()
1264           << "flags=" << (int) n->flags() << dec
1265           << (n->isSubtreeBlocked() ? "*BLOCKED*" : "");
1266 #ifdef QML_RUNTIME_TESTING
1267         d << n->description;
1268 #endif
1269         d << ")";
1270         break;
1271     }
1272     return d;
1273 }
1274
1275 #endif
1276
1277 QT_END_NAMESPACE