Skip to content

Commit

Permalink
MAYA-132068: Unusable UI when docking with QWebEngineView (qtbase) (q…
Browse files Browse the repository at this point in the history
…t#104)

* rhi: d3d11: Flush() when destroying a swapchain

Task-number: QTBUG-120276
Pick-to: 6.7 6.6 6.5
Change-Id: Iaf79c4dcf60d9a52bd562fd94976402cf570147d
Reviewed-by: Tor Arne Vestbø <[email protected]>
(cherry picked from commit cff5a49)

* 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
Pick-to: 6.7 6.5
Change-Id: Ic4c60e89be985f12a84e9f893c299e602b70851a
Reviewed-by: Qt CI Bot <[email protected]>
Reviewed-by: Laszlo Agocs <[email protected]>
(cherry picked from commit 1bd7554)

rename sendWindowChangeToTextureChildrenRecursively

Change-Id: I457f50b68d5813e3ef09c31749dc3db8d0dc6822

---------

Co-authored-by: Laszlo Agocs <[email protected]>
Co-authored-by: Tor Arne Vestbø <[email protected]>
  • Loading branch information
3 people authored and GitHub Enterprise committed May 29, 2024
1 parent aaca5d7 commit f2b8467
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 7 deletions.
7 changes: 4 additions & 3 deletions src/gui/painting/qbackingstorerhisupport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
6 changes: 5 additions & 1 deletion src/gui/rhi/qrhid3d11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4738,8 +4738,12 @@ void QD3D11SwapChain::destroy()
}

QRHI_RES_RHI(QRhiD3D11);
if (rhiD)
if (rhiD) {
rhiD->unregisterResource(this);
// See Deferred Destruction Issues with Flip Presentation Swap Chains in
// https://learn.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-id3d11devicecontext-flush
rhiD->context->Flush();
}
}

QRhiCommandBuffer *QD3D11SwapChain::currentFrameCommandBuffer()
Expand Down
12 changes: 9 additions & 3 deletions src/widgets/kernel/qwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10659,9 +10659,15 @@ static void sendWindowChangeToTextureChildrenRecursively(QWidget *widget, QEvent

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())
sendWindowChangeToTextureChildrenRecursively(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);
}
}

/*!
Expand Down Expand Up @@ -10721,7 +10727,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)))
sendWindowChangeToTextureChildrenRecursively(this, QEvent::WindowAboutToChangeInternal);

// If we get parented into another window, children will be folded
Expand Down Expand Up @@ -10802,7 +10808,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())
sendWindowChangeToTextureChildrenRecursively(this, QEvent::WindowChangeInternal);

if (!wasCreated) {
Expand Down

0 comments on commit f2b8467

Please sign in to comment.