aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/qquickwindow.cpp
diff options
context:
space:
mode:
authorRobin Burchell <robin.burchell@crimson.no>2022-10-26 17:55:33 +0200
committerRobin Burchell <robin.burchell@crimson.no>2022-11-01 16:40:31 +0200
commita9900e9f30fa5f6c943a7c363d57c0d9d748b92f (patch)
tree2c469a2e9039b23f80f01fc389bd1a342a75c440 /src/quick/items/qquickwindow.cpp
parente3a8d8136706c9c50d76a39b72ab90cced34cca7 (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.cpp25
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;
}