Mir

Merge lp:~raof/mir/nested-scale-setting into lp:mir

Proposed by Chris Halse Rogers
Status: Merged
Approved by: Chris Halse Rogers
Approved revision: no longer in the source branch.
Merged at revision: 3265
Proposed branch: lp:~raof/mir/nested-scale-setting
Merge into: lp:mir
Diff against target: 254 lines (+150/-6)
3 files modified
src/server/graphics/nested/nested_display_configuration.cpp (+37/-6)
src/server/graphics/nested/nested_display_configuration.h (+20/-0)
tests/acceptance-tests/test_nested_mir.cpp (+93/-0)
To merge this branch: bzr merge lp:~raof/mir/nested-scale-setting
Reviewer Review Type Date Requested Status
Alan Griffiths Approve
Daniel van Vugt Approve
PS Jenkins bot (community) continuous-integration Approve
Mir CI Bot continuous-integration Approve
Alberto Aguirre (community) Approve
Review via email: mp+283324@code.launchpad.net

Commit message

Fix output configuration scale_factor and form_factor for nested servers.

The scale_factor and form_factor aren't exposed in the client MirDisplayOutput struct (and can't easily be, as that's an ABI break), and even if they were it's not clear that it makes sense to let clients set these values.

Store this configuration locally in the NestedDisplayConfiguration instead.

Fixes: https://bugs.launchpad.net/mir/+bug/1535780

Description of the change

Fix output configuration scale_factor and form_factor for nested servers.

The scale_factor and form_factor aren't exposed in the client MirDisplayOutput struct (and can't easily be, as that's an ABI break), and even if they were it's not clear that it makes sense to let clients set these values.

Store this configuration locally in the NestedDisplayConfiguration instead.

To post a comment you must log in.
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:3254
https://mir-jenkins.ubuntu.com/job/mir-ci/98/
Executed test runs:
    None: https://mir-jenkins.ubuntu.com/job/generic-update-mp/98/console

Click here to trigger a rebuild:
https://mir-jenkins.ubuntu.com/job/mir-ci/98/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:3255
https://mir-jenkins.ubuntu.com/job/mir-ci/107/
Executed test runs:
    None: https://mir-jenkins.ubuntu.com/job/generic-update-mp/107/console

Click here to trigger a rebuild:
https://mir-jenkins.ubuntu.com/job/mir-ci/107/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

PASSED: Continuous integration, rev:3256
https://mir-jenkins.ubuntu.com/job/mir-ci/121/
Executed test runs:
    None: https://mir-jenkins.ubuntu.com/job/generic-update-mp/121/console

Click here to trigger a rebuild:
https://mir-jenkins.ubuntu.com/job/mir-ci/121/rebuild

review: Approve (continuous-integration)
Revision history for this message
Alberto Aguirre (albaguirre) wrote :

---
179 + auto base_configuration_now_set = std::make_shared<mt::Signal>();
---

Not used anymore.

LGTM otherwise.

review: Approve
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

PASSED: Continuous integration, rev:3257
https://mir-jenkins.ubuntu.com/job/mir-ci/124/
Executed test runs:
    None: https://mir-jenkins.ubuntu.com/job/generic-update-mp/124/console

Click here to trigger a rebuild:
https://mir-jenkins.ubuntu.com/job/mir-ci/124/rebuild

review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:3256
http://jenkins.qa.ubuntu.com/job/mir-ci/6101/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-android-vivid-i386-build/5646
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-clang-vivid-amd64-build/4553
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-vivid-touch/5602
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-xenial-touch/319
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-xenial-amd64-ci/425
        deb: http://jenkins.qa.ubuntu.com/job/mir-xenial-amd64-ci/425/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-xenial-i386-ci/425
        deb: http://jenkins.qa.ubuntu.com/job/mir-xenial-i386-ci/425/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-vivid-armhf/5599
        deb: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-vivid-armhf/5599/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-runner-touch/8040
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/26912
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-xenial-armhf/315
        deb: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-xenial-armhf/315/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-runner-xenial-touch/171
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/26925

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/mir-ci/6101/rebuild

