Merge lp:~mir-team/mir/introduce-scene-observer into lp:mir
- introduce-scene-observer
- Merge into development-branch
Status: | Superseded |
---|---|
Proposed branch: | lp:~mir-team/mir/introduce-scene-observer |
Merge into: | lp:mir |
Diff against target: |
1103 lines (+594/-77) (has conflicts) 17 files modified
include/server/mir/compositor/scene.h (+7/-9) include/server/mir/scene/legacy_scene_change_notification.h (+58/-0) include/server/mir/scene/observer.h (+50/-0) include/test/mir_test_doubles/mock_scene.h (+3/-3) include/test/mir_test_doubles/mock_surface.h (+1/-0) src/server/compositor/multi_threaded_compositor.cpp (+20/-3) src/server/compositor/multi_threaded_compositor.h (+8/-0) src/server/scene/CMakeLists.txt (+2/-1) src/server/scene/legacy_scene_change_notification.cpp (+71/-0) src/server/scene/surface_stack.cpp (+76/-16) src/server/scene/surface_stack.h (+22/-6) tests/integration-tests/test_surface_first_frame_sync.cpp (+15/-11) tests/unit-tests/compositor/test_default_display_buffer_compositor.cpp (+9/-2) tests/unit-tests/compositor/test_multi_threaded_compositor.cpp (+45/-24) tests/unit-tests/scene/CMakeLists.txt (+1/-0) tests/unit-tests/scene/test_legacy_scene_change_notification.cpp (+96/-0) tests/unit-tests/scene/test_surface_stack.cpp (+110/-2) Text conflict in src/server/scene/surface_stack.cpp |
To merge this branch: | bzr merge lp:~mir-team/mir/introduce-scene-observer |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alan Griffiths | Needs Fixing | ||
Alberto Aguirre (community) | Needs Fixing | ||
PS Jenkins bot (community) | continuous-integration | Needs Fixing | |
Kevin DuBois (community) | Approve | ||
Alexandros Frantzis (community) | Approve | ||
Review via email: mp+215969@code.launchpad.net |
This proposal supersedes a proposal from 2014-04-15.
This proposal has been superseded by a proposal from 2014-04-23.
Commit message
Introduce a mir::scene:
Description of the change
An alternative to:
https:/
Which better mirrors the other interfaces and supports the future needs of the compositor.
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1530
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alexandros Frantzis (afrantzis) wrote : | # |
Looks good overall.
Nits:
29 + virtual void add_observer(
30 + virtual void remove_
Adding or removing an observer from within a scene::Observer can cause a deadlock. It would be good to document this.
442 + std::unique_
We should prefer std::lock_guard<> which is slighly more efficient.
Kevin DuBois (kdub) wrote : | # |
+1! I hope that in the future the MultiThreadedCo
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1533
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Alberto Aguirre (albaguirre) wrote : | # |
~~~
784 + scene->
~~~
The test needs to be modified so starts throws to check for cleanup. The above won't do it anymore.
~~~
427 + std::unique_
428 +
429 + for (auto observer : observers)
430 + observer-
and the rest...
~~~
During a callback if an observer modifies the scene either directly or indirectly (which could be subtle) you can end up in deadlock. Maybe copy the observer list and release the lock before calling back?
Alan Griffiths (alan-griffiths) wrote : | # |
I'm happy with this approach, but...
491 + void remove_
I think that the observed object should own the observer and that the client code should only ever need a weak_ptr (and then only if it intended to remove it at some point). Accordingly this signature should be:
void remove_
~~~~
124 +// A simple implementation of surface observer which forwards all changes to a provided callback.
125 +// Also installs surface observers on each added surface which in turn forward each change to
126 +// said callback.
127 +class SimpleObserver : public Observer
I think a better name would be LegacySceneChan
A (pre-existing and non-blocking) issue I've just noticed is that we don't remove SurfaceObservers when surfaces are removed from the scene - so that *if* surfaces were repeatedly added and removed then we'd have an increasing number of them.
~~~~
74 + virtual void surface_
75 + virtual void surface_
I'm not (yet) convinced that observers should be given shared ownership like this. I note that a pointer/reference to the surface is needed in SimpleObserver, but the ownership transfer implied by shared_ptr worries me.
~~~~
We'll likely want to supply more information about reordering than the current interface provides for.
Preview Diff
1 | === modified file 'include/server/mir/compositor/scene.h' |
2 | --- include/server/mir/compositor/scene.h 2014-04-15 05:31:19 +0000 |
3 | +++ include/server/mir/compositor/scene.h 2014-04-23 22:49:30 +0000 |
4 | @@ -27,6 +27,11 @@ |
5 | |
6 | namespace mir |
7 | { |
8 | +namespace scene |
9 | +{ |
10 | +class Observer; |
11 | +} |
12 | + |
13 | namespace compositor |
14 | { |
15 | |
16 | @@ -41,15 +46,8 @@ |
17 | */ |
18 | virtual graphics::RenderableList generate_renderable_list() const = 0; |
19 | |
20 | - /** |
21 | - * Sets a callback to be called whenever the state of the |
22 | - * Scene changes. |
23 | - * |
24 | - * The supplied callback should not directly or indirectly (e.g., |
25 | - * by changing a property of a surface) change the state of |
26 | - * the Scene, otherwise a deadlock may occur. |
27 | - */ |
28 | - virtual void set_change_callback(std::function<void()> const& f) = 0; |
29 | + virtual void add_observer(std::shared_ptr<scene::Observer> const& observer) = 0; |
30 | + virtual void remove_observer(std::weak_ptr<scene::Observer> const& observer) = 0; |
31 | |
32 | protected: |
33 | Scene() = default; |
34 | |
35 | === added file 'include/server/mir/scene/legacy_scene_change_notification.h' |
36 | --- include/server/mir/scene/legacy_scene_change_notification.h 1970-01-01 00:00:00 +0000 |
37 | +++ include/server/mir/scene/legacy_scene_change_notification.h 2014-04-23 22:49:30 +0000 |
38 | @@ -0,0 +1,58 @@ |
39 | +/* |
40 | + * Copyright © 2014 Canonical Ltd. |
41 | + * |
42 | + * This program is free software: you can redistribute it and/or modify it |
43 | + * under the terms of the GNU General Public License version 3, |
44 | + * as published by the Free Software Foundation. |
45 | + * |
46 | + * This program is distributed in the hope that it will be useful, |
47 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
48 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
49 | + * GNU General Public License for more details. |
50 | + * |
51 | + * You should have received a copy of the GNU General Public License |
52 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
53 | + * |
54 | + * Authored by: Robert Carr <robert.carr@canonical.com> |
55 | + */ |
56 | + |
57 | +#ifndef MIR_SCENE_SIMPLE_OBSERVER_H_ |
58 | +#define MIR_SCENE_SIMPLE_OBSERVER_H_ |
59 | + |
60 | +#include "mir/scene/observer.h" |
61 | + |
62 | +#include <functional> |
63 | +#include <map> |
64 | +#include <mutex> |
65 | + |
66 | +namespace mir |
67 | +{ |
68 | +namespace scene |
69 | +{ |
70 | +class SurfaceObserver; |
71 | + |
72 | +// A simple implementation of surface observer which forwards all changes to a provided callback. |
73 | +// Also installs surface observers on each added surface which in turn forward each change to |
74 | +// said callback. |
75 | +class LegacySceneChangeNotification : public Observer |
76 | +{ |
77 | +public: |
78 | + LegacySceneChangeNotification(std::function<void()> const& notify_change); |
79 | + ~LegacySceneChangeNotification(); |
80 | + |
81 | + void surface_added(std::shared_ptr<Surface> const& surface) override; |
82 | + void surface_removed(std::shared_ptr<Surface> const& surface) override; |
83 | + void surfaces_reordered() override; |
84 | + |
85 | +private: |
86 | + std::function<void()> notify_change; |
87 | + |
88 | + std::mutex surface_observers_guard; |
89 | + std::map<std::weak_ptr<Surface>, std::shared_ptr<SurfaceObserver>, |
90 | + std::owner_less<std::weak_ptr<Surface>>> surface_observers; |
91 | +}; |
92 | + |
93 | +} |
94 | +} // namespace mir |
95 | + |
96 | +#endif // MIR_SCENE_SIMPLE_OBSERVER_H_ |
97 | |
98 | === added file 'include/server/mir/scene/observer.h' |
99 | --- include/server/mir/scene/observer.h 1970-01-01 00:00:00 +0000 |
100 | +++ include/server/mir/scene/observer.h 2014-04-23 22:49:30 +0000 |
101 | @@ -0,0 +1,50 @@ |
102 | +/* |
103 | + * Copyright © 2014 Canonical Ltd. |
104 | + * |
105 | + * This program is free software: you can redistribute it and/or modify it |
106 | + * under the terms of the GNU General Public License version 3, |
107 | + * as published by the Free Software Foundation. |
108 | + * |
109 | + * This program is distributed in the hope that it will be useful, |
110 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
111 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
112 | + * GNU General Public License for more details. |
113 | + * |
114 | + * You should have received a copy of the GNU General Public License |
115 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
116 | + * |
117 | + * Authored by: Robert Carr <robert.carr@canonical.com> |
118 | + */ |
119 | + |
120 | +#ifndef MIR_SCENE_OBSERVER_H_ |
121 | +#define MIR_SCENE_OBSERVER_H_ |
122 | + |
123 | +#include <memory> |
124 | + |
125 | +namespace mir |
126 | +{ |
127 | +namespace scene |
128 | +{ |
129 | +class Surface; |
130 | + |
131 | +/// An observer for top level notifications of scene changes. In order |
132 | +/// to receive more granular change notifications a user may install |
133 | +/// mir::scene::SurfaceObserver in surface_added. |
134 | +class Observer |
135 | +{ |
136 | +public: |
137 | + virtual void surface_added(std::shared_ptr<Surface> const& surface) = 0; |
138 | + virtual void surface_removed(std::shared_ptr<Surface> const& surface) = 0; |
139 | + virtual void surfaces_reordered() = 0; |
140 | + |
141 | +protected: |
142 | + Observer() = default; |
143 | + virtual ~Observer() = default; |
144 | + Observer(Observer const&) = delete; |
145 | + Observer& operator=(Observer const&) = delete; |
146 | +}; |
147 | + |
148 | +} |
149 | +} // namespace mir |
150 | + |
151 | +#endif // MIR_SCENE_OBSERVER_H_ |
152 | |
153 | === modified file 'include/test/mir_test_doubles/mock_scene.h' |
154 | --- include/test/mir_test_doubles/mock_scene.h 2014-04-15 05:31:19 +0000 |
155 | +++ include/test/mir_test_doubles/mock_scene.h 2014-04-23 22:49:30 +0000 |
156 | @@ -38,9 +38,9 @@ |
157 | .WillByDefault(testing::Return(graphics::RenderableList{})); |
158 | } |
159 | MOCK_CONST_METHOD0(generate_renderable_list, graphics::RenderableList()); |
160 | - MOCK_METHOD1(set_change_callback, void(std::function<void()> const&)); |
161 | - MOCK_METHOD0(lock, void()); |
162 | - MOCK_METHOD0(unlock, void()); |
163 | + |
164 | + MOCK_METHOD1(add_observer, void(std::shared_ptr<scene::Observer> const&)); |
165 | + MOCK_METHOD1(remove_observer, void(std::weak_ptr<scene::Observer> const&)); |
166 | }; |
167 | |
168 | } // namespace doubles |
169 | |
170 | === modified file 'include/test/mir_test_doubles/mock_surface.h' |
171 | --- include/test/mir_test_doubles/mock_surface.h 2014-04-15 05:31:19 +0000 |
172 | +++ include/test/mir_test_doubles/mock_surface.h 2014-04-23 22:49:30 +0000 |
173 | @@ -63,6 +63,7 @@ |
174 | MOCK_METHOD2(configure, int(MirSurfaceAttrib, int)); |
175 | MOCK_METHOD1(take_input_focus, void(std::shared_ptr<shell::InputTargeter> const&)); |
176 | MOCK_METHOD1(add_observer, void(std::shared_ptr<scene::SurfaceObserver> const&)); |
177 | + MOCK_METHOD1(remove_observer, void(std::shared_ptr<scene::SurfaceObserver> const&)); |
178 | }; |
179 | |
180 | } |
181 | |
182 | === modified file 'src/server/compositor/multi_threaded_compositor.cpp' |
183 | --- src/server/compositor/multi_threaded_compositor.cpp 2014-04-17 01:34:35 +0000 |
184 | +++ src/server/compositor/multi_threaded_compositor.cpp 2014-04-23 22:49:30 +0000 |
185 | @@ -23,6 +23,9 @@ |
186 | #include "mir/compositor/display_buffer_compositor_factory.h" |
187 | #include "mir/compositor/scene.h" |
188 | #include "mir/compositor/compositor_report.h" |
189 | +#include "mir/scene/legacy_scene_change_notification.h" |
190 | +#include "mir/scene/surface_observer.h" |
191 | +#include "mir/scene/surface.h" |
192 | |
193 | #include <thread> |
194 | #include <condition_variable> |
195 | @@ -31,6 +34,7 @@ |
196 | |
197 | namespace mc = mir::compositor; |
198 | namespace mg = mir::graphics; |
199 | +namespace ms = mir::scene; |
200 | |
201 | namespace |
202 | { |
203 | @@ -259,6 +263,7 @@ |
204 | void mc::MultiThreadedCompositor::schedule_compositing() |
205 | { |
206 | std::unique_lock<std::mutex> lk(state_guard); |
207 | + |
208 | report->scheduled(); |
209 | for (auto& f : thread_functors) |
210 | f->schedule_compositing(); |
211 | @@ -282,8 +287,7 @@ |
212 | }}; |
213 | |
214 | lk.unlock(); |
215 | - /* Recomposite whenever the scene changes */ |
216 | - scene->set_change_callback([this]() { schedule_compositing(); }); |
217 | + add_observer(); |
218 | lk.lock(); |
219 | |
220 | create_compositing_threads(); |
221 | @@ -314,7 +318,7 @@ |
222 | }}; |
223 | |
224 | lk.unlock(); |
225 | - scene->set_change_callback([]{}); |
226 | + scene->remove_observer(observer); |
227 | lk.lock(); |
228 | |
229 | destroy_compositing_threads(lk); |
230 | @@ -370,3 +374,16 @@ |
231 | |
232 | state = CompositorState::stopped; |
233 | } |
234 | + |
235 | +void mc::MultiThreadedCompositor::add_observer() |
236 | +{ |
237 | + auto strong_observer = std::make_shared<ms::LegacySceneChangeNotification>([this]() |
238 | + { |
239 | + /* Recomposite whenever the scene changes */ |
240 | + schedule_compositing(); |
241 | + }); |
242 | + observer = strong_observer; |
243 | + |
244 | + scene->add_observer(strong_observer); |
245 | +} |
246 | + |
247 | |
248 | === modified file 'src/server/compositor/multi_threaded_compositor.h' |
249 | --- src/server/compositor/multi_threaded_compositor.h 2014-04-14 18:34:06 +0000 |
250 | +++ src/server/compositor/multi_threaded_compositor.h 2014-04-23 22:49:30 +0000 |
251 | @@ -32,6 +32,11 @@ |
252 | { |
253 | class Display; |
254 | } |
255 | +namespace scene |
256 | +{ |
257 | +class Observer; |
258 | +} |
259 | + |
260 | namespace compositor |
261 | { |
262 | |
263 | @@ -78,6 +83,9 @@ |
264 | bool compose_on_start; |
265 | |
266 | void schedule_compositing(); |
267 | + |
268 | + void add_observer(); |
269 | + std::weak_ptr<mir::scene::Observer> observer; |
270 | }; |
271 | |
272 | } |
273 | |
274 | === modified file 'src/server/scene/CMakeLists.txt' |
275 | --- src/server/scene/CMakeLists.txt 2014-04-17 13:55:46 +0000 |
276 | +++ src/server/scene/CMakeLists.txt 2014-04-23 22:49:30 +0000 |
277 | @@ -8,7 +8,6 @@ |
278 | default_session_container.cpp |
279 | gl_pixel_buffer.cpp |
280 | global_event_sender.cpp |
281 | - legacy_surface_change_notification.cpp |
282 | mediating_display_changer.cpp |
283 | session_manager.cpp |
284 | surface_allocator.cpp |
285 | @@ -18,4 +17,6 @@ |
286 | surface_event_source.cpp |
287 | surface_observer.cpp |
288 | threaded_snapshot_strategy.cpp |
289 | + legacy_scene_change_notification.cpp |
290 | + legacy_surface_change_notification.cpp |
291 | ) |
292 | |
293 | === added file 'src/server/scene/legacy_scene_change_notification.cpp' |
294 | --- src/server/scene/legacy_scene_change_notification.cpp 1970-01-01 00:00:00 +0000 |
295 | +++ src/server/scene/legacy_scene_change_notification.cpp 2014-04-23 22:49:30 +0000 |
296 | @@ -0,0 +1,71 @@ |
297 | +/* |
298 | + * Copyright © 2014 Canonical Ltd. |
299 | + * |
300 | + * This program is free software: you can redistribute it and/or modify it |
301 | + * under the terms of the GNU General Public License version 3, |
302 | + * as published by the Free Software Foundation. |
303 | + * |
304 | + * This program is distributed in the hope that it will be useful, |
305 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
306 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
307 | + * GNU General Public License for more details. |
308 | + * |
309 | + * You should have received a copy of the GNU General Public License |
310 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
311 | + * |
312 | + * Authored by: Robert Carr <robert.carr@canonical.com> |
313 | + */ |
314 | + |
315 | +#include "legacy_surface_change_notification.h" |
316 | + |
317 | +#include "mir/scene/legacy_scene_change_notification.h" |
318 | +#include "mir/scene/surface.h" |
319 | + |
320 | +#include <boost/throw_exception.hpp> |
321 | + |
322 | +namespace ms = mir::scene; |
323 | + |
324 | +ms::LegacySceneChangeNotification::LegacySceneChangeNotification(std::function<void()> const& notify_change) |
325 | + : notify_change(notify_change) |
326 | +{ |
327 | +} |
328 | + |
329 | +ms::LegacySceneChangeNotification::~LegacySceneChangeNotification() |
330 | +{ |
331 | + std::unique_lock<decltype(surface_observers_guard)> lg(surface_observers_guard); |
332 | + for (auto &kv : surface_observers) |
333 | + { |
334 | + auto surface = kv.first.lock(); |
335 | + if (surface) |
336 | + surface->remove_observer(kv.second); |
337 | + } |
338 | +} |
339 | + |
340 | +void ms::LegacySceneChangeNotification::surface_added(std::shared_ptr<ms::Surface> const& surface) |
341 | +{ |
342 | + auto observer = std::make_shared<ms::LegacySurfaceChangeNotification>(notify_change); |
343 | + surface->add_observer(observer); |
344 | + |
345 | + { |
346 | + std::unique_lock<decltype(surface_observers_guard)> lg(surface_observers_guard); |
347 | + surface_observers[surface] = observer; |
348 | + } |
349 | + notify_change(); |
350 | +} |
351 | + |
352 | +void ms::LegacySceneChangeNotification::surface_removed(std::shared_ptr<ms::Surface> const& surface) |
353 | +{ |
354 | + { |
355 | + std::unique_lock<decltype(surface_observers_guard)> lg(surface_observers_guard); |
356 | + auto it = surface_observers.find(surface); |
357 | + if (it != surface_observers.end()) |
358 | + surface_observers.erase(it); |
359 | + } |
360 | + notify_change(); |
361 | +} |
362 | + |
363 | +void ms::LegacySceneChangeNotification::surfaces_reordered() |
364 | +{ |
365 | + notify_change(); |
366 | +} |
367 | + |
368 | |
369 | === modified file 'src/server/scene/surface_stack.cpp' |
370 | --- src/server/scene/surface_stack.cpp 2014-04-22 21:37:27 +0000 |
371 | +++ src/server/scene/surface_stack.cpp 2014-04-23 22:49:30 +0000 |
372 | @@ -23,7 +23,6 @@ |
373 | #include "surface_stack.h" |
374 | #include "mir/compositor/buffer_stream.h" |
375 | #include "mir/scene/input_registrar.h" |
376 | -#include "legacy_surface_change_notification.h" |
377 | #include "mir/input/input_channel_factory.h" |
378 | #include "mir/scene/scene_report.h" |
379 | |
380 | @@ -52,9 +51,7 @@ |
381 | std::shared_ptr<InputRegistrar> const& input_registrar, |
382 | std::shared_ptr<SceneReport> const& report) : |
383 | input_registrar{input_registrar}, |
384 | - report{report}, |
385 | - change_cb{[this]() { emit_change_notification(); }}, |
386 | - notify_change{[]{}} |
387 | + report{report} |
388 | { |
389 | } |
390 | |
391 | @@ -125,13 +122,6 @@ |
392 | return list; |
393 | } |
394 | |
395 | -void ms::SurfaceStack::set_change_callback(std::function<void()> const& f) |
396 | -{ |
397 | - std::lock_guard<decltype(notify_change_mutex)> lg(notify_change_mutex); |
398 | - assert(f); |
399 | - notify_change = f; |
400 | -} |
401 | - |
402 | void ms::SurfaceStack::add_surface( |
403 | std::shared_ptr<Surface> const& surface, |
404 | DepthId depth, |
405 | @@ -142,10 +132,9 @@ |
406 | layers_by_depth[depth].push_back(surface); |
407 | } |
408 | input_registrar->input_channel_opened(surface->input_channel(), surface, input_mode); |
409 | + observers.surface_added(surface); |
410 | + |
411 | report->surface_added(surface.get(), surface.get()->name()); |
412 | - auto const observer = std::make_shared<LegacySurfaceChangeNotification>(change_cb); |
413 | - surface->add_observer(observer); |
414 | - emit_change_notification(); |
415 | } |
416 | |
417 | |
418 | @@ -174,12 +163,14 @@ |
419 | if (found_surface) |
420 | { |
421 | input_registrar->input_channel_closed(keep_alive->input_channel()); |
422 | + observers.surface_removed(keep_alive); |
423 | + |
424 | report->surface_removed(keep_alive.get(), keep_alive.get()->name()); |
425 | - emit_change_notification(); |
426 | } |
427 | // TODO: error logging when surface not found |
428 | } |
429 | |
430 | +<<<<<<< TREE |
431 | void ms::SurfaceStack::emit_change_notification() |
432 | { |
433 | std::lock_guard<decltype(notify_change_mutex)> lg(notify_change_mutex); |
434 | @@ -187,6 +178,9 @@ |
435 | } |
436 | |
437 | void ms::SurfaceStack::for_each(std::function<void(std::shared_ptr<mi::Surface> const&)> const& callback) |
438 | +======= |
439 | +void ms::SurfaceStack::for_each(std::function<void(std::shared_ptr<mi::InputChannel> const&)> const& callback) |
440 | +>>>>>>> MERGE-SOURCE |
441 | { |
442 | std::lock_guard<decltype(guard)> lg(guard); |
443 | for (auto &layer : layers_by_depth) |
444 | @@ -213,7 +207,7 @@ |
445 | surfaces.push_back(surface); |
446 | |
447 | ul.unlock(); |
448 | - emit_change_notification(); |
449 | + observers.surfaces_reordered(); |
450 | |
451 | return; |
452 | } |
453 | @@ -222,3 +216,69 @@ |
454 | |
455 | BOOST_THROW_EXCEPTION(std::runtime_error("Invalid surface")); |
456 | } |
457 | + |
458 | +void ms::SurfaceStack::add_observer(std::shared_ptr<ms::Observer> const& observer) |
459 | +{ |
460 | + observers.add_observer(observer); |
461 | + |
462 | + // Notify observer of existing surfaces |
463 | + { |
464 | + std::unique_lock<decltype(guard)> ul(guard); |
465 | + for (auto &layer : layers_by_depth) |
466 | + { |
467 | + for (auto &surface : layer.second) |
468 | + observer->surface_added(surface); |
469 | + } |
470 | + } |
471 | +} |
472 | + |
473 | +void ms::SurfaceStack::remove_observer(std::weak_ptr<ms::Observer> const& observer) |
474 | +{ |
475 | + observers.remove_observer(observer); |
476 | +} |
477 | + |
478 | +void ms::Observers::surface_added(std::shared_ptr<ms::Surface> const& surface) |
479 | +{ |
480 | + std::unique_lock<decltype(mutex)> lg(mutex); |
481 | + |
482 | + for (auto observer : observers) |
483 | + observer->surface_added(surface); |
484 | +} |
485 | + |
486 | +void ms::Observers::surface_removed(std::shared_ptr<ms::Surface> const& surface) |
487 | +{ |
488 | + std::unique_lock<decltype(mutex)> lg(mutex); |
489 | + |
490 | + for (auto observer : observers) |
491 | + observer->surface_removed(surface); |
492 | +} |
493 | + |
494 | +void ms::Observers::surfaces_reordered() |
495 | +{ |
496 | + std::unique_lock<decltype(mutex)> lg(mutex); |
497 | + |
498 | + for (auto observer : observers) |
499 | + observer->surfaces_reordered(); |
500 | +} |
501 | + |
502 | +void ms::Observers::add_observer(std::shared_ptr<ms::Observer> const& observer) |
503 | +{ |
504 | + std::unique_lock<decltype(mutex)> lg(mutex); |
505 | + |
506 | + observers.push_back(observer); |
507 | +} |
508 | + |
509 | +void ms::Observers::remove_observer(std::weak_ptr<ms::Observer> const& observer) |
510 | +{ |
511 | + std::unique_lock<decltype(mutex)> lg(mutex); |
512 | + |
513 | + auto o = observer.lock(); |
514 | + if (!o) |
515 | + BOOST_THROW_EXCEPTION(std::logic_error("Invalid observer (destroyed)")); |
516 | + |
517 | + auto it = std::find(observers.begin(), observers.end(), o); |
518 | + if (it == observers.end()) |
519 | + BOOST_THROW_EXCEPTION(std::runtime_error("Invalid observer (not previously added)")); |
520 | + |
521 | + observers.erase(it); |
522 | +} |
523 | |
524 | === modified file 'src/server/scene/surface_stack.h' |
525 | --- src/server/scene/surface_stack.h 2014-04-15 16:41:27 +0000 |
526 | +++ src/server/scene/surface_stack.h 2014-04-23 22:49:30 +0000 |
527 | @@ -23,6 +23,7 @@ |
528 | |
529 | #include "mir/compositor/scene.h" |
530 | #include "mir/scene/depth_id.h" |
531 | +#include "mir/scene/observer.h" |
532 | #include "mir/input/input_targets.h" |
533 | |
534 | #include <memory> |
535 | @@ -57,6 +58,22 @@ |
536 | class BasicSurface; |
537 | class SceneReport; |
538 | |
539 | +class Observers : public Observer |
540 | +{ |
541 | +public: |
542 | + // ms::Observer |
543 | + void surface_added(std::shared_ptr<Surface> const& surface) override; |
544 | + void surface_removed(std::shared_ptr<Surface> const& surface) override; |
545 | + void surfaces_reordered(); |
546 | + |
547 | + void add_observer(std::shared_ptr<Observer> const& observer); |
548 | + void remove_observer(std::weak_ptr<Observer> const& observer); |
549 | + |
550 | +private: |
551 | + std::mutex mutex; |
552 | + std::vector<std::shared_ptr<Observer>> observers; |
553 | +}; |
554 | + |
555 | class SurfaceStack : public compositor::Scene, public input::InputTargets, public SurfaceStackModel |
556 | { |
557 | public: |
558 | @@ -67,7 +84,6 @@ |
559 | |
560 | // From Scene |
561 | graphics::RenderableList generate_renderable_list() const; |
562 | - virtual void set_change_callback(std::function<void()> const& f); |
563 | |
564 | // From InputTargets |
565 | void for_each(std::function<void(std::shared_ptr<input::Surface> const&)> const& callback); |
566 | @@ -80,23 +96,23 @@ |
567 | std::shared_ptr<Surface> const& surface, |
568 | DepthId depth, |
569 | input::InputReceptionMode input_mode) override; |
570 | + |
571 | + void add_observer(std::shared_ptr<Observer> const& observer) override; |
572 | + void remove_observer(std::weak_ptr<Observer> const& observer) override; |
573 | |
574 | private: |
575 | SurfaceStack(const SurfaceStack&) = delete; |
576 | SurfaceStack& operator=(const SurfaceStack&) = delete; |
577 | |
578 | - void emit_change_notification(); |
579 | - |
580 | std::mutex mutable guard; |
581 | + |
582 | std::shared_ptr<InputRegistrar> const input_registrar; |
583 | std::shared_ptr<SceneReport> const report; |
584 | - std::function<void()> const change_cb; |
585 | |
586 | typedef std::vector<std::shared_ptr<Surface>> Layer; |
587 | std::map<DepthId, Layer> layers_by_depth; |
588 | |
589 | - std::mutex notify_change_mutex; |
590 | - std::function<void()> notify_change; |
591 | + Observers observers; |
592 | }; |
593 | |
594 | } |
595 | |
596 | === modified file 'tests/integration-tests/test_surface_first_frame_sync.cpp' |
597 | --- tests/integration-tests/test_surface_first_frame_sync.cpp 2014-04-16 03:38:42 +0000 |
598 | +++ tests/integration-tests/test_surface_first_frame_sync.cpp 2014-04-23 22:49:30 +0000 |
599 | @@ -24,6 +24,7 @@ |
600 | #include "mir/compositor/display_buffer_compositor.h" |
601 | #include "mir/compositor/display_buffer_compositor_factory.h" |
602 | #include "mir/compositor/scene.h" |
603 | +#include "mir/scene/legacy_scene_change_notification.h" |
604 | |
605 | #include "mir_test_framework/display_server_test_fixture.h" |
606 | #include "mir_test_doubles/null_display.h" |
607 | @@ -54,10 +55,10 @@ |
608 | class SynchronousCompositor : public mc::Compositor |
609 | { |
610 | public: |
611 | - SynchronousCompositor(std::shared_ptr<mg::Display> const& display, |
612 | + SynchronousCompositor(std::shared_ptr<mg::Display> const& display_, |
613 | std::shared_ptr<mc::Scene> const& scene, |
614 | std::shared_ptr<mc::DisplayBufferCompositorFactory> const& db_compositor_factory) |
615 | - : display{display}, |
616 | + : display{display_}, |
617 | scene{scene} |
618 | { |
619 | display->for_each_display_buffer( |
620 | @@ -65,28 +66,31 @@ |
621 | { |
622 | display_buffer_compositor_map[&display_buffer] = db_compositor_factory->create_compositor_for(display_buffer); |
623 | }); |
624 | -} |
625 | + |
626 | + observer = std::make_shared<ms::LegacySceneChangeNotification>([this]() { |
627 | + display->for_each_display_buffer([this](mg::DisplayBuffer& display_buffer) |
628 | + { |
629 | + display_buffer_compositor_map[&display_buffer]->composite(); |
630 | + }); |
631 | + }); |
632 | + } |
633 | |
634 | void start() |
635 | { |
636 | - scene->set_change_callback([this]() |
637 | - { |
638 | - display->for_each_display_buffer([this](mg::DisplayBuffer& display_buffer) |
639 | - { |
640 | - display_buffer_compositor_map[&display_buffer]->composite(); |
641 | - }); |
642 | - }); |
643 | + scene->add_observer(observer); |
644 | } |
645 | |
646 | void stop() |
647 | { |
648 | - scene->set_change_callback([]{}); |
649 | + scene->remove_observer(observer); |
650 | } |
651 | |
652 | private: |
653 | std::shared_ptr<mg::Display> const display; |
654 | std::shared_ptr<mc::Scene> const scene; |
655 | std::unordered_map<mg::DisplayBuffer*,std::unique_ptr<mc::DisplayBufferCompositor>> display_buffer_compositor_map; |
656 | + |
657 | + std::shared_ptr<ms::Observer> observer; |
658 | }; |
659 | |
660 | class StubRenderer : public mtd::StubRenderer |
661 | |
662 | === modified file 'tests/unit-tests/compositor/test_default_display_buffer_compositor.cpp' |
663 | --- tests/unit-tests/compositor/test_default_display_buffer_compositor.cpp 2014-04-16 03:38:42 +0000 |
664 | +++ tests/unit-tests/compositor/test_default_display_buffer_compositor.cpp 2014-04-23 22:49:30 +0000 |
665 | @@ -39,9 +39,11 @@ |
666 | namespace mg = mir::graphics; |
667 | namespace mc = mir::compositor; |
668 | namespace geom = mir::geometry; |
669 | +namespace ms = mir::scene; |
670 | +namespace mr = mir::report; |
671 | + |
672 | namespace mt = mir::test; |
673 | namespace mtd = mir::test::doubles; |
674 | -namespace mr = mir::report; |
675 | |
676 | namespace |
677 | { |
678 | @@ -58,7 +60,12 @@ |
679 | return renderlist; |
680 | } |
681 | |
682 | - void set_change_callback(std::function<void()> const&) {} |
683 | + void add_observer(std::shared_ptr<ms::Observer> const& /* observer */) override |
684 | + { |
685 | + } |
686 | + void remove_observer(std::weak_ptr<ms::Observer> const& /* observer */) override |
687 | + { |
688 | + } |
689 | |
690 | void change(mg::RenderableList const& new_renderlist) |
691 | { |
692 | |
693 | === modified file 'tests/unit-tests/compositor/test_multi_threaded_compositor.cpp' |
694 | --- tests/unit-tests/compositor/test_multi_threaded_compositor.cpp 2014-04-16 14:49:54 +0000 |
695 | +++ tests/unit-tests/compositor/test_multi_threaded_compositor.cpp 2014-04-23 22:49:30 +0000 |
696 | @@ -17,10 +17,13 @@ |
697 | */ |
698 | |
699 | #include "src/server/compositor/multi_threaded_compositor.h" |
700 | +#include "src/server/report/null_report_factory.h" |
701 | + |
702 | #include "mir/compositor/display_buffer_compositor.h" |
703 | #include "mir/compositor/scene.h" |
704 | #include "mir/compositor/display_buffer_compositor_factory.h" |
705 | -#include "src/server/report/null_report_factory.h" |
706 | +#include "mir/scene/observer.h" |
707 | + |
708 | #include "mir_test_doubles/null_display.h" |
709 | #include "mir_test_doubles/null_display_buffer.h" |
710 | #include "mir_test_doubles/mock_display_buffer.h" |
711 | @@ -30,6 +33,8 @@ |
712 | #include "mir_test_doubles/null_display_buffer_compositor_factory.h" |
713 | #include "mir_test/spin_wait.h" |
714 | |
715 | +#include <boost/throw_exception.hpp> |
716 | + |
717 | #include <unordered_map> |
718 | #include <unordered_set> |
719 | #include <thread> |
720 | @@ -42,9 +47,10 @@ |
721 | |
722 | namespace mc = mir::compositor; |
723 | namespace mg = mir::graphics; |
724 | +namespace ms = mir::scene; |
725 | +namespace mr = mir::report; |
726 | namespace geom = mir::geometry; |
727 | namespace mtd = mir::test::doubles; |
728 | -namespace mr = mir::report; |
729 | |
730 | namespace |
731 | { |
732 | @@ -89,9 +95,8 @@ |
733 | { |
734 | public: |
735 | StubScene(mg::RenderableList const& list) |
736 | - : callback{[]{}}, |
737 | - throw_on_set_callback_{false}, |
738 | - renderable_list{list} |
739 | + : renderable_list{list}, |
740 | + throw_on_add_observer_{false} |
741 | { |
742 | } |
743 | StubScene() : StubScene(mg::RenderableList{}) {} |
744 | @@ -101,38 +106,51 @@ |
745 | return renderable_list; |
746 | } |
747 | |
748 | - void set_change_callback(std::function<void()> const& f) |
749 | - { |
750 | - if (throw_on_set_callback_) |
751 | - throw std::runtime_error(""); |
752 | - std::lock_guard<std::mutex> lock{callback_mutex}; |
753 | - assert(f); |
754 | - callback = f; |
755 | + void add_observer(std::shared_ptr<ms::Observer> const& observer_) |
756 | + { |
757 | + std::lock_guard<std::mutex> lock{observer_mutex}; |
758 | + |
759 | + if (throw_on_add_observer_) |
760 | + BOOST_THROW_EXCEPTION(std::runtime_error("")); |
761 | + |
762 | + assert(!observer); |
763 | + observer = observer_; |
764 | + } |
765 | + |
766 | + void remove_observer(std::weak_ptr<ms::Observer> const& /* observer */) |
767 | + { |
768 | + std::lock_guard<std::mutex> lock{observer_mutex}; |
769 | + observer.reset(); |
770 | } |
771 | |
772 | void emit_change_event() |
773 | { |
774 | { |
775 | - std::lock_guard<std::mutex> lock{callback_mutex}; |
776 | - callback(); |
777 | + std::lock_guard<std::mutex> lock{observer_mutex}; |
778 | + |
779 | + // Any old event will do. |
780 | + if (observer) |
781 | + observer->surfaces_reordered(); |
782 | } |
783 | /* Reduce run-time under valgrind */ |
784 | std::this_thread::yield(); |
785 | } |
786 | |
787 | - void throw_on_set_callback(bool flag) |
788 | + void throw_on_add_observer(bool flag) |
789 | { |
790 | - throw_on_set_callback_ = flag; |
791 | + throw_on_add_observer_ = flag; |
792 | } |
793 | |
794 | void lock() {} |
795 | void unlock() {} |
796 | |
797 | private: |
798 | - std::function<void()> callback; |
799 | - std::mutex callback_mutex; |
800 | - bool throw_on_set_callback_; |
801 | + std::mutex observer_mutex; |
802 | mg::RenderableList renderable_list; |
803 | + |
804 | + std::shared_ptr<ms::Observer> observer; |
805 | + |
806 | + bool throw_on_add_observer_; |
807 | }; |
808 | |
809 | class RecordingDisplayBufferCompositor : public mc::DisplayBufferCompositor |
810 | @@ -564,19 +582,22 @@ |
811 | |
812 | TEST(MultiThreadedCompositor, double_start_or_stop_ignored) |
813 | { |
814 | - using namespace testing; |
815 | + using namespace ::testing; |
816 | |
817 | unsigned int const nbuffers{3}; |
818 | auto display = std::make_shared<StubDisplayWithMockBuffers>(nbuffers); |
819 | auto mock_scene = std::make_shared<mtd::MockScene>(); |
820 | auto db_compositor_factory = std::make_shared<mtd::NullDisplayBufferCompositorFactory>(); |
821 | auto mock_report = std::make_shared<testing::NiceMock<mtd::MockCompositorReport>>(); |
822 | + |
823 | EXPECT_CALL(*mock_report, started()) |
824 | .Times(1); |
825 | EXPECT_CALL(*mock_report, stopped()) |
826 | .Times(1); |
827 | - EXPECT_CALL(*mock_scene, set_change_callback(_)) |
828 | - .Times(2); |
829 | + EXPECT_CALL(*mock_scene, add_observer(_)) |
830 | + .Times(1); |
831 | + EXPECT_CALL(*mock_scene, remove_observer(_)) |
832 | + .Times(1); |
833 | EXPECT_CALL(*mock_scene, generate_renderable_list()) |
834 | .Times(AtLeast(0)) |
835 | .WillRepeatedly(Return(mg::RenderableList{})); |
836 | @@ -632,11 +653,11 @@ |
837 | auto db_compositor_factory = std::make_shared<RecordingDisplayBufferCompositorFactory>(); |
838 | mc::MultiThreadedCompositor compositor{display, scene, db_compositor_factory, null_report, true}; |
839 | |
840 | - scene->throw_on_set_callback(true); |
841 | + scene->throw_on_add_observer(true); |
842 | |
843 | EXPECT_THROW(compositor.start(), std::runtime_error); |
844 | |
845 | - scene->throw_on_set_callback(false); |
846 | + scene->throw_on_add_observer(false); |
847 | |
848 | /* No point in running the rest of the test if it throws again */ |
849 | ASSERT_NO_THROW(compositor.start()); |
850 | |
851 | === modified file 'tests/unit-tests/scene/CMakeLists.txt' |
852 | --- tests/unit-tests/scene/CMakeLists.txt 2014-03-06 06:05:17 +0000 |
853 | +++ tests/unit-tests/scene/CMakeLists.txt 2014-04-23 22:49:30 +0000 |
854 | @@ -14,6 +14,7 @@ |
855 | ${CMAKE_CURRENT_SOURCE_DIR}/test_basic_surface.cpp |
856 | ${CMAKE_CURRENT_SOURCE_DIR}/test_surface_stack.cpp |
857 | ${CMAKE_CURRENT_SOURCE_DIR}/test_surface_controller.cpp |
858 | + ${CMAKE_CURRENT_SOURCE_DIR}/test_legacy_scene_change_notification.cpp |
859 | ) |
860 | |
861 | set(UNIT_TEST_SOURCES ${UNIT_TEST_SOURCES} PARENT_SCOPE) |
862 | |
863 | === added file 'tests/unit-tests/scene/test_legacy_scene_change_notification.cpp' |
864 | --- tests/unit-tests/scene/test_legacy_scene_change_notification.cpp 1970-01-01 00:00:00 +0000 |
865 | +++ tests/unit-tests/scene/test_legacy_scene_change_notification.cpp 2014-04-23 22:49:30 +0000 |
866 | @@ -0,0 +1,96 @@ |
867 | +/* |
868 | + * Copyright © 2014 Canonical Ltd. |
869 | + * |
870 | + * This program is free software: you can redistribute it and/or modify |
871 | + * it under the terms of the GNU General Public License version 3 as |
872 | + * published by the Free Software Foundation. |
873 | + * |
874 | + * This program is distributed in the hope that it will be useful, |
875 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
876 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
877 | + * GNU General Public License for more details. |
878 | + * |
879 | + * You should have received a copy of the GNU General Public License |
880 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
881 | + * |
882 | + * Authored by: Robert Carr <robert.carr@canonical.com> |
883 | + */ |
884 | + |
885 | +#include "mir/scene/legacy_scene_change_notification.h" |
886 | +#include "mir/scene/surface_observer.h" |
887 | + |
888 | +#include "mir_test/fake_shared.h" |
889 | +#include "mir_test_doubles/mock_surface.h" |
890 | + |
891 | +#include <gtest/gtest.h> |
892 | +#include <gmock/gmock.h> |
893 | + |
894 | +namespace ms = mir::scene; |
895 | +namespace mt = mir::test; |
896 | +namespace mtd = mt::doubles; |
897 | + |
898 | +namespace |
899 | +{ |
900 | +struct MockCallback |
901 | +{ |
902 | + MOCK_METHOD0(invoke, void()); |
903 | +}; |
904 | +} |
905 | + |
906 | +TEST(LegacySceneChangeNotificationTest, fowards_all_observations_to_callback) |
907 | +{ |
908 | + MockCallback callback; |
909 | + ms::LegacySceneChangeNotification observer([&](){ callback.invoke(); }); |
910 | + |
911 | + testing::NiceMock<mtd::MockSurface> surface; |
912 | + |
913 | + EXPECT_CALL(callback, invoke()).Times(3); |
914 | + observer.surface_added(mt::fake_shared(surface)); |
915 | + observer.surface_removed(mt::fake_shared(surface)); |
916 | + observer.surfaces_reordered(); |
917 | +} |
918 | + |
919 | +TEST(LegacySceneChangeNotificationTest, registers_observer_with_surfaces) |
920 | +{ |
921 | + using namespace ::testing; |
922 | + |
923 | + mtd::MockSurface surface; |
924 | + ms::LegacySceneChangeNotification observer([](){}); |
925 | + |
926 | + EXPECT_CALL(surface, add_observer(_)).Times(1); |
927 | + observer.surface_added(mt::fake_shared(surface)); |
928 | +} |
929 | + |
930 | +TEST(LegacySceneChangeNotification, observes_surface_changes) |
931 | +{ |
932 | + using namespace ::testing; |
933 | + |
934 | + mtd::MockSurface surface; |
935 | + MockCallback callback; |
936 | + ms::LegacySceneChangeNotification observer([&](){ callback.invoke(); }); |
937 | + |
938 | + std::shared_ptr<ms::SurfaceObserver> surface_observer; |
939 | + EXPECT_CALL(surface, add_observer(_)).Times(1) |
940 | + .WillOnce(SaveArg<0>(&surface_observer)); |
941 | + |
942 | + // Once for surface added and once for surface change |
943 | + EXPECT_CALL(callback, invoke()).Times(2); |
944 | + observer.surface_added(mt::fake_shared(surface)); |
945 | + |
946 | + surface_observer->frame_posted(); |
947 | +} |
948 | + |
949 | +TEST(LegacySceneChangeNotification, destroying_observer_unregisters_surface_observers) |
950 | +{ |
951 | + using namespace ::testing; |
952 | + |
953 | + auto surface = std::make_shared<mtd::MockSurface>(); |
954 | + |
955 | + EXPECT_CALL(*surface, add_observer(_)).Times(1); |
956 | + EXPECT_CALL(*surface, remove_observer(_)).Times(1); |
957 | + |
958 | + { |
959 | + ms::LegacySceneChangeNotification observer([](){}); |
960 | + observer.surface_added(surface); |
961 | + } |
962 | +} |
963 | |
964 | === modified file 'tests/unit-tests/scene/test_surface_stack.cpp' |
965 | --- tests/unit-tests/scene/test_surface_stack.cpp 2014-04-15 05:31:19 +0000 |
966 | +++ tests/unit-tests/scene/test_surface_stack.cpp 2014-04-23 22:49:30 +0000 |
967 | @@ -19,6 +19,7 @@ |
968 | #include "src/server/scene/surface_stack.h" |
969 | #include "mir/graphics/buffer_properties.h" |
970 | #include "mir/geometry/rectangle.h" |
971 | +#include "mir/scene/observer.h" |
972 | #include "mir/scene/surface_creation_parameters.h" |
973 | #include "src/server/report/null_report_factory.h" |
974 | #include "src/server/scene/basic_surface.h" |
975 | @@ -80,12 +81,18 @@ |
976 | int const c_fd; |
977 | }; |
978 | |
979 | -class MockCallback |
980 | +struct MockCallback |
981 | { |
982 | -public: |
983 | MOCK_METHOD0(call, void()); |
984 | }; |
985 | |
986 | +struct MockSceneObserver : public ms::Observer |
987 | +{ |
988 | + MOCK_METHOD1(surface_added, void(std::shared_ptr<ms::Surface> const&)); |
989 | + MOCK_METHOD1(surface_removed, void(std::shared_ptr<ms::Surface> const&)); |
990 | + MOCK_METHOD0(surfaces_reordered, void()); |
991 | +}; |
992 | + |
993 | struct SurfaceStack : public ::testing::Test |
994 | { |
995 | void SetUp() |
996 | @@ -333,6 +340,107 @@ |
997 | stack.remove_surface(surface); |
998 | } |
999 | |
1000 | +TEST_F(SurfaceStack, scene_observer_notified_of_add_and_remove) |
1001 | +{ |
1002 | + using namespace ::testing; |
1003 | + |
1004 | + ms::SurfaceStack stack( |
1005 | + mt::fake_shared(input_registrar), report); |
1006 | + MockSceneObserver observer; |
1007 | + |
1008 | + InSequence seq; |
1009 | + EXPECT_CALL(observer, surface_added(Eq(stub_surface1))).Times(1); |
1010 | + EXPECT_CALL(observer, surface_removed(Eq(stub_surface1))) |
1011 | + .Times(1); |
1012 | + |
1013 | + stack.add_observer(mt::fake_shared(observer)); |
1014 | + |
1015 | + stack.add_surface(stub_surface1, default_params.depth, default_params.input_mode); |
1016 | + stack.remove_surface(stub_surface1); |
1017 | +} |
1018 | + |
1019 | +TEST_F(SurfaceStack, multiple_observers) |
1020 | +{ |
1021 | + using namespace ::testing; |
1022 | + |
1023 | + ms::SurfaceStack stack( |
1024 | + mt::fake_shared(input_registrar), report); |
1025 | + MockSceneObserver observer1, observer2; |
1026 | + |
1027 | + InSequence seq; |
1028 | + EXPECT_CALL(observer1, surface_added(Eq(stub_surface1))).Times(1); |
1029 | + EXPECT_CALL(observer2, surface_added(Eq(stub_surface1))).Times(1); |
1030 | + |
1031 | + stack.add_observer(mt::fake_shared(observer1)); |
1032 | + stack.add_observer(mt::fake_shared(observer2)); |
1033 | + |
1034 | + stack.add_surface(stub_surface1, default_params.depth, default_params.input_mode); |
1035 | +} |
1036 | + |
1037 | +TEST_F(SurfaceStack, remove_scene_observer) |
1038 | +{ |
1039 | + using namespace ::testing; |
1040 | + |
1041 | + ms::SurfaceStack stack( |
1042 | + mt::fake_shared(input_registrar), report); |
1043 | + MockSceneObserver observer; |
1044 | + |
1045 | + InSequence seq; |
1046 | + EXPECT_CALL(observer, surface_added(Eq(stub_surface1))).Times(1); |
1047 | + // We remove the scene observer before removing the surface, and thus |
1048 | + // expect to NOT see the surface_removed call |
1049 | + EXPECT_CALL(observer, surface_removed(Eq(stub_surface1))) |
1050 | + .Times(0); |
1051 | + |
1052 | + stack.add_observer(mt::fake_shared(observer)); |
1053 | + |
1054 | + stack.add_surface(stub_surface1, default_params.depth, default_params.input_mode); |
1055 | + stack.remove_observer(mt::fake_shared(observer)); |
1056 | + |
1057 | + stack.remove_surface(stub_surface1); |
1058 | +} |
1059 | + |
1060 | +// Many clients of the scene observer wish to install surface observers to monitor surface |
1061 | +// notifications. We offer them a surface_added event for existing surfaces to give them |
1062 | +// a chance to do this. |
1063 | +TEST_F(SurfaceStack, scene_observer_informed_of_existing_surfaces) |
1064 | +{ |
1065 | + using namespace ::testing; |
1066 | + |
1067 | + using namespace ::testing; |
1068 | + |
1069 | + ms::SurfaceStack stack( |
1070 | + mt::fake_shared(input_registrar), report); |
1071 | + MockSceneObserver observer; |
1072 | + |
1073 | + InSequence seq; |
1074 | + EXPECT_CALL(observer, surface_added(Eq(stub_surface1))).Times(1); |
1075 | + |
1076 | + stack.add_surface(stub_surface1, default_params.depth, default_params.input_mode); |
1077 | + |
1078 | + stack.add_observer(mt::fake_shared(observer)); |
1079 | +} |
1080 | + |
1081 | +TEST_F(SurfaceStack, surfaces_reordered) |
1082 | +{ |
1083 | + using namespace ::testing; |
1084 | + |
1085 | + ms::SurfaceStack stack( |
1086 | + mt::fake_shared(input_registrar), report); |
1087 | + MockSceneObserver observer; |
1088 | + |
1089 | + EXPECT_CALL(observer, surface_added(_)).Times(AnyNumber()); |
1090 | + EXPECT_CALL(observer, surface_removed(_)).Times(AnyNumber()); |
1091 | + |
1092 | + EXPECT_CALL(observer, surfaces_reordered()).Times(1); |
1093 | + |
1094 | + stack.add_observer(mt::fake_shared(observer)); |
1095 | + |
1096 | + stack.add_surface(stub_surface1, default_params.depth, default_params.input_mode); |
1097 | + stack.add_surface(stub_surface2, default_params.depth, default_params.input_mode); |
1098 | + stack.raise(stub_surface1); |
1099 | +} |
1100 | + |
1101 | TEST_F(SurfaceStack, renderlist_is_snapshot_of_positioning_info) |
1102 | { |
1103 | size_t num_surfaces{3}; |
FAILED: Continuous integration, rev:1529 jenkins. qa.ubuntu. com/job/ mir-team- mir-development -branch- ci/1343/ jenkins. qa.ubuntu. com/job/ mir-android- trusty- i386-build/ 1619/console jenkins. qa.ubuntu. com/job/ mir-clang- trusty- amd64-build/ 1617/console jenkins. qa.ubuntu. com/job/ mir-mediumtests -trusty- touch/1192/ console jenkins. qa.ubuntu. com/job/ mir-team- mir-development -branch- trusty- amd64-ci/ 1075/console jenkins. qa.ubuntu. com/job/ mir-team- mir-development -branch- trusty- armhf-ci/ 1080/console jenkins. qa.ubuntu. com/job/ mir-mediumtests -builder- trusty- armhf/1193/ console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/mir- team-mir- development- branch- ci/1343/ rebuild
http://