aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp')
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp148
1 files changed, 96 insertions, 52 deletions
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
index 525d702a76..d91004fbee 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
@@ -1,32 +1,39 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Copyright (C) 2014 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2016 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
+** Copyright (C) 2016 Robin Burchell <robin.burchell@viroteck.net>
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
@@ -83,7 +90,7 @@ DECLARE_DEBUG_VAR(noclip)
static QElapsedTimer qsg_renderer_timer;
#define QSGNODE_TRAVERSE(NODE) for (QSGNode *child = NODE->firstChild(); child; child = child->nextSibling())
-#define SHADOWNODE_TRAVERSE(NODE) for (QList<Node *>::const_iterator child = NODE->children.constBegin(); child != NODE->children.constEnd(); ++child)
+#define SHADOWNODE_TRAVERSE(NODE) for (Node *child = NODE->firstChild; child; child = child->nextSibling)
static inline int size_of_type(GLenum type)
{
@@ -248,7 +255,7 @@ void qsg_dumpShadowRoots(Node *n)
}
SHADOWNODE_TRAVERSE(n)
- qsg_dumpShadowRoots(*child);
+ qsg_dumpShadowRoots(child);
--indent;
#else
@@ -331,7 +338,7 @@ void Updater::visitNode(Node *n)
n->renderNodeElement()->root = m_roots.last();
// Fall through to visit children.
default:
- SHADOWNODE_TRAVERSE(n) visitNode(*child);
+ SHADOWNODE_TRAVERSE(n) visitNode(child);
break;
}
@@ -357,7 +364,7 @@ void Updater::visitClipNode(Node *n)
cn->m_matrix = &extra->matrix;
m_combined_matrix_stack << &m_identityMatrix;
- SHADOWNODE_TRAVERSE(n) visitNode(*child);
+ SHADOWNODE_TRAVERSE(n) visitNode(child);
m_current_clip = cn->m_clip_list;
m_rootMatrices.pop_back();
@@ -381,12 +388,12 @@ void Updater::visitOpacityNode(Node *n)
n->isOpaque = is;
}
++m_opacityChange;
- SHADOWNODE_TRAVERSE(n) visitNode(*child);
+ SHADOWNODE_TRAVERSE(n) visitNode(child);
--m_opacityChange;
} else {
if (m_added > 0)
n->isOpaque = on->opacity() > OPAQUE_LIMIT;
- SHADOWNODE_TRAVERSE(n) visitNode(*child);
+ SHADOWNODE_TRAVERSE(n) visitNode(child);
}
m_opacity_stack.pop_back();
@@ -436,7 +443,7 @@ void Updater::visitTransformNode(Node *n)
if (dirty)
++m_transformChange;
- SHADOWNODE_TRAVERSE(n) visitNode(*child);
+ SHADOWNODE_TRAVERSE(n) visitNode(child);
if (dirty)
--m_transformChange;
@@ -491,7 +498,7 @@ void Updater::visitGeometryNode(Node *n)
}
}
- SHADOWNODE_TRAVERSE(n) visitNode(*child);
+ SHADOWNODE_TRAVERSE(n) visitNode(child);
}
void Updater::updateRootTransforms(Node *node, Node *root, const QMatrix4x4 &combined)
@@ -586,13 +593,13 @@ void Element::computeBounds()
}
bounds.map(*node->matrix());
- if (!qIsFinite(bounds.tl.x) || bounds.tl.x == FLT_MAX)
+ if (!qt_is_finite(bounds.tl.x) || bounds.tl.x == FLT_MAX)
bounds.tl.x = -FLT_MAX;
- if (!qIsFinite(bounds.tl.y) || bounds.tl.y == FLT_MAX)
+ if (!qt_is_finite(bounds.tl.y) || bounds.tl.y == FLT_MAX)
bounds.tl.y = -FLT_MAX;
- if (!qIsFinite(bounds.br.x) || bounds.br.x == -FLT_MAX)
+ if (!qt_is_finite(bounds.br.x) || bounds.br.x == -FLT_MAX)
bounds.br.x = FLT_MAX;
- if (!qIsFinite(bounds.br.y) || bounds.br.y == -FLT_MAX)
+ if (!qt_is_finite(bounds.br.y) || bounds.br.y == -FLT_MAX)
bounds.br.y = FLT_MAX;
Q_ASSERT(bounds.tl.x <= bounds.br.x);
@@ -971,7 +978,7 @@ void Renderer::nodeChangedBatchRoot(Node *node, Node *root)
}
SHADOWNODE_TRAVERSE(node)
- nodeChangedBatchRoot(*child, root);
+ nodeChangedBatchRoot(child, root);
}
void Renderer::nodeWasTransformed(Node *node, int *vertexCount)
@@ -993,7 +1000,7 @@ void Renderer::nodeWasTransformed(Node *node, int *vertexCount)
}
SHADOWNODE_TRAVERSE(node)
- nodeWasTransformed(*child, vertexCount);
+ nodeWasTransformed(child, vertexCount);
}
void Renderer::nodeWasAdded(QSGNode *node, Node *shadowParent)
@@ -1007,7 +1014,13 @@ void Renderer::nodeWasAdded(QSGNode *node, Node *shadowParent)
m_nodes.insert(node, snode);
if (shadowParent) {
snode->parent = shadowParent;
- shadowParent->children.append(snode);
+ if (shadowParent->lastChild) {
+ shadowParent->lastChild->nextSibling = snode;
+ shadowParent->lastChild = snode;
+ } else {
+ shadowParent->firstChild = snode;
+ shadowParent->lastChild = snode;
+ }
}
if (node->type() == QSGNode::GeometryNodeType) {
@@ -1033,10 +1046,24 @@ void Renderer::nodeWasAdded(QSGNode *node, Node *shadowParent)
void Renderer::nodeWasRemoved(Node *node)
{
- // Prefix traversal as removeBatchFromParent below removes nodes
- // in a bottom-up manner
- SHADOWNODE_TRAVERSE(node)
- nodeWasRemoved(*child);
+ // Prefix traversal as removeBatchRootFromParent below removes nodes
+ // in a bottom-up manner. Note that we *cannot* use SHADOWNODE_TRAVERSE
+ // here, because we delete 'child' (when recursed, down below), so we'd
+ // have a use-after-free.
+ {
+ Node *child = node->firstChild;
+ Node *nextChild = 0;
+
+ while (child) {
+ // Get the next child now before we proceed
+ nextChild = child->nextSibling;
+
+ // Remove (and delete) child
+ nodeWasRemoved(child);
+
+ child = nextChild;
+ }
+ }
if (node->type() == QSGNode::GeometryNodeType) {
Element *e = node->element();
@@ -1100,7 +1127,7 @@ void Renderer::turnNodeIntoBatchRoot(Node *node)
}
SHADOWNODE_TRAVERSE(node)
- nodeChangedBatchRoot(*child, node);
+ nodeChangedBatchRoot(child, node);
}
@@ -1235,8 +1262,23 @@ void Renderer::nodeChanged(QSGNode *node, QSGNode::DirtyState state)
// Delete happens at the very end because it deletes the shadownode.
if (state & QSGNode::DirtyNodeRemoved) {
Node *parent = shadowNode->parent;
- if (parent)
- parent->children.removeOne(shadowNode);
+ if (parent) {
+ Q_ASSERT(parent->firstChild);
+ Q_ASSERT(parent->lastChild);
+ shadowNode->parent = 0;
+ Node *child = parent->firstChild;
+ if (child == shadowNode) {
+ parent->firstChild = shadowNode->nextSibling;
+ if (parent->lastChild == shadowNode)
+ parent->lastChild = 0;
+ } else {
+ while (child->nextSibling != shadowNode)
+ child = child->nextSibling;
+ child->nextSibling = shadowNode->nextSibling;
+ if (shadowNode == parent->lastChild)
+ parent->lastChild = child;
+ }
+ }
nodeWasRemoved(shadowNode);
Q_ASSERT(m_nodes.value(node) == 0);
}
@@ -1948,25 +1990,27 @@ void Renderer::uploadBatch(Batch *b)
vd += g->sizeOfVertex();
}
- const quint16 *id =
+ if (!b->drawSets.isEmpty()) {
+ const quint16 *id =
# ifdef QSG_SEPARATE_INDEX_BUFFER
(const quint16 *) (b->ibo.data);
# else
(const quint16 *) (b->vbo.data + b->drawSets.at(0).indices);
# endif
- {
- QDebug iDump = qDebug();
- iDump << " -- Index Data, count:" << b->indexCount;
- for (int i=0; i<b->indexCount; ++i) {
- if ((i % 24) == 0)
- iDump << endl << " --- ";
- iDump << id[i];
+ {
+ QDebug iDump = qDebug();
+ iDump << " -- Index Data, count:" << b->indexCount;
+ for (int i=0; i<b->indexCount; ++i) {
+ if ((i % 24) == 0)
+ iDump << endl << " --- ";
+ iDump << id[i];
+ }
}
- }
- for (int i=0; i<b->drawSets.size(); ++i) {
- const DrawSet &s = b->drawSets.at(i);
- qDebug() << " -- DrawSet: indexCount:" << s.indexCount << " vertices:" << s.vertices << " z:" << s.zorders << " indices:" << s.indices;
+ for (int i=0; i<b->drawSets.size(); ++i) {
+ const DrawSet &s = b->drawSets.at(i);
+ qDebug() << " -- DrawSet: indexCount:" << s.indexCount << " vertices:" << s.vertices << " z:" << s.zorders << " indices:" << s.indices;
+ }
}
}
#endif // QT_NO_DEBUG_OUTPUT
@@ -2924,7 +2968,7 @@ void Renderer::visualizeChangesPrepare(Node *n, uint parentChanges)
if (n->type() == QSGNode::GeometryNodeType && selfDirty != 0)
m_visualizeChanceSet.insert(n, selfDirty);
SHADOWNODE_TRAVERSE(n) {
- visualizeChangesPrepare(*child, childDirty);
+ visualizeChangesPrepare(child, childDirty);
}
}
@@ -2960,7 +3004,7 @@ void Renderer::visualizeChanges(Node *n)
}
SHADOWNODE_TRAVERSE(n) {
- visualizeChanges(*child);
+ visualizeChanges(child);
}
}
@@ -2987,7 +3031,7 @@ void Renderer::visualizeOverdraw_helper(Node *node)
}
SHADOWNODE_TRAVERSE(node) {
- visualizeOverdraw_helper(*child);
+ visualizeOverdraw_helper(child);
}
}