aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2020-05-28 16:58:00 +0200
committerLaszlo Agocs <laszlo.agocs@qt.io>2020-06-03 10:51:26 +0200
commit5e0bf417fb38c53d4ae43f9f84fe42461cd2e00c (patch)
treec0dcc0954ce73447819841202cacd7615715aab6
parentff6369767321afc49b37645bb6b85d3556921645 (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.cpp10
-rw-r--r--src/quick/scenegraph/qsgthreadedrenderloop.cpp17
-rw-r--r--tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp3
-rw-r--r--tests/auto/quick/qquickwindow/tst_qquickwindow.cpp36
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;