review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:3257
http://jenkins.qa.ubuntu.com/job/mir-ci/6103/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-android-vivid-i386-build/5650
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-clang-vivid-amd64-build/4557
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-vivid-touch/5606
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-xenial-touch/321
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-xenial-amd64-ci/427
        deb: http://jenkins.qa.ubuntu.com/job/mir-xenial-amd64-ci/427/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-xenial-i386-ci/427
        deb: http://jenkins.qa.ubuntu.com/job/mir-xenial-i386-ci/427/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-vivid-armhf/5603
        deb: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-vivid-armhf/5603/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-runner-touch/8044
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/26929
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-xenial-armhf/317
        deb: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-builder-xenial-armhf/317/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-mediumtests-runner-xenial-touch/173
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/26933

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/mir-ci/6103/rebuild

review: Approve (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Ummkay.

review: Approve
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

+ while (!done && (std::chrono::steady_clock::now() < end_time))

Hmm. Can't we use the display report or something to detect change?

review: Approve
Revision history for this message
Chris Halse Rogers (raof) wrote :

Hm.

Probably, yes. However...

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/server/graphics/nested/nested_display_configuration.cpp'
2--- src/server/graphics/nested/nested_display_configuration.cpp 2016-01-20 23:59:18 +0000
3+++ src/server/graphics/nested/nested_display_configuration.cpp 2016-01-21 23:53:03 +0000
4@@ -59,6 +59,8 @@
5 : mg::DisplayConfiguration(),
6 display_config{copy_config(other.display_config.get())}
7 {
8+ std::lock_guard<std::mutex> lock{other.local_config_mutex};
9+ local_config = other.local_config;
10 }
11
12 void mgn::NestedDisplayConfiguration::for_each_card(
13@@ -78,7 +80,7 @@
14 std::for_each(
15 display_config->outputs,
16 display_config->outputs+display_config->num_outputs,
17- [&f](MirDisplayOutput const& mir_output)
18+ [&f, this](MirDisplayOutput const& mir_output)
19 {
20 std::vector<MirPixelFormat> formats;
21 formats.reserve(mir_output.num_output_formats);
22@@ -90,6 +92,8 @@
23 for (auto p = mir_output.modes; p != mir_output.modes+mir_output.num_modes; ++p)
24 modes.push_back(DisplayConfigurationMode{{p->horizontal_resolution, p->vertical_resolution}, p->refresh_rate});
25
26+ auto local_config = get_local_config_for(mir_output.output_id);
27+
28 DisplayConfigurationOutput const output{
29 DisplayConfigurationOutputId(mir_output.output_id),
30 DisplayConfigurationCardId(mir_output.card_id),
31@@ -105,8 +109,8 @@
32 mir_output.current_format,
33 mir_output.power_mode,
34 mir_output.orientation,
35- 1.0f,
36- mir_form_factor_monitor
37+ local_config.scale,
38+ local_config.form_factor
39 };
40
41 f(output);
42@@ -122,7 +126,7 @@
43 std::for_each(
44 display_config->outputs,
45 display_config->outputs+display_config->num_outputs,
46- [&f](MirDisplayOutput& mir_output)
47+ [&f, this](MirDisplayOutput& mir_output)
48 {
49 std::vector<MirPixelFormat> formats;
50 formats.reserve(mir_output.num_output_formats);
51@@ -145,6 +149,8 @@
52 p->refresh_rate});
53 }
54
55+ auto local_config = get_local_config_for(mir_output.output_id);
56+
57 DisplayConfigurationOutput output{
58 DisplayConfigurationOutputId(mir_output.output_id),
59 DisplayConfigurationCardId(mir_output.card_id),
60@@ -161,13 +167,15 @@
61 mir_output.current_format,
62 mir_output.power_mode,
63 mir_output.orientation,
64- 1.0f,
65- mir_form_factor_monitor
66+ local_config.scale,
67+ local_config.form_factor
68 };
69 UserDisplayConfigurationOutput user(output);
70
71 f(user);
72
73+ set_local_config_for(mir_output.output_id, {user.scale, user.form_factor });
74+
75 mir_output.current_mode = output.current_mode_index;
76 mir_output.current_format = output.current_format;
77 mir_output.position_x = output.top_left.x.as_int();
78@@ -182,3 +190,26 @@
79 {
80 return std::make_unique<mgn::NestedDisplayConfiguration>(*this);
81 }
82+
83+mgn::NestedDisplayConfiguration::LocalOutputConfig
84+mgn::NestedDisplayConfiguration::get_local_config_for(uint32_t output_id) const
85+{
86+ std::lock_guard<std::mutex> lock{local_config_mutex};
87+
88+ constexpr LocalOutputConfig default_values {1.0f, mir_form_factor_monitor };
89+
90+ bool inserted;
91+ decltype(local_config)::iterator keypair;
92+
93+ std::tie(keypair, inserted) = local_config.insert(std::make_pair(output_id, default_values));
94+
95+ // We don't care whether we inserted the default values or retrieved the previously set value.
96+ return keypair->second;
97+}
98+
99+void mgn::NestedDisplayConfiguration::set_local_config_for(uint32_t output_id, LocalOutputConfig const& config)
100+{
101+ std::lock_guard<std::mutex> lock{local_config_mutex};
102+
103+ local_config[output_id] = config;
104+}
105
106=== modified file 'src/server/graphics/nested/nested_display_configuration.h'
107--- src/server/graphics/nested/nested_display_configuration.h 2016-01-20 23:59:18 +0000
108+++ src/server/graphics/nested/nested_display_configuration.h 2016-01-21 23:53:03 +0000
109@@ -22,6 +22,8 @@
110 #include "mir/graphics/display_configuration.h"
111 #include "mir_toolkit/client_types.h"
112 #include <memory>
113+#include <mutex>
114+#include <unordered_map>
115
116 namespace mir
117 {
118@@ -45,7 +47,25 @@
119
120 private:
121 std::shared_ptr<MirDisplayConfiguration> display_config;
122+
123+ /*
124+ * The client display config doesn't currently expose the form factor or scaling factor, nor is it
125+ * entirely clear that it should allow a client to set them.
126+ *
127+ * We therefore need to store these explicitly in the NestedConfiguration.
128+ */
129+ std::mutex mutable local_config_mutex;
130+ struct LocalOutputConfig
131+ {
132+ float scale;
133+ MirFormFactor form_factor;
134+ };
135+ std::unordered_map<uint32_t, LocalOutputConfig> mutable local_config;
136+
137+ LocalOutputConfig get_local_config_for(uint32_t output_id) const;
138+ void set_local_config_for(uint32_t output_id, LocalOutputConfig const& config);
139 };
140+
141 }
142 }
143 }
144
145=== modified file 'tests/acceptance-tests/test_nested_mir.cpp'
146--- tests/acceptance-tests/test_nested_mir.cpp 2016-01-20 23:59:18 +0000
147+++ tests/acceptance-tests/test_nested_mir.cpp 2016-01-21 23:53:03 +0000
148@@ -42,6 +42,7 @@
149 #include "mir/test/doubles/fake_display.h"
150 #include "mir/test/doubles/stub_cursor.h"
151 #include "mir/test/doubles/stub_display_configuration.h"
152+#include "mir/test/signal.h"
153
154 #include "mir/test/doubles/nested_mock_egl.h"
155 #include "mir/test/fake_shared.h"
156@@ -469,6 +470,98 @@
157 EXPECT_THAT(outputs, ContainerEq(display_geometry));
158 }
159
160+TEST_F(NestedServer, shell_sees_set_scaling_factor)
161+{
162+ using namespace std::literals::chrono_literals;
163+ NestedMirRunner nested_mir{new_connection()};
164+
165+ constexpr float expected_scale{2.3f};
166+ constexpr MirFormFactor expected_form_factor{mir_form_factor_tv};
167+
168+ auto const configurator = nested_mir.server.the_display_configuration_controller();
169+ std::shared_ptr<mg::DisplayConfiguration> config = nested_mir.server.the_display()->configuration();
170+
171+ config->for_each_output([] (mg::UserDisplayConfigurationOutput& output)
172+ {
173+ output.scale = expected_scale;
174+ output.form_factor = expected_form_factor;
175+ });
176+
177+ configurator->set_base_configuration(config);
178+
179+ /* Now, because we have absolutely no idea when the call to set_base_configuration will *actually*
180+ * set the base configuration we get to poll configuration() until we see that it's actually changed.
181+ */
182+ auto const end_time = std::chrono::steady_clock::now() + 10s;
183+ bool done{false};
184+ while (!done && (std::chrono::steady_clock::now() < end_time))
185+ {
186+ auto const new_config = nested_mir.server.the_display()->configuration();
187+
188+ new_config->for_each_output([&done, expected_scale, expected_form_factor] (auto const& output)
189+ {
190+ if (output.scale == expected_scale &&
191+ output.form_factor == expected_form_factor)
192+ {
193+ done = true;
194+ }
195+ });
196+ }
197+
198+ EXPECT_THAT(std::chrono::steady_clock::now(), Le(end_time)) << "Timed out waiting for display configuration to propagate";
199+}
200+
201+TEST_F(NestedServer, client_sees_set_scaling_factor)
202+{
203+ using namespace std::literals::chrono_literals;
204+
205+ NestedMirRunner nested_mir{new_connection()};
206+
207+ constexpr float expected_scale{2.3f};
208+ constexpr MirFormFactor expected_form_factor{mir_form_factor_tv};
209+
210+ auto const configurator = nested_mir.server.the_display_configuration_controller();
211+ std::shared_ptr<mg::DisplayConfiguration> config = nested_mir.server.the_display()->configuration();
212+
213+ config->for_each_output([] (mg::UserDisplayConfigurationOutput& output)
214+ {
215+ output.scale = expected_scale;
216+ output.form_factor = expected_form_factor;
217+ });
218+
219+ configurator->set_base_configuration(config);
220+
221+ Client client{nested_mir};
222+
223+ auto spec = mir_connection_create_spec_for_normal_surface(client.connection,
224+ 800, 600,
225+ mir_pixel_format_abgr_8888);
226+
227+ mt::Signal surface_event_received;
228+ mir_surface_spec_set_event_handler(spec, [](MirSurface*, MirEvent const* event, void* ctx)
229+ {
230+ if (mir_event_get_type(event) == mir_event_type_surface_output)
231+ {
232+ auto surface_event = mir_event_get_surface_output_event(event);
233+ EXPECT_THAT(mir_surface_output_event_get_form_factor(surface_event), Eq(expected_form_factor));
234+ EXPECT_THAT(mir_surface_output_event_get_scale(surface_event), Eq(expected_scale));
235+ auto signal = static_cast<mt::Signal*>(ctx);
236+ signal->raise();
237+ }
238+ },
239+ &surface_event_received);
240+
241+ auto surface = mir_surface_create_sync(spec);
242+ mir_surface_spec_release(spec);
243+
244+ auto stream = mir_surface_get_buffer_stream(surface);
245+ mir_buffer_stream_swap_buffers_sync(stream);
246+
247+ mir_surface_release_sync(surface);
248+
249+ EXPECT_TRUE(surface_event_received.wait_for(30s));
250+}
251+
252 //////////////////////////////////////////////////////////////////
253 // TODO the following test was used in investigating lifetime issues.
254 // TODO it may not have much long term value, but decide that later.

Subscribers

People subscribed via source and target branches