diff options
-rw-r--r-- | src/quick/items/qquickcanvas.cpp | 5 | ||||
-rw-r--r-- | src/quick/items/qquickitem.cpp | 2 | ||||
-rw-r--r-- | src/quick/items/qquickitem_p.h | 3 | ||||
-rw-r--r-- | src/quick/scenegraph/coreapi/qsgdefaultrenderer.cpp | 14 | ||||
-rw-r--r-- | src/quick/scenegraph/coreapi/qsgdefaultrenderer_p.h | 2 | ||||
-rw-r--r-- | src/quick/scenegraph/coreapi/qsgnode.cpp | 57 | ||||
-rw-r--r-- | src/quick/scenegraph/coreapi/qsgnode.h | 55 | ||||
-rw-r--r-- | src/quick/scenegraph/coreapi/qsgnodeupdater.cpp | 14 | ||||
-rw-r--r-- | src/quick/scenegraph/coreapi/qsgrenderer.cpp | 15 | ||||
-rw-r--r-- | src/quick/scenegraph/coreapi/qsgrenderer_p.h | 2 | ||||
-rw-r--r-- | tests/auto/qtquick2/nodes/tst_nodestest.cpp | 16 |
11 files changed, 108 insertions, 77 deletions
diff --git a/src/quick/items/qquickcanvas.cpp b/src/quick/items/qquickcanvas.cpp index 432d167864..596db6c03e 100644 --- a/src/quick/items/qquickcanvas.cpp +++ b/src/quick/items/qquickcanvas.cpp @@ -1610,6 +1610,11 @@ void QQuickCanvasPrivate::updateDirtyNode(QQuickItem *item) } } + if ((dirty & QQuickItemPrivate::PerformanceHints) && itemPriv->groupNode) { + itemPriv->groupNode->setFlag(QSGNode::ChildrenDoNotOverlap, itemPriv->childrenDoNotOverlap); + itemPriv->groupNode->setFlag(QSGNode::StaticSubtreeGeometry, itemPriv->staticSubtreeGeometry); + } + #ifndef QT_NO_DEBUG // Check consistency. const QSGNode *nodeChain[] = { diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 8f58c33613..008ac961ba 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -2250,6 +2250,7 @@ QQuickItemPrivate::QQuickItemPrivate() effectiveVisible(true), explicitEnable(true), effectiveEnable(true), polishScheduled(false), inheritedLayoutMirror(false), effectiveLayoutMirror(false), isMirrorImplicit(true), inheritMirrorFromParent(false), inheritMirrorFromItem(false), childrenDoNotOverlap(false), + staticSubtreeGeometry(false), canvas(0), parentItem(0), sortedChildItems(&childItems), @@ -3960,6 +3961,7 @@ QString QQuickItemPrivate::dirtyToString() const DIRTY_TO_STRING(EffectReference); DIRTY_TO_STRING(Visible); DIRTY_TO_STRING(HideReference); + DIRTY_TO_STRING(PerformanceHints); return rv; } diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h index e9c9498c44..6ed4a694a7 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -279,6 +279,7 @@ public: bool inheritMirrorFromParent:1; bool inheritMirrorFromItem:1; bool childrenDoNotOverlap:1; + bool staticSubtreeGeometry:1; QQuickCanvas *canvas; QSGContext *sceneGraphContext() const { Q_ASSERT(canvas); return static_cast<QQuickCanvasPrivate *>(QObjectPrivate::get(canvas))->context; } @@ -396,6 +397,7 @@ public: EffectReference = 0x00008000, Visible = 0x00010000, HideReference = 0x00020000, + PerformanceHints = 0x00040000, // When you add an attribute here, don't forget to update // dirtyToString() @@ -738,6 +740,7 @@ QSGNode *QQuickItemPrivate::childContainerNode() else itemNode()->appendChildNode(groupNode); groupNode->setFlag(QSGNode::ChildrenDoNotOverlap, childrenDoNotOverlap); + groupNode->setFlag(QSGNode::StaticSubtreeGeometry, staticSubtreeGeometry); #ifdef QML_RUNTIME_TESTING groupNode->description = QLatin1String("group"); #endif diff --git a/src/quick/scenegraph/coreapi/qsgdefaultrenderer.cpp b/src/quick/scenegraph/coreapi/qsgdefaultrenderer.cpp index 56a6e0e5d9..0bed1b8683 100644 --- a/src/quick/scenegraph/coreapi/qsgdefaultrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgdefaultrenderer.cpp @@ -175,18 +175,18 @@ QSGDefaultRenderer::QSGDefaultRenderer(QSGContext *context) #endif } -void QSGDefaultRenderer::nodeChanged(QSGNode *node, QSGNode::DirtyFlags flags) +void QSGDefaultRenderer::nodeChanged(QSGNode *node, QSGNode::DirtyState state) { - QSGRenderer::nodeChanged(node, flags); + QSGRenderer::nodeChanged(node, state); - quint32 rebuildFlags = QSGNode::DirtyNodeAdded | QSGNode::DirtyNodeRemoved - | QSGNode::DirtyMaterial | QSGNode::DirtyOpacity - | QSGNode::DirtyForceUpdate; + const quint32 rebuildBits = QSGNode::DirtyNodeAdded | QSGNode::DirtyNodeRemoved + | QSGNode::DirtyMaterial | QSGNode::DirtyOpacity + | QSGNode::DirtyForceUpdate | QSGNode::DirtyChildrenDoNotOverlap; - if (flags & rebuildFlags) + if (state & rebuildBits) m_rebuild_lists = true; - if (flags & (rebuildFlags | QSGNode::DirtyClipList)) + if (state & (rebuildBits | QSGNode::DirtyClipList)) m_needs_sorting = true; } diff --git a/src/quick/scenegraph/coreapi/qsgdefaultrenderer_p.h b/src/quick/scenegraph/coreapi/qsgdefaultrenderer_p.h index a4c2ffbdbc..7bbac40f84 100644 --- a/src/quick/scenegraph/coreapi/qsgdefaultrenderer_p.h +++ b/src/quick/scenegraph/coreapi/qsgdefaultrenderer_p.h @@ -82,7 +82,7 @@ public: void render(); - void nodeChanged(QSGNode *node, QSGNode::DirtyFlags flags); + void nodeChanged(QSGNode *node, QSGNode::DirtyState state); void setSortFrontToBackEnabled(bool sort); bool isSortFrontToBackEnabled() const; diff --git a/src/quick/scenegraph/coreapi/qsgnode.cpp b/src/quick/scenegraph/coreapi/qsgnode.cpp index 2d6828323c..bc83a81b48 100644 --- a/src/quick/scenegraph/coreapi/qsgnode.cpp +++ b/src/quick/scenegraph/coreapi/qsgnode.cpp @@ -92,7 +92,7 @@ QSGNode::QSGNode() , m_previousSibling(0) , m_subtreeGeometryCount(0) , m_nodeFlags(OwnedByParent) - , m_flags(0) + , m_dirtyState(0) { init(); } @@ -106,7 +106,7 @@ QSGNode::QSGNode(NodeType type) , m_previousSibling(0) , m_subtreeGeometryCount(type == GeometryNodeType ? 1 : 0) , m_nodeFlags(OwnedByParent) - , m_flags(0) + , m_dirtyState(0) { init(); } @@ -421,10 +421,15 @@ QSGNode *QSGNode::childAtIndex(int i) const void QSGNode::setFlag(Flag f, bool enabled) { - if (enabled) - m_nodeFlags |= f; - else - m_nodeFlags &= ~f; + if (bool(m_nodeFlags & f) == enabled) + return; + m_nodeFlags ^= f; + Q_ASSERT(int(UsePreprocess) == int(DirtyUsePreprocess)); + Q_ASSERT(int(ChildrenDoNotOverlap) == int(DirtyChildrenDoNotOverlap)); + Q_ASSERT(int(StaticSubtreeGeometry) == int(DirtyStaticSubtreeGeometry)); + int changedFlag = f & (UsePreprocess | ChildrenDoNotOverlap | StaticSubtreeGeometry); + if (changedFlag) + markDirty(DirtyState(changedFlag)); } @@ -437,10 +442,18 @@ void QSGNode::setFlag(Flag f, bool enabled) void QSGNode::setFlags(Flags f, bool enabled) { + Flags oldFlags = m_nodeFlags; if (enabled) m_nodeFlags |= f; else m_nodeFlags &= ~f; + Q_ASSERT(int(UsePreprocess) == int(DirtyUsePreprocess)); + Q_ASSERT(int(ChildrenDoNotOverlap) == int(DirtyChildrenDoNotOverlap)); + Q_ASSERT(int(StaticSubtreeGeometry) == int(DirtyStaticSubtreeGeometry)); + int changedFlags = (oldFlags ^ m_nodeFlags) + & (UsePreprocess | ChildrenDoNotOverlap | StaticSubtreeGeometry); + if (changedFlags) + markDirty(DirtyState(changedFlags)); } @@ -452,24 +465,24 @@ void QSGNode::setFlags(Flags f, bool enabled) as dirty and notify all connected renderers that the has dirty states. */ -void QSGNode::markDirty(DirtyFlags flags) +void QSGNode::markDirty(DirtyState bits) { - m_flags |= (flags & DirtyPropagationMask); + m_dirtyState |= (bits & DirtyPropagationMask); - DirtyFlags subtreeFlags = DirtyFlags((flags & DirtyPropagationMask) << 16); + DirtyState subtreeBits = DirtyState((bits & DirtyPropagationMask) << 16); int geometryCountDiff = 0; - if (flags & DirtyNodeAdded) + if (bits & DirtyNodeAdded) geometryCountDiff += m_subtreeGeometryCount; - if (flags & DirtyNodeRemoved) + if (bits & DirtyNodeRemoved) geometryCountDiff -= m_subtreeGeometryCount; QSGNode *p = m_parent; while (p) { - p->m_flags |= subtreeFlags; + p->m_dirtyState |= subtreeBits; p->m_subtreeGeometryCount += geometryCountDiff; if (p->type() == RootNodeType) - static_cast<QSGRootNode *>(p)->notifyNodeChange(this, flags); + static_cast<QSGRootNode *>(p)->notifyNodeChange(this, bits); p = p->m_parent; } } @@ -685,7 +698,7 @@ void QSGGeometryNode::setOpaqueMaterial(QSGMaterial *material) */ QSGMaterial *QSGGeometryNode::activeMaterial() const { - Q_ASSERT_X(dirtyFlags() == 0, "QSGGeometryNode::activeMaterial()", "function assumes that all dirty states are cleaned up"); + Q_ASSERT_X(dirtyState() == 0, "QSGGeometryNode::activeMaterial()", "function assumes that all dirty states are cleaned up"); if (m_opaque_material && m_opacity > 0.999) return m_opaque_material; return m_material; @@ -908,10 +921,10 @@ QSGRootNode::~QSGRootNode() with \a flags. */ -void QSGRootNode::notifyNodeChange(QSGNode *node, DirtyFlags flags) +void QSGRootNode::notifyNodeChange(QSGNode *node, DirtyState state) { for (int i=0; i<m_renderers.size(); ++i) { - m_renderers.at(i)->nodeChanged(node, flags); + m_renderers.at(i)->nodeChanged(node, state); } } @@ -1138,7 +1151,7 @@ QDebug operator<<(QDebug d, const QSGGeometryNode *n) #ifdef QML_RUNTIME_TESTING d << n->description; #endif - d << "dirty=" << hex << (int) n->dirtyFlags() << dec; + d << "dirty=" << hex << (int) n->dirtyState() << dec; return d; } @@ -1159,7 +1172,7 @@ QDebug operator<<(QDebug d, const QSGClipNode *n) #ifdef QML_RUNTIME_TESTING d << n->description; #endif - d << "dirty=" << hex << (int) n->dirtyFlags() << dec << (n->isSubtreeBlocked() ? "*BLOCKED*" : ""); + d << "dirty=" << hex << (int) n->dirtyState() << dec << (n->isSubtreeBlocked() ? "*BLOCKED*" : ""); return d; } @@ -1181,7 +1194,7 @@ QDebug operator<<(QDebug d, const QSGTransformNode *n) #ifdef QML_RUNTIME_TESTING d << n->description; #endif - d << "dirty=" << hex << (int) n->dirtyFlags() << dec << (n->isSubtreeBlocked() ? "*BLOCKED*" : ""); + d << "dirty=" << hex << (int) n->dirtyState() << dec << (n->isSubtreeBlocked() ? "*BLOCKED*" : ""); d << ")"; return d; } @@ -1200,7 +1213,7 @@ QDebug operator<<(QDebug d, const QSGOpacityNode *n) #ifdef QML_RUNTIME_TESTING d << n->description; #endif - d << "dirty=" << hex << (int) n->dirtyFlags() << dec; + d << "dirty=" << hex << (int) n->dirtyState() << dec; d << ")"; return d; } @@ -1212,7 +1225,7 @@ QDebug operator<<(QDebug d, const QSGRootNode *n) d << "QSGRootNode(null)"; return d; } - d << "QSGRootNode" << hex << (void *) n << "dirty=" << (int) n->dirtyFlags() << dec + d << "QSGRootNode" << hex << (void *) n << "dirty=" << (int) n->dirtyState() << dec << (n->isSubtreeBlocked() ? "*BLOCKED*" : ""); #ifdef QML_RUNTIME_TESTING d << n->description; @@ -1247,7 +1260,7 @@ QDebug operator<<(QDebug d, const QSGNode *n) break; default: d << "QSGNode(" << hex << (void *) n << dec - << "dirty=" << hex << (int) n->dirtyFlags() + << "dirty=" << hex << (int) n->dirtyState() << "flags=" << (int) n->flags() << dec << (n->isSubtreeBlocked() ? "*BLOCKED*" : ""); #ifdef QML_RUNTIME_TESTING diff --git a/src/quick/scenegraph/coreapi/qsgnode.h b/src/quick/scenegraph/coreapi/qsgnode.h index 41c63e27b6..54e50e48be 100644 --- a/src/quick/scenegraph/coreapi/qsgnode.h +++ b/src/quick/scenegraph/coreapi/qsgnode.h @@ -74,30 +74,12 @@ public: UserNodeType = 1024 }; - enum DirtyFlag { - DirtyMatrix = 0x0001, - DirtyClipList = 0x0002, - DirtyNodeAdded = 0x0004, - DirtyNodeRemoved = 0x0008, - DirtyGeometry = 0x0010, - DirtyMaterial = 0x0040, - DirtyOpacity = 0x0080, - DirtyForceUpdate = 0x0100, - - DirtyPropagationMask = DirtyMatrix - | DirtyClipList - | DirtyNodeAdded - | DirtyOpacity - | DirtyForceUpdate - - }; - Q_DECLARE_FLAGS(DirtyFlags, DirtyFlag) - enum Flag { // Lower 16 bites reserved for general node OwnedByParent = 0x0001, UsePreprocess = 0x0002, ChildrenDoNotOverlap = 0x0004, + StaticSubtreeGeometry = 0x0008, // Subtree nodes have fixed matrix and vertex data. // Upper 16 bits reserved for node subclasses @@ -108,6 +90,29 @@ public: }; Q_DECLARE_FLAGS(Flags, Flag) + enum DirtyStateBit { + DirtyUsePreprocess = UsePreprocess, + DirtyChildrenDoNotOverlap = ChildrenDoNotOverlap, + DirtyStaticSubtreeGeometry = StaticSubtreeGeometry, + + DirtyMatrix = 0x0100, + DirtyClipList = 0x0200, + DirtyNodeAdded = 0x0400, + DirtyNodeRemoved = 0x0800, + DirtyGeometry = 0x1000, + DirtyMaterial = 0x2000, + DirtyOpacity = 0x4000, + DirtyForceUpdate = 0x8000, + + DirtyPropagationMask = DirtyMatrix + | DirtyClipList + | DirtyNodeAdded + | DirtyOpacity + | DirtyForceUpdate + + }; + Q_DECLARE_FLAGS(DirtyState, DirtyStateBit) + QSGNode(); virtual ~QSGNode(); @@ -129,9 +134,9 @@ public: inline NodeType type() const { return m_type; } - void clearDirty() { m_flags = 0; } - void markDirty(DirtyFlags flags); - DirtyFlags dirtyFlags() const { return m_flags; } + void clearDirty() { m_dirtyState = 0; } + void markDirty(DirtyState bits); + DirtyState dirtyState() const { return m_dirtyState; } virtual bool isSubtreeBlocked() const; @@ -163,12 +168,12 @@ private: int m_subtreeGeometryCount; Flags m_nodeFlags; - DirtyFlags m_flags; + DirtyState m_dirtyState; void *m_reserved; }; -Q_DECLARE_OPERATORS_FOR_FLAGS(QSGNode::DirtyFlags) +Q_DECLARE_OPERATORS_FOR_FLAGS(QSGNode::DirtyState) Q_DECLARE_OPERATORS_FOR_FLAGS(QSGNode::Flags) class Q_QUICK_EXPORT QSGBasicGeometryNode : public QSGNode @@ -284,7 +289,7 @@ public: ~QSGRootNode(); private: - void notifyNodeChange(QSGNode *node, DirtyFlags flags); + void notifyNodeChange(QSGNode *node, DirtyState state); friend class QSGRenderer; friend class QSGNode; diff --git a/src/quick/scenegraph/coreapi/qsgnodeupdater.cpp b/src/quick/scenegraph/coreapi/qsgnodeupdater.cpp index a7e5b08dc1..c5fa656c71 100644 --- a/src/quick/scenegraph/coreapi/qsgnodeupdater.cpp +++ b/src/quick/scenegraph/coreapi/qsgnodeupdater.cpp @@ -114,7 +114,7 @@ bool QSGNodeUpdater::isNodeBlocked(QSGNode *node, QSGNode *root) const void QSGNodeUpdater::enterTransformNode(QSGTransformNode *t) { - if (t->dirtyFlags() & QSGNode::DirtyMatrix) + if (t->dirtyState() & QSGNode::DirtyMatrix) ++m_force_update; #ifdef QSG_UPDATER_DEBUG @@ -144,7 +144,7 @@ void QSGNodeUpdater::leaveTransformNode(QSGTransformNode *t) qDebug() << "leave transform:" << t; #endif - if (t->dirtyFlags() & QSGNode::DirtyMatrix) + if (t->dirtyState() & QSGNode::DirtyMatrix) --m_force_update; if (!t->matrix().isIdentity()) { @@ -160,7 +160,7 @@ void QSGNodeUpdater::enterClipNode(QSGClipNode *c) qDebug() << "enter clip:" << c; #endif - if (c->dirtyFlags() & QSGNode::DirtyClipList) + if (c->dirtyState() & QSGNode::DirtyClipList) ++m_force_update; c->m_matrix = m_combined_matrix_stack.isEmpty() ? 0 : m_combined_matrix_stack.last(); @@ -175,7 +175,7 @@ void QSGNodeUpdater::leaveClipNode(QSGClipNode *c) qDebug() << "leave clip:" << c; #endif - if (c->dirtyFlags() & QSGNode::DirtyClipList) + if (c->dirtyState() & QSGNode::DirtyClipList) --m_force_update; m_current_clip = c->m_clip_list; @@ -204,7 +204,7 @@ void QSGNodeUpdater::leaveGeometryNode(QSGGeometryNode *g) void QSGNodeUpdater::enterOpacityNode(QSGOpacityNode *o) { - if (o->dirtyFlags() & QSGNode::DirtyOpacity) + if (o->dirtyState() & QSGNode::DirtyOpacity) ++m_force_update; qreal opacity = m_opacity_stack.last() * o->opacity(); @@ -239,12 +239,12 @@ void QSGNodeUpdater::visitNode(QSGNode *n) qDebug() << "enter:" << n; #endif - if (!n->dirtyFlags() && !m_force_update) + if (!n->dirtyState() && !m_force_update) return; if (n->isSubtreeBlocked()) return; - bool forceUpdate = n->dirtyFlags() & (QSGNode::DirtyNodeAdded | QSGNode::DirtyForceUpdate); + bool forceUpdate = n->dirtyState() & (QSGNode::DirtyNodeAdded | QSGNode::DirtyForceUpdate); if (forceUpdate) ++m_force_update; diff --git a/src/quick/scenegraph/coreapi/qsgrenderer.cpp b/src/quick/scenegraph/coreapi/qsgrenderer.cpp index b22631afae..1b4f5da435 100644 --- a/src/quick/scenegraph/coreapi/qsgrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgrenderer.cpp @@ -325,15 +325,18 @@ void QSGRenderer::setClearColor(const QColor &color) pointer. */ -void QSGRenderer::nodeChanged(QSGNode *node, QSGNode::DirtyFlags flags) +void QSGRenderer::nodeChanged(QSGNode *node, QSGNode::DirtyState state) { - Q_UNUSED(node); - Q_UNUSED(flags); - - if (flags & QSGNode::DirtyNodeAdded) + if (state & QSGNode::DirtyNodeAdded) addNodesToPreprocess(node); - if (flags & QSGNode::DirtyNodeRemoved) + if (state & QSGNode::DirtyNodeRemoved) removeNodesToPreprocess(node); + if (state & QSGNode::DirtyUsePreprocess) { + if (node->flags() & QSGNode::UsePreprocess) + m_nodes_to_preprocess.insert(node); + else + m_nodes_to_preprocess.remove(node); + } if (!m_changed_emitted && !m_is_rendering) { // Premature overoptimization to avoid excessive signal emissions diff --git a/src/quick/scenegraph/coreapi/qsgrenderer_p.h b/src/quick/scenegraph/coreapi/qsgrenderer_p.h index e5667c710a..5217bee205 100644 --- a/src/quick/scenegraph/coreapi/qsgrenderer_p.h +++ b/src/quick/scenegraph/coreapi/qsgrenderer_p.h @@ -120,7 +120,7 @@ public: void renderScene(); void renderScene(const QSGBindable &bindable); - virtual void nodeChanged(QSGNode *node, QSGNode::DirtyFlags flags); + virtual void nodeChanged(QSGNode *node, QSGNode::DirtyState state); virtual void materialChanged(QSGGeometryNode *node, QSGMaterial *from, QSGMaterial *to); QSGNodeUpdater *nodeUpdater() const; diff --git a/tests/auto/qtquick2/nodes/tst_nodestest.cpp b/tests/auto/qtquick2/nodes/tst_nodestest.cpp index 3036bbf2dd..7aaff3fe91 100644 --- a/tests/auto/qtquick2/nodes/tst_nodestest.cpp +++ b/tests/auto/qtquick2/nodes/tst_nodestest.cpp @@ -93,7 +93,7 @@ public: DummyRenderer(QSGRootNode *root) : QSGRenderer(QSGContext::createDefaultContext()) , changedNode(0) - , changedFlags(0) + , changedState(0) , renderCount(0) { setRootNode(root); @@ -104,14 +104,14 @@ public: renderingOrder = ++globalRendereringOrder; } - void nodeChanged(QSGNode *node, QSGNode::DirtyFlags flags) { + void nodeChanged(QSGNode *node, QSGNode::DirtyState state) { changedNode = node; - changedFlags = flags; - QSGRenderer::nodeChanged(node, flags); + changedState = state; + QSGRenderer::nodeChanged(node, state); } QSGNode *changedNode; - QSGNode::DirtyFlags changedFlags; + QSGNode::DirtyState changedState; int renderCount; int renderingOrder; @@ -136,7 +136,7 @@ void NodesTest::propegate() child.markDirty(QSGNode::DirtyGeometry); QCOMPARE(&child, renderer.changedNode); - QCOMPARE((int) renderer.changedFlags, (int) QSGNode::DirtyGeometry); + QCOMPARE((int) renderer.changedState, (int) QSGNode::DirtyGeometry); } @@ -159,8 +159,8 @@ void NodesTest::propegateWithMultipleRoots() QCOMPARE(ren1.changedNode, &child4); QCOMPARE(ren2.changedNode, &child4); - QCOMPARE((int) ren1.changedFlags, (int) QSGNode::DirtyGeometry); - QCOMPARE((int) ren2.changedFlags, (int) QSGNode::DirtyGeometry); + QCOMPARE((int) ren1.changedState, (int) QSGNode::DirtyGeometry); + QCOMPARE((int) ren2.changedState, (int) QSGNode::DirtyGeometry); } |