summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTor Arne Vestbø <[email protected]>2024-04-03 14:37:03 +0200
committerTor Arne Vestbø <[email protected]>2024-04-20 10:25:05 +0200
commit294fb8e9b79fa1ec94af3afa9b0d686fac3f835c (patch)
tree193e8a1c611b35ad1670a7c1966d7aced34031c9
parent5c32d48a3a0384561c11f41d0c8bdc7e56775285 (diff)
widgets: Invalidate RHI swapchain when window moves to new top level
When a QWidget with an associated RHI swapchain (via its QWindow) is moved to a different top level window, that top level window has its own backing store, and QBackingStoreRhiSupport, which doesn't know anything about the fact that the window already has an associated swap chain in the original top level window's QBackingStoreRhiSupport. As having multiple swap chains for the same window is not supported on all RHI backends (Vulkan and DX in particular), we need to throw away the swap chain when detecting that the window is moved to a new top level. We do this by hooking into the existing WindowAboutToChangeInternal event delivery to renderToTexture children, which now delivers the event both to renderToTexture QWidget children as well as QWindows in the hierarchy. The condition of when to deliver the event has been updated to reflect whether the top level uses RHI for flushing, instead of only including renderToTexture children, as the former also includes setting QT_WIDGETS_RHI=1 explicitly. The event is then caught by QBackingStoreRhiSupportWindowWatcher, and handled the same way as for SurfaceAboutToBeDestroyed. Renaming qSendWindowChangeToTextureChildrenRecursively would make sense at this point, but to make cherry-picks easier we keep the current name for now. Fixes: QTBUG-120276 Change-Id: Ic4c60e89be985f12a84e9f893c299e602b70851a Reviewed-by: Qt CI Bot <[email protected]> Reviewed-by: Laszlo Agocs <[email protected]> (cherry picked from commit 1bd755465efa27294362925f55306f88f1800936) Reviewed-by: Qt Cherry-pick Bot <[email protected]> (cherry picked from commit 81581819c79c9195b0a732cc3ba99a67a18c06f0) Reviewed-by: Tor Arne Vestbø <[email protected]>
-rw-r--r--src/gui/painting/qbackingstorerhisupport.cpp7
-rw-r--r--src/widgets/kernel/qwidget.cpp12
2 files changed, 13 insertions, 6 deletions
diff --git a/src/gui/painting/qbackingstorerhisupport.cpp b/src/gui/painting/qbackingstorerhisupport.cpp
index 422159dfd90..55cfb9a61bc 100644
--- a/src/gui/painting/qbackingstorerhisupport.cpp
+++ b/src/gui/painting/qbackingstorerhisupport.cpp
@@ -181,13 +181,14 @@ QRhiSwapChain *QBackingStoreRhiSupport::swapChainForWindow(QWindow *window)
bool QBackingStoreRhiSupportWindowWatcher::eventFilter(QObject *obj, QEvent *event)
{
- if (event->type() == QEvent::PlatformSurface
- && static_cast<QPlatformSurfaceEvent *>(event)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed)
+ if (event->type() == QEvent::WindowAboutToChangeInternal
+ || (event->type() == QEvent::PlatformSurface
+ && static_cast<QPlatformSurfaceEvent *>(event)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed))
{
QWindow *window = qobject_cast<QWindow *>(obj);
auto it = m_rhiSupport->m_swapchains.find(window);
if (it != m_rhiSupport->m_swapchains.end()) {
- qCDebug(lcQpaBackingStore) << "SurfaceAboutToBeDestroyed received for tracked window" << window << "cleaning up swapchain";
+ qCDebug(lcQpaBackingStore) << event << "received for" << window << "- cleaning up swapchain";
auto data = *it;
m_rhiSupport->m_swapchains.erase(it);
data.reset(); // deletes 'this'
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 0e7a86e4665..f78504b338f 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -10643,9 +10643,15 @@ void qSendWindowChangeToTextureChildrenRecursively(QWidget *widget, QEvent::Type
for (int i = 0; i < d->children.size(); ++i) {
QWidget *w = qobject_cast<QWidget *>(d->children.at(i));
- if (w && !w->isWindow() && QWidgetPrivate::get(w)->textureChildSeen)
+ if (w && !w->isWindow())
qSendWindowChangeToTextureChildrenRecursively(w, eventType);
}
+
+ // Notify QWidgetWindow after we've notified all child QWidgets
+ if (auto *window = d->windowHandle(QWidgetPrivate::WindowHandleMode::Direct)) {
+ QEvent e(eventType);
+ QCoreApplication::sendEvent(window, &e);
+ }
}
/*!
@@ -10705,7 +10711,7 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
// texture-based widgets need a pre-notification when their associated top-level window changes
// This is not under the wasCreated/newParent conditions above in order to also play nice with QDockWidget.
- if (d->textureChildSeen && ((!parent && parentWidget()) || (parent && parent->window() != oldtlw)))
+ if ((oldtlw && oldtlw->d_func()->usesRhiFlush) && ((!parent && parentWidget()) || (parent && parent->window() != oldtlw)))
qSendWindowChangeToTextureChildrenRecursively(this, QEvent::WindowAboutToChangeInternal);
// If we get parented into another window, children will be folded
@@ -10786,7 +10792,7 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
// texture-based widgets need another event when their top-level window
// changes (more precisely, has already changed at this point)
- if (d->textureChildSeen && oldtlw != window())
+ if ((oldtlw && oldtlw->d_func()->usesRhiFlush) && oldtlw != window())
qSendWindowChangeToTextureChildrenRecursively(this, QEvent::WindowChangeInternal);
if (!wasCreated) {