Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-56657

The image is not shown in some QML case

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • P1: Critical
    • 5.6.3
    • 5.6.0
    • Quick: SceneGraph
    • 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

        Activity

          People

            sletta Gunnar Sletta
            inhyeseo Inhye Seo
            Votes:
            0 Vote for this issue
            Watchers:
            8 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes