diff options
author | Robin Burchell <robin.burchell@crimson.no> | 2022-10-26 17:55:33 +0200 |
---|---|---|
committer | Robin Burchell <robin.burchell@crimson.no> | 2022-11-01 16:40:31 +0200 |
commit | a9900e9f30fa5f6c943a7c363d57c0d9d748b92f (patch) | |
tree | 2c469a2e9039b23f80f01fc389bd1a342a75c440 /src/quick/items/qquickwindow.cpp | |
parent | e3a8d8136706c9c50d76a39b72ab90cced34cca7 (diff) |
QQuickWindow: Avoid shuffling around QSGNodes more than necessary
This optimization should help performance of the common cases
quite significantly, as entire subtrees of the scenegraph are no longer
shuffled around as much for no reason.
While the changes may look trivial, it's especially important to note that
changing children will likely need to recursively mark nodes in the
scenegraph backend, so the more expensive the subtree, the worse
the impact of this would have been - and the effects may have been quite
subtle (e.g. a lot of useless extra work, partial repaints not working, etc).
After this patch, the relevant tests in qmlbench change as follows:
auto/changes/set_visible_in_long_tree_begin.qml +25%
auto/changes/set_visible_in_long_tree_middle.qml +15%
auto/changes/set_visible_in_long_tree_end.qml +0.4% (insignificant)
The edge cases for child changes (e.g. altering many children rather
than one at a time, or reshuffling the tree due to z order changes)
are still not very well optimized.
Improvement for those cases are left as an exercise for the reader, but
should at least work as well as they did before.
Change-Id: I556f6270f81579e88be53880e532f06ad18bf2f9
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
Diffstat (limited to 'src/quick/items/qquickwindow.cpp')
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 25 |
1 files changed, 15 insertions, 10 deletions
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index e9272c164a..d3bab7eea5 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -2046,18 +2046,23 @@ void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item) QSGNode *desiredNode = nullptr; while (currentNode && (desiredNode = fetchNextNode(itemPriv, ii, fetchedPaintNode))) { - // uh oh... reality and our utopic paradise are diverging! - // we need to reconcile this... if (currentNode != desiredNode) { - // for now, we're just removing the node from the children - - // and replacing it with the new node. - if (desiredNode->parent()) - desiredNode->parent()->removeChildNode(desiredNode); - groupNode->insertChildNodeAfter(desiredNode, currentNode); - groupNode->removeChildNode(currentNode); + // uh oh... reality and our utopic paradise are diverging! + // we need to reconcile this... + if (currentNode->nextSibling() == desiredNode) { + // nice and simple: a node was removed, and the next in line is correct. + groupNode->removeChildNode(currentNode); + } else { + // a node needs to be added.. + // remove it from any pre-existing parent, and push it before currentNode, + // so it's in the correct place... + if (desiredNode->parent()) { + desiredNode->parent()->removeChildNode(desiredNode); + } + groupNode->insertChildNodeBefore(desiredNode, currentNode); + } - // since we just replaced currentNode, we also need to reset - // the pointer. + // continue iteration at the correct point, now desiredNode is in place... currentNode = desiredNode; } |