Merge lp:~timo-jyrinki/kubuntu-packaging/qtdeclarative-opensource-src_530ubuntu9 into lp:~kubuntu-packagers/kubuntu-packaging/qtdeclarative-opensource-src

Proposed by Timo Jyrinki
Status: Merged
Approved by: Timo Jyrinki
Approved revision: 165
Merged at revision: 163
Proposed branch: lp:~timo-jyrinki/kubuntu-packaging/qtdeclarative-opensource-src_530ubuntu9
Merge into: lp:~kubuntu-packagers/kubuntu-packaging/qtdeclarative-opensource-src
Diff against target: 401 lines (+381/-0)
3 files modified
debian/changelog (+8/-0)
debian/patches/Fix-crash-with-running-animators-on-re-shown-windows.patch (+372/-0)
debian/patches/series (+1/-0)
To merge this branch: bzr merge lp:~timo-jyrinki/kubuntu-packaging/qtdeclarative-opensource-src_530ubuntu9
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Approve
Kubuntu Packagers Pending
Review via email: mp+230615@code.launchpad.net

Commit message

* debian/patches/Fix-crash-with-running-animators-on-re-shown-windows.patch:
  - Cherry-pick a fix from Qt 5.3.1 to fix crash in RotationAnimator
    (LP: #1356279)

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'debian/changelog'
--- debian/changelog 2014-08-04 11:27:03 +0000
+++ debian/changelog 2014-08-13 12:23:14 +0000
@@ -1,3 +1,11 @@
1qtdeclarative-opensource-src (5.3.0-3ubuntu9) utopic; urgency=medium
2
3 * debian/patches/Fix-crash-with-running-animators-on-re-shown-windows.patch:
4 - Cherry-pick a fix from Qt 5.3.1 to fix crash in RotationAnimator
5 (LP: #1356279)
6
7 -- Timo Jyrinki <timo-jyrinki@ubuntu.com> Wed, 13 Aug 2014 12:18:47 +0000
8
1qtdeclarative-opensource-src (5.3.0-3ubuntu8) utopic; urgency=medium9qtdeclarative-opensource-src (5.3.0-3ubuntu8) utopic; urgency=medium
210
3 [ Michał Sawicz ]11 [ Michał Sawicz ]
412
=== added file 'debian/patches/Fix-crash-with-running-animators-on-re-shown-windows.patch'
--- debian/patches/Fix-crash-with-running-animators-on-re-shown-windows.patch 1970-01-01 00:00:00 +0000
+++ debian/patches/Fix-crash-with-running-animators-on-re-shown-windows.patch 2014-08-13 12:23:14 +0000
@@ -0,0 +1,372 @@
1From 7640e387030962651f698765b64abbba938b0a82 Mon Sep 17 00:00:00 2001
2From: Gunnar Sletta <gunnar.sletta@jollamobile.com>
3Date: Thu, 15 May 2014 21:01:06 +0200
4Subject: [PATCH] Fix crash with running animators on re-shown windows.
5
6The non-threaded render loops would clean up the nodes for a window
7when it was hidden, but the animators kept running and had a reference
8to the deleted nodes. This was not a problem for the threaded render
9loop as it would wipe the animator controller as well which would
10clean the jobs.
11
12Fix it by triggering a reset of all nodes in the animators when the
13window is told to clean up. If an animator is ticked when it doesn't
14have a node, it will simply do nothing. When the window is made visible
15again, we call initialize on all animators to find the new node.
16
17Task-number: QTBUG-37995
18Change-Id: Ie5609d95db29f4b2b30ca5bf641dce901e528389
19---
20 src/quick/items/qquickwindow.cpp | 1 +
21 src/quick/util/qquickanimatorcontroller.cpp | 42 ++++++++-
22 src/quick/util/qquickanimatorcontroller_p.h | 4 +
23 src/quick/util/qquickanimatorjob.cpp | 26 ++++--
24 src/quick/util/qquickanimatorjob_p.h | 4 +
25 tests/auto/qmltest/animators/tst_multiwindow.qml | 103 +++++++++++++++++++++++
26 6 files changed, 171 insertions(+), 9 deletions(-)
27 create mode 100644 tests/auto/qmltest/animators/tst_multiwindow.qml
28
29diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
30index 16b48ef..5308d08 100644
31--- a/src/quick/items/qquickwindow.cpp
32+++ b/src/quick/items/qquickwindow.cpp
33@@ -2522,6 +2522,7 @@ void QQuickWindowPrivate::cleanupNodesOnShutdown()
34 QSet<QQuickItem *>::const_iterator it = parentlessItems.begin();
35 for (; it != parentlessItems.end(); ++it)
36 cleanupNodesOnShutdown(*it);
37+ animationController->windowNodesDestroyed();
38 q->cleanupSceneGraph();
39 }
40
41diff --git a/src/quick/util/qquickanimatorcontroller.cpp b/src/quick/util/qquickanimatorcontroller.cpp
42index 7991dd8..697c25b 100644
43--- a/src/quick/util/qquickanimatorcontroller.cpp
44+++ b/src/quick/util/qquickanimatorcontroller.cpp
45@@ -54,6 +54,7 @@ QT_BEGIN_NAMESPACE
46
47 QQuickAnimatorController::QQuickAnimatorController()
48 : m_window(0)
49+ , m_nodesAreInvalid(false)
50 {
51 }
52
53@@ -80,6 +81,26 @@ QQuickAnimatorController::~QQuickAnimatorController()
54 }
55 }
56
57+static void qquickanimator_invalidate_node(QAbstractAnimationJob *job)
58+{
59+ if (job->isRenderThreadJob()) {
60+ static_cast<QQuickAnimatorJob *>(job)->nodeWasDestroyed();
61+ } else if (job->isGroup()) {
62+ QAnimationGroupJob *g = static_cast<QAnimationGroupJob *>(job);
63+ for (QAbstractAnimationJob *a = g->firstChild(); a; a = a->nextSibling())
64+ qquickanimator_invalidate_node(a);
65+ }
66+}
67+
68+void QQuickAnimatorController::windowNodesDestroyed()
69+{
70+ m_nodesAreInvalid = true;
71+ for (QHash<QAbstractAnimationJob *, QQuickAnimatorProxyJob *>::const_iterator it = m_animatorRoots.constBegin();
72+ it != m_animatorRoots.constEnd(); ++it) {
73+ qquickanimator_invalidate_node(it.key());
74+ }
75+}
76+
77 void QQuickAnimatorController::itemDestroyed(QObject *o)
78 {
79 m_deletedSinceLastFrame << (QQuickItem *) o;
80@@ -112,7 +133,7 @@ void QQuickAnimatorController::advance()
81 m_window->update();
82 }
83
84-static void qquick_initialize_helper(QAbstractAnimationJob *job, QQuickAnimatorController *c)
85+static void qquick_initialize_helper(QAbstractAnimationJob *job, QQuickAnimatorController *c, bool attachListener)
86 {
87 if (job->isRenderThreadJob()) {
88 QQuickAnimatorJob *j = static_cast<QQuickAnimatorJob *>(job);
89@@ -121,13 +142,14 @@ static void qquick_initialize_helper(QAbstractAnimationJob *job, QQuickAnimatorC
90 } else if (c->m_deletedSinceLastFrame.contains(j->target())) {
91 j->targetWasDeleted();
92 } else {
93- j->addAnimationChangeListener(c, QAbstractAnimationJob::StateChange);
94+ if (attachListener)
95+ j->addAnimationChangeListener(c, QAbstractAnimationJob::StateChange);
96 j->initialize(c);
97 }
98 } else if (job->isGroup()) {
99 QAnimationGroupJob *g = static_cast<QAnimationGroupJob *>(job);
100 for (QAbstractAnimationJob *a = g->firstChild(); a; a = a->nextSibling())
101- qquick_initialize_helper(a, c);
102+ qquick_initialize_helper(a, c, attachListener);
103 }
104 }
105
106@@ -147,7 +169,7 @@ void QQuickAnimatorController::beforeNodeSync()
107 foreach (QQuickAnimatorProxyJob *proxy, m_starting) {
108 QAbstractAnimationJob *job = proxy->job();
109 job->addAnimationChangeListener(this, QAbstractAnimationJob::Completion);
110- qquick_initialize_helper(job, this);
111+ qquick_initialize_helper(job, this, true);
112 m_animatorRoots[job] = proxy;
113 job->start();
114 proxy->startedByController();
115@@ -160,6 +182,18 @@ void QQuickAnimatorController::beforeNodeSync()
116 }
117 m_stopping.clear();
118
119+ // First sync after a window was hidden or otherwise invalidated.
120+ // call initialize again to pick up new nodes..
121+ if (m_nodesAreInvalid) {
122+ for (QHash<QAbstractAnimationJob *, QQuickAnimatorProxyJob *>::const_iterator it = m_animatorRoots.constBegin();
123+ it != m_animatorRoots.constEnd(); ++it) {
124+ qquick_initialize_helper(it.key(), this, false);
125+ }
126+ m_nodesAreInvalid = false;
127+ }
128+
129+
130+
131 foreach (QQuickAnimatorJob *job, m_activeLeafAnimations) {
132 if (!job->target())
133 continue;
134diff --git a/src/quick/util/qquickanimatorcontroller_p.h b/src/quick/util/qquickanimatorcontroller_p.h
135index 6223a99..745a494 100644
136--- a/src/quick/util/qquickanimatorcontroller_p.h
137+++ b/src/quick/util/qquickanimatorcontroller_p.h
138@@ -76,6 +76,8 @@ public:
139 void lock() { m_mutex.lock(); }
140 void unlock() { m_mutex.unlock(); }
141
142+ void windowNodesDestroyed();
143+
144 public Q_SLOTS:
145 void itemDestroyed(QObject *);
146
147@@ -92,6 +94,8 @@ public:
148 QSet<QQuickItem *> m_deletedSinceLastFrame;
149 QQuickWindow *m_window;
150 QMutex m_mutex;
151+
152+ bool m_nodesAreInvalid;
153 };
154
155 QT_END_NAMESPACE
156diff --git a/src/quick/util/qquickanimatorjob.cpp b/src/quick/util/qquickanimatorjob.cpp
157index 3bc4cef..0bf95a4 100644
158--- a/src/quick/util/qquickanimatorjob.cpp
159+++ b/src/quick/util/qquickanimatorjob.cpp
160@@ -281,6 +281,12 @@ void QQuickTransformAnimatorJob::initialize(QQuickAnimatorController *controller
161 }
162 }
163
164+void QQuickTransformAnimatorJob::nodeWasDestroyed()
165+{
166+ if (m_helper)
167+ m_helper->node = 0;
168+}
169+
170 void QQuickTransformAnimatorJob::Helper::sync()
171 {
172 const quint32 mask = QQuickItemPrivate::Position
173@@ -326,7 +332,7 @@ void QQuickTransformAnimatorJob::Helper::sync()
174
175 void QQuickTransformAnimatorJob::Helper::apply()
176 {
177- if (!wasChanged)
178+ if (!wasChanged || !node)
179 return;
180
181 QMatrix4x4 m;
182@@ -412,6 +418,11 @@ void QQuickOpacityAnimatorJob::initialize(QQuickAnimatorController *controller)
183 }
184 }
185
186+void QQuickOpacityAnimatorJob::nodeWasDestroyed()
187+{
188+ m_opacityNode = 0;
189+}
190+
191 void QQuickOpacityAnimatorJob::writeBack()
192 {
193 if (m_target)
194@@ -420,7 +431,7 @@ void QQuickOpacityAnimatorJob::writeBack()
195
196 void QQuickOpacityAnimatorJob::updateCurrentTime(int time)
197 {
198- if (!m_controller)
199+ if (!m_controller || !m_opacityNode)
200 return;
201 Q_ASSERT(m_controller->m_window->openglContext()->thread() == QThread::currentThread());
202
203@@ -504,13 +515,18 @@ void QQuickUniformAnimatorJob::setTarget(QQuickItem *target)
204 m_target = target;
205 }
206
207+void QQuickUniformAnimatorJob::nodeWasDestroyed()
208+{
209+ m_node = 0;
210+ m_uniformIndex = -1;
211+ m_uniformType = -1;
212+}
213+
214 void QQuickUniformAnimatorJob::afterNodeSync()
215 {
216 m_node = static_cast<QQuickShaderEffectNode *>(QQuickItemPrivate::get(m_target)->paintNode);
217
218- if (m_node) {
219- m_uniformIndex = -1;
220- m_uniformType = -1;
221+ if (m_node && m_uniformIndex == -1 && m_uniformType == -1) {
222 QQuickShaderEffectMaterial *material =
223 static_cast<QQuickShaderEffectMaterial *>(m_node->material());
224 bool found = false;
225diff --git a/src/quick/util/qquickanimatorjob_p.h b/src/quick/util/qquickanimatorjob_p.h
226index 8aae121..03b13bc 100644
227--- a/src/quick/util/qquickanimatorjob_p.h
228+++ b/src/quick/util/qquickanimatorjob_p.h
229@@ -131,6 +131,7 @@ public:
230 void targetWasDeleted();
231 virtual void initialize(QQuickAnimatorController *controller);
232 virtual void writeBack() = 0;
233+ virtual void nodeWasDestroyed() = 0;
234
235 bool isTransform() const { return m_isTransform; }
236 bool isUniform() const { return m_isUniform; }
237@@ -208,6 +209,7 @@ public:
238 protected:
239 QQuickTransformAnimatorJob();
240 void initialize(QQuickAnimatorController *controller);
241+ void nodeWasDestroyed();
242
243 Helper *m_helper;
244 };
245@@ -256,6 +258,7 @@ public:
246 void initialize(QQuickAnimatorController *controller);
247 void updateCurrentTime(int time);
248 void writeBack();
249+ void nodeWasDestroyed();
250
251 private:
252 QSGOpacityNode *m_opacityNode;
253@@ -275,6 +278,7 @@ public:
254
255 void updateCurrentTime(int time);
256 void writeBack();
257+ void nodeWasDestroyed();
258
259 private:
260 QByteArray m_uniform;
261diff --git a/tests/auto/qmltest/animators/tst_multiwindow.qml b/tests/auto/qmltest/animators/tst_multiwindow.qml
262new file mode 100644
263index 0000000..7f7ca25
264--- /dev/null
265+++ b/tests/auto/qmltest/animators/tst_multiwindow.qml
266@@ -0,0 +1,103 @@
267+/****************************************************************************
268+**
269+** Copyright (C) 2014 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
270+** Contact: http://www.qt-project.org/legal
271+**
272+** This file is part of the test suite of the Qt Toolkit.
273+**
274+** $QT_BEGIN_LICENSE:LGPL$
275+** Commercial License Usage
276+** Licensees holding valid commercial Qt licenses may use this file in
277+** accordance with the commercial license agreement provided with the
278+** Software or, alternatively, in accordance with the terms contained in
279+** a written agreement between you and Digia. For licensing terms and
280+** conditions see http://qt.digia.com/licensing. For further information
281+** use the contact form at http://qt.digia.com/contact-us.
282+**
283+** GNU Lesser General Public License Usage
284+** Alternatively, this file may be used under the terms of the GNU Lesser
285+** General Public License version 2.1 as published by the Free Software
286+** Foundation and appearing in the file LICENSE.LGPL included in the
287+** packaging of this file. Please review the following information to
288+** ensure the GNU Lesser General Public License version 2.1 requirements
289+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
290+**
291+** In addition, as a special exception, Digia gives you certain additional
292+** rights. These rights are described in the Digia Qt LGPL Exception
293+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
294+**
295+** GNU General Public License Usage
296+** Alternatively, this file may be used under the terms of the GNU
297+** General Public License version 3.0 as published by the Free Software
298+** Foundation and appearing in the file LICENSE.GPL included in the
299+** packaging of this file. Please review the following information to
300+** ensure the GNU General Public License version 3.0 requirements will be
301+** met: http://www.gnu.org/copyleft/gpl.html.
302+**
303+**
304+** $QT_END_LICENSE$
305+**
306+****************************************************************************/
307+
308+import QtQuick 2.2
309+import QtTest 1.0
310+import QtQuick.Window 2.0
311+
312+Item {
313+ id: root;
314+ width: 200
315+ height: 200
316+
317+ TestCase {
318+ id: testCase
319+ name: "animators-mixed"
320+ when: countdown == 0
321+ function test_endresult() {
322+ verify(true, "Just making sure we didn't crash");
323+ }
324+ }
325+
326+ property int countdown: 5;
327+
328+ Window {
329+ id: window
330+
331+ width: 100
332+ height: 100
333+
334+ ShaderEffect {
335+ width: 50
336+ height: 50
337+
338+ property real t;
339+ UniformAnimator on t { from: 0; to: 1; duration: 1000; loops: Animation.Infinite }
340+ RotationAnimator on rotation { from: 0; to: 360; duration: 1000; loops: Animation.Infinite }
341+ ScaleAnimator on scale { from: 0.5; to: 1.5; duration: 1000; loops: Animation.Infinite }
342+ XAnimator on x { from: 0; to: 50; duration: 1000; loops: Animation.Infinite }
343+ YAnimator on y { from: 0; to: 50; duration: 1000; loops: Animation.Infinite }
344+ OpacityAnimator on opacity { from: 1; to: 0.5; duration: 1000; loops: Animation.Infinite }
345+
346+ fragmentShader: "
347+ uniform lowp float t;
348+ uniform lowp float qt_Opacity;
349+ varying highp vec2 qt_TexCoord0;
350+ void main() {
351+ gl_FragColor = vec4(qt_TexCoord0, t, 1) * qt_Opacity;
352+ }
353+ "
354+ }
355+
356+ visible: true
357+ }
358+
359+ Timer {
360+ interval: 250
361+ running: true
362+ repeat: true
363+ onTriggered: {
364+ if (window.visible)
365+ --countdown
366+ window.visible = !window.visible;
367+ }
368+ }
369+}
370--
3712.1.0.rc1
372
0373
=== modified file 'debian/patches/series'
--- debian/patches/series 2014-08-04 08:09:32 +0000
+++ debian/patches/series 2014-08-13 12:23:14 +0000
@@ -10,3 +10,4 @@
10Fix-interaction-of-garbage-collector-with-JS-objects.patch10Fix-interaction-of-garbage-collector-with-JS-objects.patch
11Support-RFC2822Date-date-format-similar-to-V8.patch11Support-RFC2822Date-date-format-similar-to-V8.patch
128454a21b-Flickable-Cancel-interaction-on-interactive-changes.patch128454a21b-Flickable-Cancel-interaction-on-interactive-changes.patch
13Fix-crash-with-running-animators-on-re-shown-windows.patch

Subscribers

People subscribed via source and target branches