Skip to content

Split window texture provider from window texture node

Vlad Zahorodnii requested to merge work/zzag/split-window-texture-provider into master

Currently, the WindowThumbnail item puts both the texture provider and the scene graph node in a single object.

It uses QPointer to detect if the scene graph node has been deleted. However, that seems to break if QtQuick passes null oldNode while the real old node is still alive.

Because the WindowThumbnail caches the old node, it may not see that QtQuick wants a new scene graph node. With debug build, it's going to trigger an assert in QQuickWindowPrivate::updateDirtyNode() that checks if the paint node is either new or belongs to the child container node. With a release build, it's undefined behavior.

In order to make the WindowThumbnail item handle the case where oldNode is null while the cached old node is still alive, this change decouples texture provider bits from the scene graph node and ports the item to QSGImageNode, which we need to do anyway.

BUG: 439681

* thread #42, name = 'QSGRenderThread', stop reason = signal SIGABRT
  * frame #0: 0x00007fc096f54d22`raise + 322
    frame #1: 0x00007fc096f3e862`abort + 278
    frame #2: 0x00007fc09751b99c`::qt_message_fatal((null)=QtFatalMsg, context=0x00007fbfedffa570, message=0x00007fbfedffa460) at qlogging.cpp:1914:15
    frame #3: 0x00007fc097517ed6`QMessageLogger::fatal(this=0x00007fbfedffa570, msg="ASSERT: \"%s\" in file %s, line %d") const at qlogging.cpp:893:21
    frame #4: 0x00007fc09750e70c`qt_assert(assertion="itemPriv->paintNode == nullptr || itemPriv->paintNode->parent() == nullptr || itemPriv->paintNode->parent() == itemPriv->childContainerNode()", file="items/qquickwindow.cpp", line=3874) at qglobal.cpp:3358:46
    frame #5: 0x00007fc09a5d879a`QQuickWindowPrivate::updateDirtyNode(this=0x000056502e3ec510, item=0x0000565031984e00) at qquickwindow.cpp:3874:13
    frame #6: 0x00007fc09a5d72a7`QQuickWindowPrivate::updateDirtyNodes(this=0x000056502e3ec510) at qquickwindow.cpp:3617:24
    frame #7: 0x00007fc09a5c6f18`QQuickWindowPrivate::syncSceneGraph(this=0x000056502e3ec510) at qquickwindow.cpp:524:21
    frame #8: 0x00007fc09a5483ff`QSGRenderThread::sync(this=0x0000565031a8aa00, inExpose=true, inGrab=false) at qsgthreadedrenderloop.cpp:647:26
    frame #9: 0x00007fc09a54901e`QSGRenderThread::syncAndRender(this=0x0000565031a8aa00, grabImage=0x0000000000000000) at qsgthreadedrenderloop.cpp:778:13
    frame #10: 0x00007fc09a54a6b6`QSGRenderThread::run(this=0x0000565031a8aa00) at qsgthreadedrenderloop.cpp:1043:30
    frame #11: 0x00007fc0975274c4`QThreadPrivate::start(arg=0x0000565031a8aa00) at qthread_unix.cpp:329:17
    frame #12: 0x00007fc09670a259`start_thread + 233
    frame #13: 0x00007fc0970165e3`__clone + 67
frame #5: 0x00007f208aac179a`QQuickWindowPrivate::updateDirtyNode(this=0x0000560ad419d9c0, item=0x0000560ad74cfbf0) at qquickwindow.cpp:3874:13
   3871             updatePaintNodeData.transformNode = itemPriv->itemNode();
   3872             itemPriv->paintNode = item->updatePaintNode(itemPriv->paintNode, &updatePaintNodeData);
-> 3874             Q_ASSERT(itemPriv->paintNode == nullptr ||
   3875                      itemPriv->paintNode->parent() == nullptr ||
   3876                      itemPriv->paintNode->parent() == itemPriv->childContainerNode());
(lldb) p itemPriv->paintNode
(Plasma::WindowTextureNode *) $0 = 0x00007f1f74ee06f0
(lldb) p itemPriv->paintNode->parent()
(QSGRootNode *) $1 = 0x00007f1f74cd51e0
(lldb) p itemPriv->childContainerNode()
(QSGRootNode *) $2 = 0x00007f1f9821f060
Edited by Vlad Zahorodnii

Merge request reports