Mir

Merge lp:~alan-griffiths/mir/nested-sessions-dont-post-buffers-until-something-happens into lp:mir

Proposed by Alan Griffiths
Status: Merged
Approved by: Alan Griffiths
Approved revision: no longer in the source branch.
Merged at revision: 1456
Proposed branch: lp:~alan-griffiths/mir/nested-sessions-dont-post-buffers-until-something-happens
Merge into: lp:mir
Prerequisite: lp:~alan-griffiths/mir/add-some-intelligence-to-scheduling-compositing
Diff against target: 344 lines (+135/-23)
5 files modified
examples/render_surfaces.cpp (+30/-2)
src/server/compositor/default_configuration.cpp (+7/-4)
src/server/compositor/multi_threaded_compositor.cpp (+27/-9)
src/server/compositor/multi_threaded_compositor.h (+5/-1)
tests/unit-tests/compositor/test_multi_threaded_compositor.cpp (+66/-7)
To merge this branch: bzr merge lp:~alan-griffiths/mir/nested-sessions-dont-post-buffers-until-something-happens
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Alexandros Frantzis (community) Approve
Alberto Aguirre (community) Approve
Review via email: mp+209107@code.launchpad.net

Commit message

compositor: Don't automatically paint the framebuffer when compositing starts. (This is really only appropriate for a host session.)

Description of the change

compositor: Don't automatically paint the framebuffer when compositing starts. (This is really only appropriate for a host session.)

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

299 + compositor.start();
300 + std::this_thread::sleep_for(std::chrono::milliseconds(100));

