Details
-
Bug
-
Resolution: Done
-
P1: Critical
-
5.6.0
-
None
-
9f4bb9a687277932125a065a53e3f3d8afdebc8b
Description
I found a bug in following QML. The image is not shown.
It works with Qt 5.4. But it's not working with Qt 5.6.
import QtQuick 2.4 import QtQuick.Window 2.2 Window { width: 1000 height: 900 visible: true Image { id: outer width: 100; height: 100 visible: false Rectangle { id: inner visible: false z: -1 color: "blue" x: 50; y: 50; width: 100; height: 100 } } MouseArea { anchors.fill: parent onClicked: { outer.source = "Mickey_-_House_of_Mouse.png" inner.visible = true; visibleTimer.start(); } } Timer { id : visibleTimer interval: 200; running: false; repeat:false; onTriggered: { outer.visible = true; } } }
As I debugged, a geometry node of Image is not added to scenegraph tree. I think it is caused from following.
static inline QSGNode *qquickitem_before_paintNode(QQuickItemPrivate *d) { const QList<QQuickItem *> childItems = d->paintOrderChildItems(); QQuickItem *before = 0; for (int i=0; i<childItems.size(); ++i) { QQuickItemPrivate *dd = QQuickItemPrivate::get(childItems.at(i)); // Perform the same check as the in fetchNextNode below. if (dd->z() < 0 && (dd->explicitVisible || (dd->extra.isAllocated() && dd->extra->effectRefCount))) before = childItems.at(i); else break; } return Q_UNLIKELY(before) ? QQuickItemPrivate::get(before)->itemNode() : 0; }
In short, that returns a transform node which has no parent.
Consequently, it leads to following assertion case .
void QSGNode::insertChildNodeAfter(QSGNode *node, QSGNode *after) { //Q_ASSERT_X(!m_children.contains(node), "QSGNode::insertChildNodeAfter", "QSGNode is already a child!"); Q_ASSERT_X(!node->m_parent, "QSGNode::insertChildNodeAfter", "QSGNode already has a parent"); Q_ASSERT_X(after && after->m_parent == this, "QSGNode::insertChildNodeAfter", "The parent of \'after\' is wrong");
Indeed, I tested it in release mode, so no assertion happened.
Just geometry node is skipped because m_firstChild is null.
So the image is just not shown.
In summary,
Conditions for reproduce:
1. Image - rectangle are parent - child relationship.
2. z order of sibling node of image geometry node was negative.
My analysis:
1. qquickitem_before_paintNode returns the transform node for the rectangle as child node. But the node has no parent.
2. In release mode, no assertion happened. it is added without setting m_firstChild.
3. Then, in Renderer::nodeWasAdded, it is skipped to add geometry node of the image into group node, because m_firstChild of childContainerNode is null.
Quick proposal:
Can we check the parent of the child item? Here is some try for that.
static inline QSGNode *qquickitem_before_paintNode(QQuickItemPrivate *d) { const QList<QQuickItem *> childItems = d->paintOrderChildItems(); QQuickItem *before = 0; for (int i=0; i<childItems.size(); ++i) { QQuickItemPrivate *dd = QQuickItemPrivate::get(childItems.at(i)); // Perform the same check as the in fetchNextNode below. if (dd->z() < 0 && (dd->explicitVisible || (dd->extra.isAllocated() && dd->extra->effectRefCount))) before = childItems.at(i); else break; } if (before) { QSGNode* beforeNode = QQuickItemPrivate::get(before)->itemNode(); if (beforeNode->parent()) return beforeNode; } return 0; }
Attachments
For Gerrit Dashboard: QTBUG-56657 | ||||||
---|---|---|---|---|---|---|
# | Subject | Branch | Project | Status | CR | V |
174566,5 | Add checking "before" as child node | 5.6 | qt/qtdeclarative | Status: MERGED | +2 | 0 |