diff options
author | Laszlo Agocs <laszlo.agocs@qt.io> | 2020-05-28 16:58:00 +0200 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@qt.io> | 2020-06-03 10:51:26 +0200 |
commit | 5e0bf417fb38c53d4ae43f9f84fe42461cd2e00c (patch) | |
tree | c0dcc0954ce73447819841202cacd7615715aab6 | |
parent | ff6369767321afc49b37645bb6b85d3556921645 (diff) |
Fix handling of destroy-show and re-enable the zoom test for qmlpreview
Fixes: QTBUG-84059
Change-Id: Id70c043f96e9525a5a6053efbf99c5ea3408da65
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
-rw-r--r-- | src/quick/scenegraph/qsgrenderloop.cpp | 10 | ||||
-rw-r--r-- | src/quick/scenegraph/qsgthreadedrenderloop.cpp | 17 | ||||
-rw-r--r-- | tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp | 3 | ||||
-rw-r--r-- | tests/auto/quick/qquickwindow/tst_qquickwindow.cpp | 36 |
4 files changed, 58 insertions, 8 deletions
diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp index 12797c196b..9306d3351a 100644 --- a/src/quick/scenegraph/qsgrenderloop.cpp +++ b/src/quick/scenegraph/qsgrenderloop.cpp @@ -466,7 +466,9 @@ void QSGGuiThreadRenderLoop::releaseSwapchain(QQuickWindow *window) QQuickWindowPrivate *wd = QQuickWindowPrivate::get(window); // Unlike the threaded render loop, this one reuses the same rendercontext - // for all QQuickWindows for the entire lifetime of the render loop. + // for all QQuickWindows for the entire lifetime of the render loop. (and + // even if it wouldn't, special cases like destroy() - show() on the + // QQuickWindow still needed this) // Therefore the renderer, if there is one, needs to be notified about the // destruction of certain resources because they may be referenced from // per-rendercontext data structures. @@ -489,10 +491,10 @@ bool QSGGuiThreadRenderLoop::eventFilter(QObject *watched, QEvent *event) // this is the proper time to tear down the swapchain (while the native window and surface are still around) if (static_cast<QPlatformSurfaceEvent *>(event)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed) { QQuickWindow *w = qobject_cast<QQuickWindow *>(watched); - if (w) { + if (w) releaseSwapchain(w); - w->removeEventFilter(this); - } + // keep this filter on the window - needed for uncommon but valid + // sequences of calls like window->destroy(); window->show(); } break; default: diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index 1318b2c034..76f65e5f85 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -1237,6 +1237,20 @@ void QSGThreadedRenderLoop::windowDestroyed(QQuickWindow *window) void QSGThreadedRenderLoop::releaseSwapchain(QQuickWindow *window) { QQuickWindowPrivate *wd = QQuickWindowPrivate::get(window); + + // Counterintuitive, because this is not needed under normal circumstances + // due to the render loop using a dedicated rendercontext per thread, so + // per window. Problem is, there are cases like calling destroy(); show(); + // on the QQuickWindow. (and we get here on SurfaceAboutToBeDestroyed, i.e. + // from destroy()) + // + // That means recreating the native window and all the related graphics + // infrastructure, but the rendercontext stays around. So still have to + // notify the renderer to invalidate the relevant objects in the caches. + // + if (wd->renderer) + wd->renderer->invalidatePipelineCacheDependency(wd->rpDescForSwapchain); + delete wd->rpDescForSwapchain; wd->rpDescForSwapchain = nullptr; delete wd->swapchain; @@ -1419,8 +1433,9 @@ bool QSGThreadedRenderLoop::eventFilter(QObject *watched, QEvent *event) w->thread->waitCondition.wait(&w->thread->mutex); w->thread->mutex.unlock(); } - window->removeEventFilter(this); } + // keep this filter on the window - needed for uncommon but valid + // sequences of calls like window->destroy(); window->show(); } break; default: diff --git a/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp b/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp index f3e5850edc..eb6ee09479 100644 --- a/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp +++ b/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp @@ -311,9 +311,6 @@ static void verifyZoomFactor(const QQmlDebugProcess *process, float factor) void tst_QQmlPreview::zoom() { - // ### Qt 6 - QSKIP("Crashes with dev, not clear why. TBD."); - const QString file("zoom.qml"); QCOMPARE(startQmlProcess(file), ConnectSuccess); QVERIFY(m_client); diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp index 9b88946090..b2ff74b631 100644 --- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp +++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp @@ -390,6 +390,7 @@ private slots: void constantUpdatesOnWindow(); void mouseFiltering(); void headless(); + void destroyShowWithoutHide(); void noUpdateWhenNothingChanges(); void touchEvent_basic(); @@ -1624,6 +1625,41 @@ void tst_qquickwindow::headless() qPrintable(errorMessage)); } +void tst_qquickwindow::destroyShowWithoutHide() +{ + // this is a variation of the headless case, to test if the more aggressive + // destroy(); show(); sequence survives. + + QQmlEngine engine; + QQmlComponent component(&engine); + component.loadUrl(testFileUrl("Headless.qml")); + QObject *created = component.create(); + QScopedPointer<QObject> cleanup(created); + + QQuickWindow *window = qobject_cast<QQuickWindow*>(created); + QVERIFY(window); + window->setTitle(QTest::currentTestFunction()); + window->show(); + + QVERIFY(QTest::qWaitForWindowExposed(window)); + QVERIFY(window->isSceneGraphInitialized()); + + QImage originalContent = window->grabWindow(); + + window->destroy(); + QVERIFY(!window->handle()); + + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + QVERIFY(window->isSceneGraphInitialized()); + + QImage newContent = window->grabWindow(); + QString errorMessage; + QVERIFY2(QQuickVisualTestUtil::compareImages(newContent, originalContent, &errorMessage), + qPrintable(errorMessage)); +} + void tst_qquickwindow::noUpdateWhenNothingChanges() { QQuickWindow window; |