aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorMitch Curtis <mitch.curtis@qt.io>2020-10-14 11:06:01 +0200
committerMitch Curtis <mitch.curtis@qt.io>2020-10-15 11:12:49 +0200
commit266cd7638d887b31d56964a0f13fe208821703b1 (patch)
tree8d88f95fdc1a70ac6b899af012c617ea83dd1df8 /tests
parent678d4ec4b68d43d0c748a8ec62a13716f83a27cf (diff)
QQuickShaderEffect: fix crash when hiding parent
It's possible for itemChange to be called during destruction when deleting the QQuickShaderEffectImpl. We nullify m_impl before deleting it via another pointer to it, so we must check that it's not null before trying to use it. Pick-to: 5.15 Fixes: QTBUG-86402 Change-Id: If4955445f7cc0d1f376bc9b86b95e1cca4d88ede Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/quick/qquickshadereffect/CMakeLists.txt2
-rw-r--r--tests/auto/quick/qquickshadereffect/data/hideParent.qml127
-rw-r--r--tests/auto/quick/qquickshadereffect/data/opacity-mask.frag19
-rw-r--r--tests/auto/quick/qquickshadereffect/data/opacity-mask.frag.qsbbin0 -> 1411 bytes
-rw-r--r--tests/auto/quick/qquickshadereffect/resources.qrc2
-rw-r--r--tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp14
6 files changed, 164 insertions, 0 deletions
diff --git a/tests/auto/quick/qquickshadereffect/CMakeLists.txt b/tests/auto/quick/qquickshadereffect/CMakeLists.txt
index 92a1baa227..6eebadeedf 100644
--- a/tests/auto/quick/qquickshadereffect/CMakeLists.txt
+++ b/tests/auto/quick/qquickshadereffect/CMakeLists.txt
@@ -27,6 +27,8 @@ set(resources_resource_files
"data/connections.qml"
"data/deleteShaderEffectSource.qml"
"data/deleteSourceItem.qml"
+ "data/hideParent.qml"
+ "data/opacity-mask.frag.qsb"
"data/red.frag"
"data/star.png"
"data/test.frag"
diff --git a/tests/auto/quick/qquickshadereffect/data/hideParent.qml b/tests/auto/quick/qquickshadereffect/data/hideParent.qml
new file mode 100644
index 0000000000..e862dfaa01
--- /dev/null
+++ b/tests/auto/quick/qquickshadereffect/data/hideParent.qml
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+Item {
+ id: root
+ width: 640
+ height: 480
+ objectName: "qtbug86402Container"
+
+ property bool finished
+
+ Item {
+ id: popup
+ objectName: "popup"
+ width: 200
+ height: 200
+
+ Rectangle {
+ id: rect
+ objectName: "rect"
+ implicitWidth: 100
+ implicitHeight: 100
+ color: "blue"
+
+ Item {
+ id: ripple
+ objectName: "ripple"
+ anchors.fill: parent
+ visible: false
+
+ Rectangle {
+ id: rippleBox
+ objectName: "rippleBox"
+ property real cx
+ property real cy
+ x: cx - width / 2
+ y: cy - height / 2
+ width: 0
+ height: width
+ radius: width / 2
+ color: Qt.darker("red", 1.8)
+ }
+ layer.effect: ShaderEffect {
+ id: mask
+ objectName: "shaderEffect"
+ property variant source
+ property variant maskSource: rect
+
+ fragmentShader: "opacity-mask.frag.qsb"
+ }
+ }
+
+ SequentialAnimation {
+ id: rippleStartAnimation
+ running: popup.visible
+ onFinished: {
+ popup.parent = null
+ rippleEndAnimation.start()
+ }
+
+ ScriptAction {
+ script: {
+ rippleBox.width = 0
+ rippleBox.opacity = 0.3
+ ripple.visible = true
+ ripple.layer.enabled = true
+ }
+ }
+ NumberAnimation {
+ target: rippleBox
+ property: "width"
+ from: 0
+ to: Math.max(rect.width,
+ rect.height) * 2.2
+ duration: 100
+ }
+ }
+ SequentialAnimation {
+ id: rippleEndAnimation
+
+ onFinished: root.finished = true
+
+ //Causes Crash on QT Versions > 5.12.5
+ NumberAnimation {
+ target: rippleBox
+ property: "opacity"
+ to: 0
+ duration: 100
+ }
+ ScriptAction {
+ script: {
+ rippleBox.opacity = 0
+ ripple.layer.enabled = false
+ ripple.visible = false
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickshadereffect/data/opacity-mask.frag b/tests/auto/quick/qquickshadereffect/data/opacity-mask.frag
new file mode 100644
index 0000000000..94a80b8a99
--- /dev/null
+++ b/tests/auto/quick/qquickshadereffect/data/opacity-mask.frag
@@ -0,0 +1,19 @@
+#version 440
+
+layout(location = 0) in vec2 qt_TexCoord0;
+layout(location = 0) out vec4 fragColor;
+
+layout(std140, binding = 0) uniform buf {
+ // qt_Matrix and qt_Opacity must always be both present
+ // if the built-in vertex shader is used.
+ mat4 qt_Matrix;
+ float qt_Opacity;
+};
+
+layout(binding = 1) uniform sampler2D source;
+layout(binding = 2) uniform sampler2D maskSource;
+
+void main()
+{
+ fragColor = texture(source, qt_TexCoord0.st) * (texture(maskSource, qt_TexCoord0.st).a) * qt_Opacity;
+}
diff --git a/tests/auto/quick/qquickshadereffect/data/opacity-mask.frag.qsb b/tests/auto/quick/qquickshadereffect/data/opacity-mask.frag.qsb
new file mode 100644
index 0000000000..29ce0b21a0
--- /dev/null
+++ b/tests/auto/quick/qquickshadereffect/data/opacity-mask.frag.qsb
Binary files differ
diff --git a/tests/auto/quick/qquickshadereffect/resources.qrc b/tests/auto/quick/qquickshadereffect/resources.qrc
index 2789a6eecb..50c4c82036 100644
--- a/tests/auto/quick/qquickshadereffect/resources.qrc
+++ b/tests/auto/quick/qquickshadereffect/resources.qrc
@@ -12,5 +12,7 @@
<file>data/+qsb/test.vert</file>
<file>data/+qsb/test.frag</file>
<file>data/+qsb/red.frag</file>
+ <file>data/hideParent.qml</file>
+ <file>data/opacity-mask.frag.qsb</file>
</qresource>
</RCC>
diff --git a/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp b/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp
index 9bc4b20968..fa5a0ed384 100644
--- a/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp
+++ b/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp
@@ -82,6 +82,8 @@ private slots:
void withoutQmlEngine();
+ void hideParent();
+
private:
enum PresenceFlags {
VertexPresent = 0x01,
@@ -177,6 +179,18 @@ void tst_qquickshadereffect::withoutQmlEngine()
delete window;
}
+// QTBUG-86402: hiding the parent of an item that uses an effect should not cause a crash.
+void tst_qquickshadereffect::hideParent()
+{
+ QScopedPointer<QQuickView> view(new QQuickView);
+ view->setSource(QUrl(QStringLiteral("qrc:/data/hideParent.qml")));
+ QCOMPARE(view->status(), QQuickView::Ready);
+ view->show();
+ QVERIFY(QTest::qWaitForWindowExposed(view.data()));
+ // Should finish without crashing.
+ QTRY_VERIFY(view->rootObject()->property("finished").toBool());
+}
+
QTEST_MAIN(tst_qquickshadereffect)
#include "tst_qquickshadereffect.moc"