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 libc.so.6`raise + 322
    frame #1: 0x00007fc096f3e862 libc.so.6`abort + 278
    frame #2: 0x00007fc09751b99c libQt5Core.so.5`::qt_message_fatal((null)=QtFatalMsg, context=0x00007fbfedffa570, message=0x00007fbfedffa460) at qlogging.cpp:1914:15
    frame #3: 0x00007fc097517ed6 libQt5Core.so.5`QMessageLogger::fatal(this=0x00007fbfedffa570, msg="ASSERT: \"%s\" in file %s, line %d") const at qlogging.cpp:893:21
    frame #4: 0x00007fc09750e70c libQt5Core.so.5`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 libQt5Quick.so.5`QQuickWindowPrivate::updateDirtyNode(this=0x000056502e3ec510, item=0x0000565031984e00) at qquickwindow.cpp:3874:13
    frame #6: 0x00007fc09a5d72a7 libQt5Quick.so.5`QQuickWindowPrivate::updateDirtyNodes(this=0x000056502e3ec510) at qquickwindow.cpp:3617:24
    frame #7: 0x00007fc09a5c6f18 libQt5Quick.so.5`QQuickWindowPrivate::syncSceneGraph(this=0x000056502e3ec510) at qquickwindow.cpp:524:21
    frame #8: 0x00007fc09a5483ff libQt5Quick.so.5`QSGRenderThread::sync(this=0x0000565031a8aa00, inExpose=true, inGrab=false) at qsgthreadedrenderloop.cpp:647:26
    frame #9: 0x00007fc09a54901e libQt5Quick.so.5`QSGRenderThread::syncAndRender(this=0x0000565031a8aa00, grabImage=0x0000000000000000) at qsgthreadedrenderloop.cpp:778:13
    frame #10: 0x00007fc09a54a6b6 libQt5Quick.so.5`QSGRenderThread::run(this=0x0000565031a8aa00) at qsgthreadedrenderloop.cpp:1043:30
    frame #11: 0x00007fc0975274c4 libQt5Core.so.5`QThreadPrivate::start(arg=0x0000565031a8aa00) at qthread_unix.cpp:329:17
    frame #12: 0x00007fc09670a259 libpthread.so.0`start_thread + 233
    frame #13: 0x00007fc0970165e3 libc.so.6`__clone + 67
frame #5: 0x00007f208aac179a libQt5Quick.so.5`QQuickWindowPrivate::updateDirtyNode(this=0x0000560ad419d9c0, item=0x0000560ad74cfbf0) at qquickwindow.cpp:3874:13
   3871             updatePaintNodeData.transformNode = itemPriv->itemNode();
   3872             itemPriv->paintNode = item->updatePaintNode(itemPriv->paintNode, &updatePaintNodeData);
   3873
-> 3874             Q_ASSERT(itemPriv->paintNode == nullptr ||
   3875                      itemPriv->paintNode->parent() == nullptr ||
   3876                      itemPriv->paintNode->parent() == itemPriv->childContainerNode());
   3877
(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