diff options
Diffstat (limited to 'src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp')
-rw-r--r-- | src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp | 148 |
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); } } |