Merge lp:~raof/mir/dont-tear-down-compositor-if-unnecessary into lp:mir
- dont-tear-down-compositor-if-unnecessary
- Merge into development-branch
Status: | Merged |
---|---|
Approved by: | Daniel van Vugt |
Approved revision: | no longer in the source branch. |
Merged at revision: | 3712 |
Proposed branch: | lp:~raof/mir/dont-tear-down-compositor-if-unnecessary |
Merge into: | lp:mir |
Diff against target: |
541 lines (+293/-13) 16 files modified
include/platform/mir/graphics/display.h (+18/-0) include/test/mir/test/doubles/null_display.h (+4/-0) src/platforms/android/server/display.cpp (+6/-0) src/platforms/android/server/display.h (+1/-0) src/platforms/eglstream-kms/server/display.cpp (+6/-0) src/platforms/eglstream-kms/server/display.h (+2/-0) src/platforms/mesa/server/kms/display.cpp (+6/-0) src/platforms/mesa/server/kms/display.h (+1/-0) src/platforms/mesa/server/x11/graphics/display.cpp (+6/-0) src/platforms/mesa/server/x11/graphics/display.h (+3/-0) src/server/graphics/nested/display.cpp (+6/-0) src/server/graphics/nested/display.h (+3/-0) src/server/scene/mediating_display_changer.cpp (+37/-4) tests/include/mir/test/doubles/mock_display.h (+2/-0) tests/mir_test_framework/stubbed_graphics_platform.cpp (+4/-0) tests/unit-tests/scene/test_mediating_display_changer.cpp (+188/-9) |
To merge this branch: | bzr merge lp:~raof/mir/dont-tear-down-compositor-if-unnecessary |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mir CI Bot | continuous-integration | Approve | |
Cemil Azizoglu (community) | Approve | ||
Alan Griffiths | Approve | ||
Review via email: mp+305778@code.launchpad.net |
This proposal supersedes a proposal from 2016-09-09.
Commit message
Prevent unnecessary reinitialisation of the compositor on display configuration (round 1)
We currently need to tear down and reinitialise the compositor on display changes because (a) we have no way of adding or removing compositors short of a full teardown/rebuild cycle and, worse (b) because the compositor takes a non-owning reference to a DisplayBuffer and display configuration will frequently destroy all existing DisplayBuffers.
Add an interface to the platform's Display to check when a display configuration change will *not* destroy existing DisplayBuffers. If it will not, that avoids problem (b), so check if any new outputs have been enabled. If neither of those are the case we can safely apply the display configuration without reinitialising the compositor.
Follow up work will enable this in the various graphics platforms.
Fixes (part one): https:/
Description of the change
Mir CI Bot (mir-ci-bot) wrote : Posted in a previous version of this proposal | # |
Chris Halse Rogers (raof) wrote : Posted in a previous version of this proposal | # |
08:42:03 clang: error: invalid argument '/build/mir' to -fdebug-prefix-map
Again. ???
Mir CI Bot (mir-ci-bot) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:3702
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:3704
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Chris Halse Rogers (raof) wrote : Posted in a previous version of this proposal | # |
02:05:53 cc1plus: error: invalid argument ���/build/mir��� to -fdebug-prefix-map
Retriggering
Mir CI Bot (mir-ci-bot) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:3704
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal | # |
+ virtual bool configuration_
While not an issue in the current usage I worry that this style invites racy code. I would prefer something that's obviously atomic:
bool apply_configura
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal | # |
> + virtual bool
> configuration_
> const = 0;
>
> While not an issue in the current usage I worry that this style invites racy
> code. I would prefer something that's obviously atomic:
>
> bool apply_configura
> const& conf) const = 0;
I'm not going to block on this, but please consider it before TA.
Chris Halse Rogers (raof) wrote : Posted in a previous version of this proposal | # |
Hm.
It's pretty easy to use correctly now - the results of will_preserve_
But apply_configura
Chris Halse Rogers (raof) wrote : | # |
Now with atomic test-and-set semantics.
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3711
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Daniel van Vugt (vanvugt) wrote : | # |
^^^
Just the usual bug 1523621
Alan Griffiths (alan-griffiths) wrote : | # |
Looks good
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:3711
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Daniel van Vugt (vanvugt) wrote : | # |
^^^
Jenkins failures are just bug 1523621 as usual.
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
https:/
Executed test runs:
FAILURE: https:/
None: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Daniel van Vugt (vanvugt) wrote : | # |
^^^
Bug 1523621 again
Mir CI Bot (mir-ci-bot) : | # |
Preview Diff
1 | === modified file 'include/platform/mir/graphics/display.h' |
2 | --- include/platform/mir/graphics/display.h 2016-09-08 15:28:25 +0000 |
3 | +++ include/platform/mir/graphics/display.h 2016-09-15 01:44:40 +0000 |
4 | @@ -110,6 +110,24 @@ |
5 | virtual std::unique_ptr<DisplayConfiguration> configuration() const = 0; |
6 | |
7 | /** |
8 | + * Applying a display configuration only if it will not invalidate existing DisplayBuffers |
9 | + * |
10 | + * The Display must guarantee that the references to the DisplayBuffer acquired via |
11 | + * DisplaySyncGroup::for_each_display_buffer() remain valid until the Display is destroyed or |
12 | + * Display::configure() is called. |
13 | + * |
14 | + * If this function returns \c true then the new display configuration has been applied. |
15 | + * If this function returns \c false then the new display configuration has not been applied. |
16 | + * |
17 | + * In either case this function guarantees that existing DisplayBuffer references will remain |
18 | + * valid. |
19 | + * |
20 | + * \param conf [in] Configuration to possibly apply. |
21 | + * \return \c true if \p conf has been applied as the new output configuration. |
22 | + */ |
23 | + virtual bool apply_if_configuration_preserves_display_buffers(DisplayConfiguration const& conf) const = 0; |
24 | + |
25 | + /** |
26 | * Sets a new output configuration. |
27 | */ |
28 | virtual void configure(DisplayConfiguration const& conf) = 0; |
29 | |
30 | === modified file 'include/test/mir/test/doubles/null_display.h' |
31 | --- include/test/mir/test/doubles/null_display.h 2016-08-01 09:37:45 +0000 |
32 | +++ include/test/mir/test/doubles/null_display.h 2016-09-15 01:44:40 +0000 |
33 | @@ -48,6 +48,10 @@ |
34 | new NullDisplayConfiguration |
35 | ); |
36 | } |
37 | + bool apply_if_configuration_preserves_display_buffers(graphics::DisplayConfiguration const&) const override |
38 | + { |
39 | + return false; |
40 | + } |
41 | void configure(graphics::DisplayConfiguration const&) override{} |
42 | void register_configuration_change_handler( |
43 | graphics::EventHandlerRegister&, |
44 | |
45 | === modified file 'src/platforms/android/server/display.cpp' |
46 | --- src/platforms/android/server/display.cpp 2016-08-01 09:37:45 +0000 |
47 | +++ src/platforms/android/server/display.cpp 2016-09-15 01:44:40 +0000 |
48 | @@ -358,3 +358,9 @@ |
49 | { |
50 | return std::make_unique<mga::PbufferGLContext>(gl_context); |
51 | } |
52 | + |
53 | +bool mga::Display::apply_if_configuration_preserves_display_buffers( |
54 | + mg::DisplayConfiguration const& /*conf*/) const |
55 | +{ |
56 | + return false; |
57 | +} |
58 | |
59 | === modified file 'src/platforms/android/server/display.h' |
60 | --- src/platforms/android/server/display.h 2016-08-01 09:37:45 +0000 |
61 | +++ src/platforms/android/server/display.h 2016-09-15 01:44:40 +0000 |
62 | @@ -66,6 +66,7 @@ |
63 | void for_each_display_sync_group(std::function<void(graphics::DisplaySyncGroup&)> const& f) override; |
64 | |
65 | std::unique_ptr<graphics::DisplayConfiguration> configuration() const override; |
66 | + bool apply_if_configuration_preserves_display_buffers(graphics::DisplayConfiguration const& conf) const override; |
67 | void configure(graphics::DisplayConfiguration const&) override; |
68 | |
69 | void register_configuration_change_handler( |
70 | |
71 | === modified file 'src/platforms/eglstream-kms/server/display.cpp' |
72 | --- src/platforms/eglstream-kms/server/display.cpp 2016-08-01 09:37:45 +0000 |
73 | +++ src/platforms/eglstream-kms/server/display.cpp 2016-09-15 01:44:40 +0000 |
74 | @@ -367,3 +367,9 @@ |
75 | return std::make_unique<GLContext>(display, context); |
76 | } |
77 | |
78 | +bool mge::Display::apply_if_configuration_preserves_display_buffers( |
79 | + mg::DisplayConfiguration const& /*conf*/) const |
80 | +{ |
81 | + return false; |
82 | +} |
83 | + |
84 | |
85 | === modified file 'src/platforms/eglstream-kms/server/display.h' |
86 | --- src/platforms/eglstream-kms/server/display.h 2016-08-01 09:37:45 +0000 |
87 | +++ src/platforms/eglstream-kms/server/display.h 2016-09-15 01:44:40 +0000 |
88 | @@ -49,6 +49,8 @@ |
89 | |
90 | std::unique_ptr<DisplayConfiguration> configuration() const override; |
91 | |
92 | + bool apply_if_configuration_preserves_display_buffers(DisplayConfiguration const& conf) const override; |
93 | + |
94 | void configure(DisplayConfiguration const& conf) override; |
95 | |
96 | void register_configuration_change_handler(EventHandlerRegister& handlers, |
97 | |
98 | === modified file 'src/platforms/mesa/server/kms/display.cpp' |
99 | --- src/platforms/mesa/server/kms/display.cpp 2016-08-23 20:21:27 +0000 |
100 | +++ src/platforms/mesa/server/kms/display.cpp 2016-09-15 01:44:40 +0000 |
101 | @@ -415,3 +415,9 @@ |
102 | { |
103 | return std::make_unique<GBMGLContext>(*gbm, *gl_config, shared_egl.context()); |
104 | } |
105 | + |
106 | +bool mgm::Display::apply_if_configuration_preserves_display_buffers( |
107 | + mg::DisplayConfiguration const& /*conf*/) const |
108 | +{ |
109 | + return false; |
110 | +} |
111 | |
112 | === modified file 'src/platforms/mesa/server/kms/display.h' |
113 | --- src/platforms/mesa/server/kms/display.h 2016-08-01 09:37:45 +0000 |
114 | +++ src/platforms/mesa/server/kms/display.h 2016-09-15 01:44:40 +0000 |
115 | @@ -78,6 +78,7 @@ |
116 | std::function<void(graphics::DisplaySyncGroup&)> const& f) override; |
117 | |
118 | std::unique_ptr<DisplayConfiguration> configuration() const override; |
119 | + bool apply_if_configuration_preserves_display_buffers(DisplayConfiguration const& conf) const override; |
120 | void configure(DisplayConfiguration const& conf) override; |
121 | |
122 | void register_configuration_change_handler( |
123 | |
124 | === modified file 'src/platforms/mesa/server/x11/graphics/display.cpp' |
125 | --- src/platforms/mesa/server/x11/graphics/display.cpp 2016-09-07 04:54:17 +0000 |
126 | +++ src/platforms/mesa/server/x11/graphics/display.cpp 2016-09-15 01:44:40 +0000 |
127 | @@ -380,3 +380,9 @@ |
128 | { |
129 | return std::make_unique<mgx::XGLContext>(egl_display, egl_surface, egl_context); |
130 | } |
131 | + |
132 | +bool mgx::Display::apply_if_configuration_preserves_display_buffers( |
133 | + mg::DisplayConfiguration const& /*conf*/) const |
134 | +{ |
135 | + return false; |
136 | +} |
137 | |
138 | === modified file 'src/platforms/mesa/server/x11/graphics/display.h' |
139 | --- src/platforms/mesa/server/x11/graphics/display.h 2016-09-07 03:37:03 +0000 |
140 | +++ src/platforms/mesa/server/x11/graphics/display.h 2016-09-15 01:44:40 +0000 |
141 | @@ -111,6 +111,9 @@ |
142 | void for_each_display_sync_group(std::function<void(graphics::DisplaySyncGroup&)> const& f) override; |
143 | |
144 | std::unique_ptr<graphics::DisplayConfiguration> configuration() const override; |
145 | + |
146 | + bool apply_if_configuration_preserves_display_buffers(graphics::DisplayConfiguration const& conf) const override; |
147 | + |
148 | void configure(graphics::DisplayConfiguration const&) override; |
149 | |
150 | void register_configuration_change_handler( |
151 | |
152 | === modified file 'src/server/graphics/nested/display.cpp' |
153 | --- src/server/graphics/nested/display.cpp 2016-08-25 12:50:09 +0000 |
154 | +++ src/server/graphics/nested/display.cpp 2016-09-15 01:44:40 +0000 |
155 | @@ -366,3 +366,9 @@ |
156 | { |
157 | return egl_display.create_gl_context(); |
158 | } |
159 | + |
160 | +bool mgn::Display::apply_if_configuration_preserves_display_buffers( |
161 | + mg::DisplayConfiguration const& /*conf*/) const |
162 | +{ |
163 | + return false; |
164 | +} |
165 | |
166 | === modified file 'src/server/graphics/nested/display.h' |
167 | --- src/server/graphics/nested/display.h 2016-08-01 09:37:45 +0000 |
168 | +++ src/server/graphics/nested/display.h 2016-09-15 01:44:40 +0000 |
169 | @@ -128,6 +128,9 @@ |
170 | void for_each_display_sync_group(std::function<void(DisplaySyncGroup&)>const& f) override; |
171 | |
172 | std::unique_ptr<DisplayConfiguration> configuration() const override; |
173 | + |
174 | + bool apply_if_configuration_preserves_display_buffers(DisplayConfiguration const& conf) const override; |
175 | + |
176 | void configure(DisplayConfiguration const&) override; |
177 | |
178 | void register_configuration_change_handler( |
179 | |
180 | === modified file 'src/server/scene/mediating_display_changer.cpp' |
181 | --- src/server/scene/mediating_display_changer.cpp 2016-09-12 02:58:30 +0000 |
182 | +++ src/server/scene/mediating_display_changer.cpp 2016-09-15 01:44:40 +0000 |
183 | @@ -18,6 +18,7 @@ |
184 | |
185 | #include <condition_variable> |
186 | #include <boost/throw_exception.hpp> |
187 | +#include <unordered_set> |
188 | #include "mediating_display_changer.h" |
189 | #include "session_container.h" |
190 | #include "mir/scene/session.h" |
191 | @@ -330,15 +331,47 @@ |
192 | server_action_queue->resume_processing_for(this); |
193 | } |
194 | |
195 | +namespace |
196 | +{ |
197 | +bool configuration_has_new_outputs_enabled( |
198 | + mg::DisplayConfiguration const& existing, |
199 | + mg::DisplayConfiguration const& updated) |
200 | +{ |
201 | + std::unordered_set<mg::DisplayConfigurationOutputId> currently_enabled_outputs; |
202 | + existing.for_each_output( |
203 | + [¤tly_enabled_outputs](auto const& output) |
204 | + { |
205 | + if (output.used) |
206 | + { |
207 | + currently_enabled_outputs.insert(output.id); |
208 | + } |
209 | + }); |
210 | + bool has_new_output{false}; |
211 | + updated.for_each_output( |
212 | + [¤tly_enabled_outputs, &has_new_output](auto const& output) |
213 | + { |
214 | + if (output.used) |
215 | + { |
216 | + has_new_output |= (currently_enabled_outputs.count(output.id) == 0); |
217 | + } |
218 | + }); |
219 | + return has_new_output; |
220 | +} |
221 | +} |
222 | + |
223 | void ms::MediatingDisplayChanger::apply_config( |
224 | std::shared_ptr<graphics::DisplayConfiguration> const& conf) |
225 | { |
226 | report->new_configuration(*conf); |
227 | - ApplyNowAndRevertOnScopeExit comp{ |
228 | - [this] { compositor->stop(); }, |
229 | - [this] { compositor->start(); }}; |
230 | |
231 | - display->configure(*conf); |
232 | + if (configuration_has_new_outputs_enabled(*display->configuration(), *conf) || |
233 | + !display->apply_if_configuration_preserves_display_buffers(*conf)) |
234 | + { |
235 | + ApplyNowAndRevertOnScopeExit comp{ |
236 | + [this] { compositor->stop(); }, |
237 | + [this] { compositor->start(); }}; |
238 | + display->configure(*conf); |
239 | + } |
240 | update_input_rectangles(*conf); |
241 | |
242 | base_configuration_applied = false; |
243 | |
244 | === modified file 'tests/include/mir/test/doubles/mock_display.h' |
245 | --- tests/include/mir/test/doubles/mock_display.h 2016-08-01 09:37:45 +0000 |
246 | +++ tests/include/mir/test/doubles/mock_display.h 2016-09-15 01:44:40 +0000 |
247 | @@ -37,6 +37,8 @@ |
248 | public: |
249 | MOCK_METHOD1(for_each_display_sync_group, void (std::function<void(graphics::DisplaySyncGroup&)> const&)); |
250 | MOCK_CONST_METHOD0(configuration, std::unique_ptr<graphics::DisplayConfiguration>()); |
251 | + MOCK_CONST_METHOD1(apply_if_configuration_preserves_display_buffers, bool(graphics::DisplayConfiguration const |
252 | + &)); |
253 | MOCK_METHOD1(configure, void(graphics::DisplayConfiguration const&)); |
254 | MOCK_METHOD2(register_configuration_change_handler, |
255 | void(graphics::EventHandlerRegister&, graphics::DisplayConfigurationChangeHandler const&)); |
256 | |
257 | === modified file 'tests/mir_test_framework/stubbed_graphics_platform.cpp' |
258 | --- tests/mir_test_framework/stubbed_graphics_platform.cpp 2016-09-13 08:09:53 +0000 |
259 | +++ tests/mir_test_framework/stubbed_graphics_platform.cpp 2016-09-15 01:44:40 +0000 |
260 | @@ -62,6 +62,10 @@ |
261 | { |
262 | return display->configuration(); |
263 | } |
264 | + bool apply_if_configuration_preserves_display_buffers(mg::DisplayConfiguration const& /*conf*/) const override |
265 | + { |
266 | + return false; |
267 | + } |
268 | void configure(mg::DisplayConfiguration const& conf) override |
269 | { |
270 | display->configure(conf); |
271 | |
272 | === modified file 'tests/unit-tests/scene/test_mediating_display_changer.cpp' |
273 | --- tests/unit-tests/scene/test_mediating_display_changer.cpp 2016-09-12 02:58:30 +0000 |
274 | +++ tests/unit-tests/scene/test_mediating_display_changer.cpp 2016-09-15 01:44:40 +0000 |
275 | @@ -209,12 +209,15 @@ |
276 | EXPECT_THAT(*base_conf, mt::DisplayConfigMatches(std::ref(*mock_display.conf_ptr))); |
277 | } |
278 | |
279 | -TEST_F(MediatingDisplayChangerTest, pauses_system_when_applying_new_configuration_for_focused_session) |
280 | +TEST_F(MediatingDisplayChangerTest, pauses_system_when_applying_new_configuration_for_focused_session_would_invalidate_display_buffers) |
281 | { |
282 | using namespace testing; |
283 | mtd::NullDisplayConfiguration conf; |
284 | auto session = std::make_shared<mtd::StubSession>(); |
285 | |
286 | + ON_CALL(mock_display, apply_if_configuration_preserves_display_buffers(_)) |
287 | + .WillByDefault(Return(false)); |
288 | + |
289 | InSequence s; |
290 | EXPECT_CALL(mock_compositor, stop()); |
291 | |
292 | @@ -227,13 +230,32 @@ |
293 | mt::fake_shared(conf)); |
294 | } |
295 | |
296 | +TEST_F(MediatingDisplayChangerTest, does_not_pause_system_when_applying_new_configuration_for_focused_session_would_preserve_display_buffers) |
297 | +{ |
298 | + using namespace testing; |
299 | + mtd::NullDisplayConfiguration conf; |
300 | + auto session = std::make_shared<mtd::StubSession>(); |
301 | + |
302 | + EXPECT_CALL(mock_display, apply_if_configuration_preserves_display_buffers(Ref(conf))) |
303 | + .WillOnce(Return(true)); |
304 | + |
305 | + EXPECT_CALL(mock_compositor, stop()).Times(0); |
306 | + EXPECT_CALL(mock_compositor, start()).Times(0); |
307 | + EXPECT_CALL(mock_display, configure(_)).Times(0); |
308 | + |
309 | + session_event_sink.handle_focus_change(session); |
310 | + changer->configure(session, |
311 | + mt::fake_shared(conf)); |
312 | +} |
313 | + |
314 | + |
315 | TEST_F(MediatingDisplayChangerTest, doesnt_apply_config_for_unfocused_session) |
316 | { |
317 | using namespace testing; |
318 | mtd::NullDisplayConfiguration conf; |
319 | |
320 | EXPECT_CALL(mock_compositor, stop()).Times(0); |
321 | - EXPECT_CALL(mock_display, configure(Ref(conf))).Times(0); |
322 | + EXPECT_CALL(mock_display, configure(_)).Times(0); |
323 | EXPECT_CALL(mock_compositor, start()).Times(0); |
324 | |
325 | changer->configure(std::make_shared<mtd::StubSession>(), |
326 | @@ -253,11 +275,14 @@ |
327 | EXPECT_THAT(*base_conf, mt::DisplayConfigMatches(conf)); |
328 | } |
329 | |
330 | -TEST_F(MediatingDisplayChangerTest, handles_hardware_change_properly_when_pausing_system) |
331 | +TEST_F(MediatingDisplayChangerTest, handles_hardware_change_when_display_buffers_are_invalidated) |
332 | { |
333 | using namespace testing; |
334 | mtd::NullDisplayConfiguration conf; |
335 | |
336 | + ON_CALL(mock_display, apply_if_configuration_preserves_display_buffers(_)) |
337 | + .WillByDefault(Return(false)); |
338 | + |
339 | InSequence s; |
340 | EXPECT_CALL(mock_conf_policy, apply_to(Ref(conf))); |
341 | |
342 | @@ -268,6 +293,61 @@ |
343 | changer->configure_for_hardware_change(mt::fake_shared(conf)); |
344 | } |
345 | |
346 | +TEST_F(MediatingDisplayChangerTest, handles_hardware_change_when_display_buffers_are_preserved) |
347 | +{ |
348 | + using namespace testing; |
349 | + mtd::NullDisplayConfiguration conf; |
350 | + |
351 | + { |
352 | + InSequence s; |
353 | + EXPECT_CALL(mock_conf_policy, apply_to(Ref(conf))); |
354 | + |
355 | + EXPECT_CALL(mock_display, apply_if_configuration_preserves_display_buffers(Ref(conf))) |
356 | + .WillOnce(Return(true)); |
357 | + } |
358 | + |
359 | + EXPECT_CALL(mock_compositor, stop()).Times(0); |
360 | + EXPECT_CALL(mock_display, configure(_)).Times(0); |
361 | + EXPECT_CALL(mock_compositor, start()).Times(0); |
362 | + |
363 | + changer->configure_for_hardware_change(mt::fake_shared(conf)); |
364 | +} |
365 | + |
366 | +TEST_F(MediatingDisplayChangerTest, handles_hardware_change_when_display_buffers_are_preserved_but_new_outputs_are_enabled) |
367 | +{ |
368 | + using namespace testing; |
369 | + |
370 | + auto conf = changer->base_configuration(); |
371 | + |
372 | + bool new_output_enabled{false}; |
373 | + conf->for_each_output( |
374 | + [&new_output_enabled](mg::UserDisplayConfigurationOutput& output) |
375 | + { |
376 | + if (!output.used) |
377 | + { |
378 | + new_output_enabled = true; |
379 | + output.used = true; |
380 | + } |
381 | + }); |
382 | + ASSERT_TRUE(new_output_enabled); |
383 | + |
384 | + ON_CALL(mock_display, apply_if_configuration_preserves_display_buffers(_)) |
385 | + .WillByDefault(Return(true)); |
386 | + |
387 | + InSequence s; |
388 | + EXPECT_CALL(mock_conf_policy, apply_to(Ref(*conf))); |
389 | + |
390 | + /* |
391 | + * Currently we have to tear down and recreate the compositor in order to add |
392 | + * a new output. This is not an inherent limitation, and we might do better later. |
393 | + */ |
394 | + EXPECT_CALL(mock_compositor, stop()).Times(1); |
395 | + EXPECT_CALL(mock_display, configure(Ref(*conf))); |
396 | + EXPECT_CALL(mock_compositor, start()).Times(1); |
397 | + |
398 | + changer->configure_for_hardware_change(conf); |
399 | +} |
400 | + |
401 | TEST_F(MediatingDisplayChangerTest, hardware_change_doesnt_apply_base_config_if_per_session_config_is_active) |
402 | { |
403 | using namespace testing; |
404 | @@ -307,11 +387,70 @@ |
405 | changer->configure_for_hardware_change(mt::fake_shared(conf)); |
406 | } |
407 | |
408 | -TEST_F(MediatingDisplayChangerTest, focusing_a_session_with_attached_config_applies_config) |
409 | -{ |
410 | - using namespace testing; |
411 | - auto conf = std::make_shared<mtd::NullDisplayConfiguration>(); |
412 | - auto session1 = std::make_shared<mtd::StubSession>(); |
413 | +TEST_F(MediatingDisplayChangerTest, focusing_a_session_with_db_preserving_attached_config_applies_config) |
414 | +{ |
415 | + using namespace testing; |
416 | + auto conf = std::make_shared<mtd::NullDisplayConfiguration>(); |
417 | + auto session1 = std::make_shared<mtd::StubSession>(); |
418 | + |
419 | + stub_session_container.insert_session(session1); |
420 | + changer->configure(session1, conf); |
421 | + |
422 | + EXPECT_CALL(mock_display, apply_if_configuration_preserves_display_buffers(Ref(*conf))) |
423 | + .WillOnce(Return(true)); |
424 | + |
425 | + EXPECT_CALL(mock_compositor, stop()).Times(0); |
426 | + EXPECT_CALL(mock_display, configure(_)).Times(0); |
427 | + EXPECT_CALL(mock_compositor, start()).Times(0); |
428 | + |
429 | + session_event_sink.handle_focus_change(session1); |
430 | +} |
431 | + |
432 | +TEST_F(MediatingDisplayChangerTest, focusing_a_session_with_db_preserving_but_output_adding_attached_config_applies_config) |
433 | +{ |
434 | + using namespace testing; |
435 | + auto session1 = std::make_shared<mtd::StubSession>(); |
436 | + |
437 | + auto conf = changer->base_configuration(); |
438 | + |
439 | + bool new_output_enabled{false}; |
440 | + conf->for_each_output( |
441 | + [&new_output_enabled](mg::UserDisplayConfigurationOutput& output) |
442 | + { |
443 | + if (!output.used) |
444 | + { |
445 | + new_output_enabled = true; |
446 | + output.used = true; |
447 | + } |
448 | + }); |
449 | + ASSERT_TRUE(new_output_enabled); |
450 | + |
451 | + ON_CALL(mock_display, apply_if_configuration_preserves_display_buffers(_)) |
452 | + .WillByDefault(Return(true)); |
453 | + |
454 | + stub_session_container.insert_session(session1); |
455 | + changer->configure(session1, conf); |
456 | + |
457 | + /* |
458 | + * Currently we have to tear down and recreate the compositor in order to add |
459 | + * a new output. This is not an inherent limitation, and we might do better later. |
460 | + */ |
461 | + InSequence s; |
462 | + EXPECT_CALL(mock_compositor, stop()).Times(1); |
463 | + EXPECT_CALL(mock_display, configure(Ref(*conf))); |
464 | + EXPECT_CALL(mock_compositor, start()).Times(1); |
465 | + |
466 | + session_event_sink.handle_focus_change(session1); |
467 | +} |
468 | + |
469 | +TEST_F(MediatingDisplayChangerTest, focusing_a_session_with_db_invalidating_attached_config_applies_config) |
470 | +{ |
471 | + using namespace testing; |
472 | + auto conf = std::make_shared<mtd::NullDisplayConfiguration>(); |
473 | + auto session1 = std::make_shared<mtd::StubSession>(); |
474 | + |
475 | + ON_CALL(mock_display, apply_if_configuration_preserves_display_buffers(_)) |
476 | + .WillByDefault(Return(false)); |
477 | |
478 | stub_session_container.insert_session(session1); |
479 | changer->configure(session1, conf); |
480 | @@ -324,13 +463,16 @@ |
481 | session_event_sink.handle_focus_change(session1); |
482 | } |
483 | |
484 | -TEST_F(MediatingDisplayChangerTest, focusing_a_session_without_attached_config_applies_base_config) |
485 | +TEST_F(MediatingDisplayChangerTest, focusing_a_session_without_attached_config_applies_base_config_pausing_if_db_invalidated) |
486 | { |
487 | using namespace testing; |
488 | auto conf = std::make_shared<mtd::NullDisplayConfiguration>(); |
489 | auto session1 = std::make_shared<mtd::StubSession>(); |
490 | auto session2 = std::make_shared<mtd::StubSession>(); |
491 | |
492 | + ON_CALL(mock_display, apply_if_configuration_preserves_display_buffers(_)) |
493 | + .WillByDefault(Return(false)); |
494 | + |
495 | stub_session_container.insert_session(session1); |
496 | changer->configure(session1, conf); |
497 | |
498 | @@ -347,6 +489,43 @@ |
499 | session_event_sink.handle_focus_change(session2); |
500 | } |
501 | |
502 | +TEST_F(MediatingDisplayChangerTest, focusing_a_session_without_attached_config_applies_base_config_not_pausing_if_db_preserved) |
503 | +{ |
504 | + using namespace testing; |
505 | + std::shared_ptr<mg::DisplayConfiguration> conf = base_config.clone(); |
506 | + conf->for_each_output( |
507 | + [](mg::UserDisplayConfigurationOutput& output) |
508 | + { |
509 | + if (output.used) |
510 | + { |
511 | + output.orientation = |
512 | + output.orientation == mir_orientation_normal ? mir_orientation_left : mir_orientation_normal; |
513 | + } |
514 | + }); |
515 | + |
516 | + auto session1 = std::make_shared<mtd::StubSession>(); |
517 | + auto session2 = std::make_shared<mtd::StubSession>(); |
518 | + |
519 | + stub_session_container.insert_session(session1); |
520 | + changer->configure(session1, conf); |
521 | + |
522 | + session_event_sink.handle_focus_change(session1); |
523 | + |
524 | + Mock::VerifyAndClearExpectations(&mock_compositor); |
525 | + Mock::VerifyAndClearExpectations(&mock_display); |
526 | + |
527 | + EXPECT_CALL( |
528 | + mock_display, |
529 | + apply_if_configuration_preserves_display_buffers(mt::DisplayConfigMatches(std::cref(base_config)))) |
530 | + .WillOnce(Return(true)); |
531 | + |
532 | + EXPECT_CALL(mock_compositor, stop()).Times(0); |
533 | + EXPECT_CALL(mock_display, configure(_)).Times(0); |
534 | + EXPECT_CALL(mock_compositor, start()).Times(0); |
535 | + |
536 | + session_event_sink.handle_focus_change(session2); |
537 | +} |
538 | + |
539 | TEST_F(MediatingDisplayChangerTest, losing_focus_applies_base_config) |
540 | { |
541 | using namespace testing; |
FAILED: Continuous integration, rev:3702 /mir-jenkins. ubuntu. com/job/ mir-ci/ 1678/ /mir-jenkins. ubuntu. com/job/ build-mir/ 2103/console /mir-jenkins. ubuntu. com/job/ build-0- fetch/2165 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= vivid+overlay/ 2156 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= xenial+ overlay/ 2156 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= yakkety/ 2156 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= clang,platform= mesa,release= yakkety/ 2131/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= xenial+ overlay/ 2131 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= xenial+ overlay/ 2131/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= yakkety/ 2131 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= yakkety/ 2131/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= android, release= vivid+overlay/ 2131 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= android, release= vivid+overlay/ 2131/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= mesa,release= xenial+ overlay/ 2131 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= mesa,release= xenial+ overlay/ 2131/artifact/ output/ *zip*/output. zip
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild: /mir-jenkins. ubuntu. com/job/ mir-ci/ 1678/rebuild
https:/