I think the time limit is too small for our whimsical CI. Perhaps a loop checking the condition every 20ms for 5 seconds? (5s is probably too much, but it doesn't matter since we will pay the price only in case of a failure, which should hopefully be never).

302 + // Verify we're still at zero frames
303 + EXPECT_TRUE(db_compositor_factory->check_record_count_for_each_buffer(nbuffers, composites_per_update, composites_per_update));

Wrong comment?

review: Needs Fixing
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alberto Aguirre (albaguirre) wrote :

Looks good.

review: Approve
Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

OK.

review: Approve
Revision history for this message
kevin gunn (kgunn72) wrote :
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

Trivial merge conflicts resolved.

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
1=== modified file 'examples/render_surfaces.cpp'
2--- examples/render_surfaces.cpp 2014-03-04 10:10:23 +0000
3+++ examples/render_surfaces.cpp 2014-03-05 17:19:32 +0000
4@@ -17,6 +17,7 @@
5 */
6
7 #include "mir/compositor/display_buffer_compositor_factory.h"
8+#include "mir/server_status_listener.h"
9 #include "mir/compositor/display_buffer_compositor.h"
10 #include "mir/options/default_configuration.h"
11 #include "mir/graphics/graphic_buffer_allocator.h"
12@@ -86,6 +87,7 @@
13
14 namespace
15 {
16+std::atomic<bool> created{false};
17 bool input_is_on = false;
18 std::weak_ptr<mg::Cursor> cursor;
19 static const uint32_t bg_color = 0x00000000;
20@@ -326,6 +328,31 @@
21 }
22 ///\internal [RenderResourcesBufferInitializer_tag]
23
24+ // Unless the compositor starts before we create the surfaces it won't respond to
25+ // the change notification that causes.
26+ std::shared_ptr<mir::ServerStatusListener> the_server_status_listener()
27+ {
28+ struct ServerStatusListener : mir::ServerStatusListener
29+ {
30+ ServerStatusListener(std::function<void()> create_surfaces, std::shared_ptr<mir::ServerStatusListener> wrapped) :
31+ create_surfaces(create_surfaces), wrapped(wrapped) {}
32+
33+ virtual void paused() override { wrapped->paused(); }
34+ virtual void resumed() override { wrapped->resumed(); }
35+ virtual void started() override { wrapped->started(); create_surfaces(); create_surfaces = []{}; }
36+
37+ std::function<void()> create_surfaces;
38+ std::shared_ptr<mir::ServerStatusListener> const wrapped;
39+ };
40+
41+ return server_status_listener(
42+ [this]()
43+ {
44+ auto wrapped = ServerConfiguration::the_server_status_listener();
45+ return std::make_shared<ServerStatusListener>([this] { create_surfaces(); }, wrapped);
46+ });
47+ }
48+
49 ///\internal [RenderSurfacesDisplayBufferCompositor_tag]
50 // Decorate the DefaultDisplayBufferCompositor in order to move surfaces.
51 std::shared_ptr<mc::DisplayBufferCompositorFactory> the_display_buffer_compositor_factory() override
52@@ -344,6 +371,7 @@
53
54 bool composite()
55 {
56+ while (!created) std::this_thread::yield();
57 animate_cursor();
58 stop_watch.stop();
59 if (stop_watch.elapsed_seconds_since_last_restart() >= 1)
60@@ -460,6 +488,8 @@
61 2.0f * M_PI * cos(i));
62 ++i;
63 }
64+
65+ created = true;
66 }
67
68 bool input_is_on()
69@@ -493,8 +523,6 @@
70
71 mir::run_mir(conf, [&](mir::DisplayServer&)
72 {
73- conf.create_surfaces();
74-
75 cursor = conf.the_cursor();
76
77 input_is_on = conf.input_is_on();
78
79=== modified file 'src/server/compositor/default_configuration.cpp'
80--- src/server/compositor/default_configuration.cpp 2014-02-28 13:51:43 +0000
81+++ src/server/compositor/default_configuration.cpp 2014-03-05 17:19:32 +0000
82@@ -25,6 +25,7 @@
83 #include "compositing_screencast.h"
84
85 #include "mir/frontend/screencast.h"
86+#include "mir/options/configuration.h"
87
88 #include <boost/throw_exception.hpp>
89
90@@ -59,10 +60,12 @@
91 return compositor(
92 [this]()
93 {
94- return std::make_shared<mc::MultiThreadedCompositor>(the_display(),
95- the_scene(),
96- the_display_buffer_compositor_factory(),
97- the_compositor_report());
98+ return std::make_shared<mc::MultiThreadedCompositor>(
99+ the_display(),
100+ the_scene(),
101+ the_display_buffer_compositor_factory(),
102+ the_compositor_report(),
103+ !the_options()->is_set(options::host_socket_opt));
104 });
105 }
106
107
108=== modified file 'src/server/compositor/multi_threaded_compositor.cpp'
109--- src/server/compositor/multi_threaded_compositor.cpp 2014-03-04 12:16:12 +0000
110+++ src/server/compositor/multi_threaded_compositor.cpp 2014-03-05 17:19:32 +0000
111@@ -147,12 +147,14 @@
112 std::shared_ptr<mg::Display> const& display,
113 std::shared_ptr<mc::Scene> const& scene,
114 std::shared_ptr<DisplayBufferCompositorFactory> const& db_compositor_factory,
115- std::shared_ptr<CompositorReport> const& compositor_report)
116+ std::shared_ptr<CompositorReport> const& compositor_report,
117+ bool compose_on_start)
118 : display{display},
119 scene{scene},
120 display_buffer_compositor_factory{db_compositor_factory},
121 report{compositor_report},
122- started{false}
123+ started{false},
124+ compose_on_start{compose_on_start}
125 {
126 }
127
128@@ -161,6 +163,14 @@
129 stop();
130 }
131
132+void mc::MultiThreadedCompositor::schedule_compositing()
133+{
134+ std::unique_lock<std::mutex> lk(started_guard);
135+ report->scheduled();
136+ for (auto& f : thread_functors)
137+ f->schedule_compositing();
138+}
139+
140 void mc::MultiThreadedCompositor::start()
141 {
142 std::unique_lock<std::mutex> lk(started_guard);
143@@ -184,16 +194,18 @@
144 /* Recomposite whenever the scene changes */
145 scene->set_change_callback([this]()
146 {
147- report->scheduled();
148- for (auto& f : thread_functors)
149- f->schedule_compositing();
150+ schedule_compositing();
151 });
152
153- /* First render */
154- for (auto& f : thread_functors)
155- f->schedule_compositing();
156-
157 started = true;
158+
159+ /* Optional first render */
160+ if (compose_on_start)
161+ {
162+ lk.unlock();
163+ schedule_compositing();
164+ }
165+
166 }
167
168 void mc::MultiThreadedCompositor::stop()
169@@ -204,7 +216,9 @@
170 return;
171 }
172
173+ lk.unlock();
174 scene->set_change_callback([]{});
175+ lk.lock();
176
177 for (auto& f : thread_functors)
178 f->stop();
179@@ -218,4 +232,8 @@
180 report->stopped();
181
182 started = false;
183+
184+ // If the compositor is restarted we've likely got clients blocked
185+ // so we will need to schedule compositing immediately
186+ compose_on_start = true;
187 }
188
189=== modified file 'src/server/compositor/multi_threaded_compositor.h'
190--- src/server/compositor/multi_threaded_compositor.h 2014-03-05 07:21:46 +0000
191+++ src/server/compositor/multi_threaded_compositor.h 2014-03-05 17:19:32 +0000
192@@ -46,7 +46,8 @@
193 MultiThreadedCompositor(std::shared_ptr<graphics::Display> const& display,
194 std::shared_ptr<Scene> const& scene,
195 std::shared_ptr<DisplayBufferCompositorFactory> const& db_compositor_factory,
196- std::shared_ptr<CompositorReport> const& compositor_report);
197+ std::shared_ptr<CompositorReport> const& compositor_report,
198+ bool compose_on_start);
199 ~MultiThreadedCompositor();
200
201 void start();
202@@ -63,6 +64,9 @@
203
204 std::mutex started_guard;
205 bool started;
206+ bool compose_on_start;
207+
208+ void schedule_compositing();
209 };
210
211 }
212
213=== modified file 'tests/unit-tests/compositor/test_multi_threaded_compositor.cpp'
214--- tests/unit-tests/compositor/test_multi_threaded_compositor.cpp 2014-03-05 07:21:46 +0000
215+++ tests/unit-tests/compositor/test_multi_threaded_compositor.cpp 2014-03-05 17:19:32 +0000
216@@ -324,7 +324,7 @@
217 auto display = std::make_shared<StubDisplay>(nbuffers);
218 auto scene = std::make_shared<StubScene>();
219 auto db_compositor_factory = std::make_shared<RecordingDisplayBufferCompositorFactory>();
220- mc::MultiThreadedCompositor compositor{display, scene, db_compositor_factory, null_report};
221+ mc::MultiThreadedCompositor compositor{display, scene, db_compositor_factory, null_report, true};
222
223 compositor.start();
224
225@@ -348,7 +348,8 @@
226 auto mock_report = std::make_shared<mtd::MockCompositorReport>();
227 mc::MultiThreadedCompositor compositor{display, scene,
228 db_compositor_factory,
229- mock_report};
230+ mock_report,
231+ true};
232
233 EXPECT_CALL(*mock_report, started())
234 .Times(1);
235@@ -363,7 +364,7 @@
236 EXPECT_CALL(*mock_report, added_display(_,_,_,_,_))
237 .Times(1);
238 EXPECT_CALL(*mock_report, scheduled())
239- .Times(1);
240+ .Times(2);
241
242 display->for_each_mock_buffer([](mtd::MockDisplayBuffer& mock_buf)
243 {
244@@ -398,7 +399,7 @@
245 auto display = std::make_shared<StubDisplay>(nbuffers);
246 auto scene = std::make_shared<StubScene>();
247 auto db_compositor_factory = std::make_shared<RecordingDisplayBufferCompositorFactory>();
248- mc::MultiThreadedCompositor compositor{display, scene, db_compositor_factory, null_report};
249+ mc::MultiThreadedCompositor compositor{display, scene, db_compositor_factory, null_report, true};
250
251 // Verify we're actually starting at zero frames
252 EXPECT_TRUE(db_compositor_factory->check_record_count_for_each_buffer(nbuffers, 0, 0));
253@@ -449,6 +450,64 @@
254 compositor.stop();
255 }
256
257+TEST(MultiThreadedCompositor, when_no_initial_composite_is_needed_there_is_none)
258+{
259+ using namespace testing;
260+
261+ unsigned int const nbuffers = 3;
262+
263+ auto display = std::make_shared<StubDisplay>(nbuffers);
264+ auto scene = std::make_shared<StubScene>();
265+ auto db_compositor_factory = std::make_shared<RecordingDisplayBufferCompositorFactory>();
266+ mc::MultiThreadedCompositor compositor{display, scene, db_compositor_factory, null_report, false};
267+
268+ // Verify we're actually starting at zero frames
269+ ASSERT_TRUE(db_compositor_factory->check_record_count_for_each_buffer(nbuffers, 0, 0));
270+
271+ compositor.start();
272+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
273+
274+ // Verify we're still at zero frames
275+ EXPECT_TRUE(db_compositor_factory->check_record_count_for_each_buffer(nbuffers, 0, 0));
276+
277+ compositor.stop();
278+}
279+
280+TEST(MultiThreadedCompositor, when_no_initial_composite_is_needed_we_still_composite_on_restart)
281+{
282+ using namespace testing;
283+
284+ unsigned int const nbuffers = 3;
285+
286+ auto display = std::make_shared<StubDisplay>(nbuffers);
287+ auto scene = std::make_shared<StubScene>();
288+ auto db_compositor_factory = std::make_shared<RecordingDisplayBufferCompositorFactory>();
289+ mc::MultiThreadedCompositor compositor{display, scene, db_compositor_factory, null_report, false};
290+
291+ compositor.start();
292+
293+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
294+
295+ // Verify we're actually starting at zero frames
296+ ASSERT_TRUE(db_compositor_factory->check_record_count_for_each_buffer(nbuffers, 0, 0));
297+
298+ compositor.stop();
299+ compositor.start();
300+
301+ for (int countdown = 100;
302+ countdown != 0 &&
303+ !db_compositor_factory->check_record_count_for_each_buffer(nbuffers, composites_per_update, composites_per_update);
304+ --countdown)
305+ {
306+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
307+ }
308+
309+ // Verify we composited the expected frame
310+ EXPECT_TRUE(db_compositor_factory->check_record_count_for_each_buffer(nbuffers, composites_per_update, composites_per_update));
311+
312+ compositor.stop();
313+}
314+
315 TEST(MultiThreadedCompositor, surface_update_from_render_doesnt_deadlock)
316 {
317 using namespace testing;
318@@ -458,7 +517,7 @@
319 auto display = std::make_shared<StubDisplay>(nbuffers);
320 auto scene = std::make_shared<StubScene>();
321 auto db_compositor_factory = std::make_shared<SurfaceUpdatingDisplayBufferCompositorFactory>(scene);
322- mc::MultiThreadedCompositor compositor{display, scene, db_compositor_factory, null_report};
323+ mc::MultiThreadedCompositor compositor{display, scene, db_compositor_factory, null_report, true};
324
325 compositor.start();
326
327@@ -477,7 +536,7 @@
328 auto display = std::make_shared<StubDisplayWithMockBuffers>(nbuffers);
329 auto scene = std::make_shared<StubScene>();
330 auto db_compositor_factory = std::make_shared<NullDisplayBufferCompositorFactory>();
331- mc::MultiThreadedCompositor compositor{display, scene, db_compositor_factory, null_report};
332+ mc::MultiThreadedCompositor compositor{display, scene, db_compositor_factory, null_report, true};
333
334 display->for_each_mock_buffer([](mtd::MockDisplayBuffer& mock_buf)
335 {
336@@ -505,7 +564,7 @@
337 EXPECT_CALL(*mock_scene, set_change_callback(testing::_))
338 .Times(2);
339
340- mc::MultiThreadedCompositor compositor{display, mock_scene, db_compositor_factory, mock_report};
341+ mc::MultiThreadedCompositor compositor{display, mock_scene, db_compositor_factory, mock_report, true};
342
343 compositor.start();
344 compositor.start();

Subscribers

People subscribed via source and target branches