Merge lp:~nick-dedekind/qtmir/fix-dropFrame-before-draw into lp:qtmir

Proposed by Nick Dedekind
Status: Merged
Approved by: Gerry Boland
Approved revision: 409
Merged at revision: 416
Proposed branch: lp:~nick-dedekind/qtmir/fix-dropFrame-before-draw
Merge into: lp:qtmir
Diff against target: 144 lines (+46/-5)
5 files modified
src/modules/Unity/Application/mirsurface.cpp (+14/-4)
src/modules/Unity/Application/mirsurface.h (+1/-1)
src/modules/Unity/Application/mirsurfaceinterface.h (+1/-0)
tests/modules/SurfaceManager/CMakeLists.txt (+1/-0)
tests/modules/SurfaceManager/mirsurface_test.cpp (+29/-0)
To merge this branch: bzr merge lp:~nick-dedekind/qtmir/fix-dropFrame-before-draw
Reviewer Review Type Date Requested Status
Gerry Boland (community) Approve
PS Jenkins bot (community) continuous-integration Needs Fixing
Review via email: mp+277702@code.launchpad.net

Commit message

Fix a crash when dropping a surface frame before Qt draws a surface item.

Description of the change

 * Are there any related MPs required for this MP to build/function as expected? Please list.
No

 * Did you perform an exploratory manual test run of your code change and any related functionality?
Yes

 * If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
N/A

To post a comment you must log in.
Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

