1 /****************************************************************************
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qsgnodeupdater_p.h"
46 // #define QSG_UPDATER_DEBUG
48 QSGNodeUpdater::QSGNodeUpdater()
49 : m_combined_matrix_stack(64)
54 m_opacity_stack.add(1);
57 void QSGNodeUpdater::updateStates(QSGNode *n)
62 Q_ASSERT(m_opacity_stack.size() == 1); // The one we added in the constructr...
63 Q_ASSERT(m_combined_matrix_stack.isEmpty());
69 \fn void QSGNodeUpdater::setToplevelOpacity(qreal opacity)
71 Sets the toplevel opacity that will be multiplied with the
73 The default opacity is 1. Any other value will cause artifacts, and is
74 primarily useful for debug purposes.
76 The changing the value during an update pass will have undefined results
80 \fn qreal QSGNodeUpdater::toplevelOpacity() const
82 Returns the toplevel opacity for the node updater. The default
88 Returns true if \a node is has something that blocks it in the chain from
89 \a node to \a root doing a full state update pass.
91 This function does not process dirty states, simply does a simple traversion
94 The function assumes that \a root exists in the parent chain of \a node.
97 bool QSGNodeUpdater::isNodeBlocked(QSGNode *node, QSGNode *root) const
100 while (node != root) {
101 if (node->type() == QSGNode::OpacityNodeType) {
102 opacity *= static_cast<QSGOpacityNode *>(node)->opacity();
106 node = node->parent();
108 Q_ASSERT_X(node, "QSGNodeUpdater::isNodeBlocked", "node is not in the subtree of root");
115 void QSGNodeUpdater::enterTransformNode(QSGTransformNode *t)
117 if (t->dirtyState() & QSGNode::DirtyMatrix)
120 #ifdef QSG_UPDATER_DEBUG
121 qDebug() << "enter transform:" << t << "force=" << m_force_update;
124 if (!t->matrix().isIdentity()) {
125 if (!m_combined_matrix_stack.isEmpty()) {
126 t->setCombinedMatrix(*m_combined_matrix_stack.last() * t->matrix());
128 t->setCombinedMatrix(t->matrix());
130 m_combined_matrix_stack.add(&t->combinedMatrix());
132 if (!m_combined_matrix_stack.isEmpty()) {
133 t->setCombinedMatrix(*m_combined_matrix_stack.last());
135 t->setCombinedMatrix(QMatrix4x4());
141 void QSGNodeUpdater::leaveTransformNode(QSGTransformNode *t)
143 #ifdef QSG_UPDATER_DEBUG
144 qDebug() << "leave transform:" << t;
147 if (t->dirtyState() & QSGNode::DirtyMatrix)
150 if (!t->matrix().isIdentity()) {
151 m_combined_matrix_stack.pop_back();
157 void QSGNodeUpdater::enterClipNode(QSGClipNode *c)
159 #ifdef QSG_UPDATER_DEBUG
160 qDebug() << "enter clip:" << c;
163 if (c->dirtyState() & QSGNode::DirtyClipList)
166 c->m_matrix = m_combined_matrix_stack.isEmpty() ? 0 : m_combined_matrix_stack.last();
167 c->m_clip_list = m_current_clip;
172 void QSGNodeUpdater::leaveClipNode(QSGClipNode *c)
174 #ifdef QSG_UPDATER_DEBUG
175 qDebug() << "leave clip:" << c;
178 if (c->dirtyState() & QSGNode::DirtyClipList)
181 m_current_clip = c->m_clip_list;
185 void QSGNodeUpdater::enterGeometryNode(QSGGeometryNode *g)
187 #ifdef QSG_UPDATER_DEBUG
188 qDebug() << "enter geometry:" << g;
191 g->m_matrix = m_combined_matrix_stack.isEmpty() ? 0 : m_combined_matrix_stack.last();
192 g->m_clip_list = m_current_clip;
193 g->setInheritedOpacity(m_opacity_stack.last());
196 void QSGNodeUpdater::leaveGeometryNode(QSGGeometryNode *g)
198 #ifdef QSG_UPDATER_DEBUG
199 qDebug() << "leave geometry" << g;
205 void QSGNodeUpdater::enterOpacityNode(QSGOpacityNode *o)
207 if (o->dirtyState() & QSGNode::DirtyOpacity)
210 qreal opacity = m_opacity_stack.last() * o->opacity();
211 o->setCombinedOpacity(opacity);
212 m_opacity_stack.add(opacity);
214 #ifdef QSG_UPDATER_DEBUG
215 qDebug() << "enter opacity" << o;
219 void QSGNodeUpdater::leaveOpacityNode(QSGOpacityNode *o)
221 #ifdef QSG_UPDATER_DEBUG
222 qDebug() << "leave opacity" << o;
224 if (o->flags() & QSGNode::DirtyOpacity)
227 m_opacity_stack.pop_back();
230 void QSGNodeUpdater::visitChildren(QSGNode *n)
232 for (QSGNode *c = n->firstChild(); c; c = c->nextSibling())
236 void QSGNodeUpdater::visitNode(QSGNode *n)
238 #ifdef QSG_UPDATER_DEBUG
239 qDebug() << "enter:" << n;
242 if (!n->dirtyState() && !m_force_update)
244 if (n->isSubtreeBlocked())
247 bool forceUpdate = n->dirtyState() & (QSGNode::DirtyNodeAdded | QSGNode::DirtyForceUpdate);
252 case QSGNode::TransformNodeType: {
253 QSGTransformNode *t = static_cast<QSGTransformNode *>(n);
254 enterTransformNode(t);
256 leaveTransformNode(t);
258 case QSGNode::GeometryNodeType: {
259 QSGGeometryNode *g = static_cast<QSGGeometryNode *>(n);
260 enterGeometryNode(g);
262 leaveGeometryNode(g);
264 case QSGNode::ClipNodeType: {
265 QSGClipNode *c = static_cast<QSGClipNode *>(n);
270 case QSGNode::OpacityNodeType: {
271 QSGOpacityNode *o = static_cast<QSGOpacityNode *>(n);