To reproduce this you need to make sure the items don't get drawn before a frame is dropped.
This can easily be done by ensuring it is never drawn.
=== modified file 'qml/Stages/PhoneStage.qml'
--- qml/Stages/PhoneStage.qml 2015-11-04 14:58:05 +0000
+++ qml/Stages/PhoneStage.qml 2015-11-17 15:31:55 +0000
@@ -403,7 +403,6 @@
             Repeater {
                 id: spreadRepeater
                 objectName: "spreadRepeater"
- model: root.applicationManager
                 delegate: TransformedSpreadDelegate {
                     id: appDelegate
                     objectName: "appDelegate" + index

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Gerry Boland (gerboland) wrote :

Good catch!

review: Approve
410. By Nick Dedekind

stop frame dropper if can't update the texture.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/modules/Unity/Application/mirsurface.cpp'
2--- src/modules/Unity/Application/mirsurface.cpp 2015-11-13 14:13:07 +0000
3+++ src/modules/Unity/Application/mirsurface.cpp 2015-11-18 10:46:48 +0000
4@@ -292,11 +292,18 @@
5
6 int framesPending = m_surface->buffers_ready_for_compositor(userId);
7 if (framesPending > 0) {
8- qCDebug(QTMIR_SURFACES).nospace() << "MirSurface[" << appId() << "]::dropPendingBuffer() left=" << framesPending-1;
9-
10 m_textureUpdated = false;
11+
12 locker.unlock();
13- updateTexture();
14+ if (updateTexture()) {
15+ qCDebug(QTMIR_SURFACES).nospace() << "MirSurface[" << appId() << "]::dropPendingBuffer() dropped=1 left=" << framesPending-1;
16+ } else {
17+ // If we haven't managed to update the texture, don't keep banging away.
18+ m_frameDropperTimer.stop();
19+ qCDebug(QTMIR_SURFACES).nospace() << "MirSurface[" << appId() << "]::dropPendingBuffer() dropped=0"
20+ << " left=" << framesPending << " - failed to upate texture";
21+ }
22+ Q_EMIT frameDropped();
23 } else {
24 // The client can't possibly be blocked in swap buffers if the
25 // queue is empty. So we can safely enter deep sleep now. If the
26@@ -322,6 +329,8 @@
27
28 QSharedPointer<QSGTexture> MirSurface::texture()
29 {
30+ QMutexLocker locker(&m_mutex);
31+
32 if (!m_texture) {
33 QSharedPointer<QSGTexture> texture(new MirBufferSGTexture);
34 m_texture = texture.toWeakRef();
35@@ -334,9 +343,9 @@
36 bool MirSurface::updateTexture()
37 {
38 QMutexLocker locker(&m_mutex);
39- Q_ASSERT(!m_texture.isNull());
40
41 MirBufferSGTexture *texture = static_cast<MirBufferSGTexture*>(m_texture.data());
42+ if (!texture) return false;
43
44 if (m_textureUpdated) {
45 return texture->hasBuffer();
46@@ -697,6 +706,7 @@
47
48 unsigned int MirSurface::currentFrameNumber() const
49 {
50+ QMutexLocker locker(&m_mutex);
51 return m_currentFrameNumber;
52 }
53
54
55=== modified file 'src/modules/Unity/Application/mirsurface.h'
56--- src/modules/Unity/Application/mirsurface.h 2015-11-13 14:13:07 +0000
57+++ src/modules/Unity/Application/mirsurface.h 2015-11-18 10:46:48 +0000
58@@ -141,7 +141,7 @@
59
60 QTimer m_frameDropperTimer;
61
62- QMutex m_mutex;
63+ mutable QMutex m_mutex;
64
65 // Lives in the rendering (scene graph) thread
66 QWeakPointer<QSGTexture> m_texture;
67
68=== modified file 'src/modules/Unity/Application/mirsurfaceinterface.h'
69--- src/modules/Unity/Application/mirsurfaceinterface.h 2015-10-26 18:29:24 +0000
70+++ src/modules/Unity/Application/mirsurfaceinterface.h 2015-11-18 10:46:48 +0000
71@@ -88,6 +88,7 @@
72 void firstFrameDrawn();
73 void framesPosted();
74 void isBeingDisplayedChanged();
75+ void frameDropped();
76 };
77
78 } // namespace qtmir
79
80=== modified file 'tests/modules/SurfaceManager/CMakeLists.txt'
81--- tests/modules/SurfaceManager/CMakeLists.txt 2015-10-20 09:57:17 +0000
82+++ tests/modules/SurfaceManager/CMakeLists.txt 2015-11-18 10:46:48 +0000
83@@ -9,6 +9,7 @@
84
85 include_directories(
86 ${CMAKE_SOURCE_DIR}/src/modules
87+ ${CMAKE_SOURCE_DIR}/src/platforms/mirserver
88 ${CMAKE_SOURCE_DIR}/tests/modules/common
89 ${MIRSERVER_INCLUDE_DIRS}
90 )
91
92=== modified file 'tests/modules/SurfaceManager/mirsurface_test.cpp'
93--- tests/modules/SurfaceManager/mirsurface_test.cpp 2015-10-20 10:03:37 +0000
94+++ tests/modules/SurfaceManager/mirsurface_test.cpp 2015-11-18 10:46:48 +0000
95@@ -20,6 +20,7 @@
96
97 #include <QLoggingCategory>
98 #include <QTest>
99+#include <QSignalSpy>
100
101 // the test subject
102 #include <Unity/Application/mirsurface.h>
103@@ -27,6 +28,7 @@
104 // tests/modules/common
105 #include <fake_session.h>
106 #include <mock_surface.h>
107+#include <surfaceobserver.h>
108
109 using namespace qtmir;
110
111@@ -42,6 +44,33 @@
112 }
113 };
114
115+TEST_F(MirSurfaceTest, UpdateTextureBeforeDraw)
116+{
117+ using namespace testing;
118+
119+ int argc = 0;
120+ char* argv[0];
121+ QCoreApplication qtApp(argc, argv); // app for deleteLater event
122+
123+ auto fakeSession = new FakeSession();
124+ auto mockSurface = std::make_shared<NiceMock<ms::MockSurface>>();
125+ auto surfaceObserver = std::make_shared<SurfaceObserver>();
126+
127+ EXPECT_CALL(*mockSurface.get(),buffers_ready_for_compositor(_))
128+ .WillRepeatedly(Return(1));
129+
130+ MirSurface *surface = new MirSurface(mockSurface, fakeSession, nullptr, surfaceObserver);
131+ surfaceObserver->frame_posted(1);
132+
133+ QSignalSpy spyFrameDropped(surface, SIGNAL(frameDropped()));
134+ QTest::qWait(300);
135+ ASSERT_TRUE(spyFrameDropped.count() > 0);
136+
137+ delete fakeSession;
138+ delete surface;
139+}
140+
141+
142 TEST_F(MirSurfaceTest, DeleteMirSurfaceOnLastNonLiveUnregisterView)
143 {
144 using namespace testing;

Subscribers

People subscribed via source and target branches