Mir

Merge lp:~vanvugt/mir/output-event-refreshrate into lp:mir

Proposed by Daniel van Vugt
Status: Merged
Approved by: Daniel van Vugt
Approved revision: no longer in the source branch.
Merged at revision: 3738
Proposed branch: lp:~vanvugt/mir/output-event-refreshrate
Merge into: lp:mir
Prerequisite: lp:~vanvugt/mir/not-26-yet
Diff against target: 348 lines (+81/-8)
15 files modified
examples/eglapp.c (+3/-2)
include/client/mir/events/event_builders.h (+1/-0)
include/client/mir_toolkit/events/surface_output_event.h (+11/-0)
src/client/event.cpp (+6/-0)
src/client/events/event_builders.cpp (+2/-0)
src/client/symbols.map (+1/-0)
src/common/events/surface_output_event.cpp (+10/-0)
src/common/symbols.map (+2/-0)
src/include/common/mir/events/surface_output_event.h (+6/-0)
src/server/scene/application_session.cpp (+1/-0)
src/server/scene/output_properties_cache.cpp (+1/-0)
src/server/scene/output_properties_cache.h (+1/-0)
src/server/scene/surface_event_source.cpp (+1/-0)
tests/acceptance-tests/test_client_surface_events.cpp (+22/-3)
tests/unit-tests/scene/test_application_session.cpp (+13/-3)
To merge this branch: bzr merge lp:~vanvugt/mir/output-event-refreshrate
Reviewer Review Type Date Requested Status
Mir CI Bot continuous-integration Approve
Chris Halse Rogers Disapprove
Cemil Azizoglu (community) Approve
Kevin DuBois (community) Approve
Review via email: mp+307293@code.launchpad.net

Commit message

Add refresh rate to MirSurfaceOutputEvent.

Description of the change

FAQ:

  * Why?
    Two reasons at least. First and foremost, in future when libmirclient
    is doing its own vsync throttling, just knowing the timestamp of the
    last vsync isn't enough. That only gives you the correct phase
    information. Even if you observe multiple prior vsyncs that still
    won't tell you the maximum refresh rate of the display if your
    previous frames were not fast, and we need to know the maximum rate to
    calculate the correct minimal vsync interval so the client can catch
    up to the full rate of the display.
      Secondly, this gives libmirclient the correct frequency information
    it needs to do accurate touch resampling and remove the 59Hz hack.

  * So clients can do their own vsync now?
    Yes and no. You could use the refresh rate right now in a sleep and
    implement your own vsync that is immune to nesting lag.
    That's great, but it would be without the display vsync timing
    (not wired up with IPC yet) to provide the correct phase. So yes,
    you can use this refresh rate value for your vsync and solve most of
    the lag problem now, but no it's not yet the optimal solution (up to
    one frame extra lag) until we also have the vsync phase information
    from the server.

  * Why not just query the display config?
    That would be more heavy-weight than this approach, and less
    consistent with the current API. But more importantly we need these
    summary mir_surface_output_event_ functions as future proofing to
    support the possibility that the "output" being described is actually
    just a summary of multiple different physical outputs' attributes.

  * Is a double precise enough to do our own frame timing?
    Well, it's all the accuracy we can get right now. But later when
    we've got the vsync phase information too, the precision of the
    refresh_rate value won't matter as much because it will get
    autocorrected with the phase timestamp on each frame. So then we won't
    need much precision from the refresh_rate value in the end.

  * The MSC used in conjuction with UST surely provides this info?
    Indeed that used to be true for fixed framerate displays, but the old
    equation of (delta(UST)/delta(MSC)) doesn't work in the new world of
    GSync and FreeSync. You need to know the best case refresh rate,
    which that equation does not tell you any more.

  * What's MSC and UST?
    See the 'physical-frame' branch.

  * Why add a public client API function?
    Strictly speaking it won't be necessary as the refresh rate
    information will only be required internally by libmirclient. But
    right now it's proving handy for testing to add this one new public
    function.

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

PASSED: Continuous integration, rev:3737
https://mir-jenkins.ubuntu.com/job/mir-ci/1859/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/2354
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/2417
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2409
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2409
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2409
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2383
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2383/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2383
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2383/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2383
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2383/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2383
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2383/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2383
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2383/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2383
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2383/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
Revision history for this message
Kevin DuBois (kdub) wrote :

  * Why add a public client API function?
I could see nested passthrough being interested in seeing the value, so +1 to a public function.

  * Why not just query the display config?
Seems appropriate to have it be a field of the output event.

lgtm

review: Approve
Revision history for this message
Cemil Azizoglu (cemil-azizoglu) wrote :

LGTM

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

So, I think that this *should* be implemented as getting the MirOutput* associated with the event, but that ship may have sailed.

review: Disapprove
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

I half agree (depending on the day of the week), and may yet do just that.

However the alternative of landing this branch which introduces just one function is not bad. Certainly not worth disapproving.

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

FAILED: Autolanding.
More details in the following jenkins job:
https://mir-jenkins.ubuntu.com/job/mir-autolanding/652/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/2382/console
    None: https://mir-jenkins.ubuntu.com/job/generic-land-mp/693/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-0-fetch/2445/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2437/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2437/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2437/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2411/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2411/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2411/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2411/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2411/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2411/console

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

PASSED: Continuous integration, rev:3739
https://mir-jenkins.ubuntu.com/job/mir-ci/1879/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/2383
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/2446
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2438
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2438
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2438
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2412
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2412/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2412
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2412/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2412
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2412/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2412
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2412/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2412
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2412/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2412
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2412/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'examples/eglapp.c'
2--- examples/eglapp.c 2016-10-03 04:00:30 +0000
3+++ examples/eglapp.c 2016-10-04 08:31:47 +0000
4@@ -130,11 +130,12 @@
5 unsigned ff = mir_surface_output_event_get_form_factor(out);
6 char const* form_factor = (ff < 6) ? form_factor_name[ff] : "out-of-range";
7
8- printf("Surface is on output %u: %d DPI, scale %.1fx, %s form factor\n",
9+ printf("Surface is on output %u: %d DPI, scale %.1fx, %s form factor, %.2fHz\n",
10 mir_surface_output_event_get_output_id(out),
11 mir_surface_output_event_get_dpi(out),
12 mir_surface_output_event_get_scale(out),
13- form_factor);
14+ form_factor,
15+ mir_surface_output_event_get_refresh_rate(out));
16 }
17
18 static void mir_eglapp_handle_event(MirSurface* surface, MirEvent const* ev, void* context)
19
20=== modified file 'include/client/mir/events/event_builders.h'
21--- include/client/mir/events/event_builders.h 2016-09-19 04:16:15 +0000
22+++ include/client/mir/events/event_builders.h 2016-10-04 08:31:47 +0000
23@@ -55,6 +55,7 @@
24 frontend::SurfaceId const& surface_id,
25 int dpi,
26 float scale,
27+ double refresh_rate,
28 MirFormFactor form_factor,
29 uint32_t id);
30
31
32=== modified file 'include/client/mir_toolkit/events/surface_output_event.h'
33--- include/client/mir_toolkit/events/surface_output_event.h 2016-06-23 06:46:20 +0000
34+++ include/client/mir_toolkit/events/surface_output_event.h 2016-10-04 08:31:47 +0000
35@@ -55,6 +55,17 @@
36 float mir_surface_output_event_get_scale(MirSurfaceOutputEvent const* ev);
37
38 /**
39+ * Retrieve the maximum refresh rate of the output(s) associated with a
40+ * MirSurfaceOutputEvent. For variable refresh rate displays this represents
41+ * the maximum refresh rate of the display to aim for, rather than a measurement
42+ * of recent performance.
43+ *
44+ * \param [in] ev The event
45+ * \return The refresh rate in Hz
46+ */
47+double mir_surface_output_event_get_refresh_rate(MirSurfaceOutputEvent const* ev);
48+
49+/**
50 * Retrieve the ID of the output this surface is on from a MirSurfaceOutputEvent
51 *
52 * \param [in] ev The event
53
54=== modified file 'src/client/event.cpp'
55--- src/client/event.cpp 2016-09-19 04:16:15 +0000
56+++ src/client/event.cpp 2016-10-04 08:31:47 +0000
57@@ -278,6 +278,12 @@
58 return ev->scale();
59 }
60
61+double mir_surface_output_event_get_refresh_rate(MirSurfaceOutputEvent const* ev)
62+{
63+ expect_event_type(ev, mir_event_type_surface_output);
64+ return ev->refresh_rate();
65+}
66+
67 uint32_t mir_surface_output_event_get_output_id(MirSurfaceOutputEvent const *ev)
68 {
69 expect_event_type(ev, mir_event_type_surface_output);
70
71=== modified file 'src/client/events/event_builders.cpp'
72--- src/client/events/event_builders.cpp 2016-09-19 04:16:15 +0000
73+++ src/client/events/event_builders.cpp 2016-10-04 08:31:47 +0000
74@@ -127,6 +127,7 @@
75 mf::SurfaceId const& surface_id,
76 int dpi,
77 float scale,
78+ double refresh_rate,
79 MirFormFactor form_factor,
80 uint32_t output_id)
81 {
82@@ -135,6 +136,7 @@
83 e->set_surface_id(surface_id.as_value());
84 e->set_dpi(dpi);
85 e->set_scale(scale);
86+ e->set_refresh_rate(refresh_rate);
87 e->set_form_factor(form_factor);
88 e->set_output_id(output_id);
89
90
91=== modified file 'src/client/symbols.map'
92--- src/client/symbols.map 2016-10-04 07:43:10 +0000
93+++ src/client/symbols.map 2016-10-04 08:31:47 +0000
94@@ -433,6 +433,7 @@
95 mir_surface_placement_get_relative_position;
96 mir_display_output_type_name;
97 mir_output_type_name;
98+ mir_surface_output_event_get_refresh_rate;
99 } MIR_CLIENT_0.24;
100
101 MIR_CLIENT_DETAIL_0.25 {
102
103=== modified file 'src/common/events/surface_output_event.cpp'
104--- src/common/events/surface_output_event.cpp 2016-03-29 03:41:45 +0000
105+++ src/common/events/surface_output_event.cpp 2016-10-04 08:31:47 +0000
106@@ -53,6 +53,16 @@
107 scale_ = scale;
108 }
109
110+double MirSurfaceOutputEvent::refresh_rate() const
111+{
112+ return refresh_rate_;
113+}
114+
115+void MirSurfaceOutputEvent::set_refresh_rate(double rate)
116+{
117+ refresh_rate_ = rate;
118+}
119+
120 MirFormFactor MirSurfaceOutputEvent::form_factor() const
121 {
122 return form_factor_;
123
124=== modified file 'src/common/symbols.map'
125--- src/common/symbols.map 2016-09-27 08:57:34 +0000
126+++ src/common/symbols.map 2016-10-04 08:31:47 +0000
127@@ -402,5 +402,7 @@
128 MirSurfacePlacementEvent::placement*;
129 MirSurfacePlacementEvent::set_placement*;
130 mir::output_type_name*;
131+ MirSurfaceOutputEvent::refresh_rate*;
132+ MirSurfaceOutputEvent::set_refresh_rate*;
133 };
134 } MIR_COMMON_0.24;
135
136=== modified file 'src/include/common/mir/events/surface_output_event.h'
137--- src/include/common/mir/events/surface_output_event.h 2016-03-30 19:01:10 +0000
138+++ src/include/common/mir/events/surface_output_event.h 2016-10-04 08:31:47 +0000
139@@ -24,6 +24,8 @@
140
141 #include "mir/events/event.h"
142
143+// XXX This is a private structure so why are its members kept private?
144+// What's the point in having all the getters and setters?
145 struct MirSurfaceOutputEvent : MirEvent
146 {
147 MirSurfaceOutputEvent();
148@@ -37,6 +39,9 @@
149 float scale() const;
150 void set_scale(float scale);
151
152+ double refresh_rate() const;
153+ void set_refresh_rate(double);
154+
155 MirFormFactor form_factor() const;
156 void set_form_factor(MirFormFactor factor);
157
158@@ -49,6 +54,7 @@
159 float scale_{0.0f};
160 MirFormFactor form_factor_;
161 uint32_t output_id_{std::numeric_limits<uint32_t>::max()};
162+ double refresh_rate_{0.0};
163 };
164
165 #endif /* MIR_COMMON_SURFACE_OUTPUT_EVENT_H_ */
166
167=== modified file 'src/server/scene/application_session.cpp'
168--- src/server/scene/application_session.cpp 2016-09-28 00:41:49 +0000
169+++ src/server/scene/application_session.cpp 2016-10-04 08:31:47 +0000
170@@ -328,6 +328,7 @@
171 surface.first,
172 output_properties->dpi,
173 output_properties->scale,
174+ output_properties->refresh_rate,
175 output_properties->form_factor,
176 static_cast<uint32_t>(output_properties->id.as_value())
177 ));
178
179=== modified file 'src/server/scene/output_properties_cache.cpp'
180--- src/server/scene/output_properties_cache.cpp 2016-01-29 08:18:22 +0000
181+++ src/server/scene/output_properties_cache.cpp 2016-10-04 08:31:47 +0000
182@@ -57,6 +57,7 @@
183 output.extents(),
184 calculate_dpi(mode.size, output.physical_size_mm),
185 output.scale,
186+ mode.vrefresh_hz,
187 output.form_factor,
188 output.id});
189 }
190
191=== modified file 'src/server/scene/output_properties_cache.h'
192--- src/server/scene/output_properties_cache.h 2016-01-29 08:18:22 +0000
193+++ src/server/scene/output_properties_cache.h 2016-10-04 08:31:47 +0000
194@@ -37,6 +37,7 @@
195 geometry::Rectangle extents;
196 int dpi;
197 float scale;
198+ double refresh_rate;
199 MirFormFactor form_factor;
200 graphics::DisplayConfigurationOutputId id;
201 };
202
203=== modified file 'src/server/scene/surface_event_source.cpp'
204--- src/server/scene/surface_event_source.cpp 2016-09-19 04:16:15 +0000
205+++ src/server/scene/surface_event_source.cpp 2016-10-04 08:31:47 +0000
206@@ -57,6 +57,7 @@
207 id,
208 new_output_properties->dpi,
209 new_output_properties->scale,
210+ new_output_properties->refresh_rate,
211 new_output_properties->form_factor,
212 static_cast<uint32_t>(new_output_properties->id.as_value())
213 ));
214
215=== modified file 'tests/acceptance-tests/test_client_surface_events.cpp'
216--- tests/acceptance-tests/test_client_surface_events.cpp 2016-06-27 10:58:58 +0000
217+++ tests/acceptance-tests/test_client_surface_events.cpp 2016-10-04 08:31:47 +0000
218@@ -37,6 +37,7 @@
219 #include <condition_variable>
220 #include <chrono>
221 #include <mutex>
222+#include <unordered_map>
223
224 namespace mf = mir::frontend;
225 namespace ms = mir::scene;
226@@ -265,16 +266,21 @@
227
228 auto constexpr form_factor = mir_form_factor_tablet;
229 float constexpr scale = 2.15f;
230+ std::unordered_map<unsigned,mg::DisplayConfigurationMode> current_mode;
231
232 auto display_configuration = server.the_display()->configuration();
233
234 display_configuration->for_each_output(
235- [](mg::UserDisplayConfigurationOutput& output_config)
236+ [&current_mode](mg::UserDisplayConfigurationOutput& output_config)
237 {
238 output_config.scale = scale;
239 output_config.form_factor = form_factor;
240+ current_mode[output_config.id.as_value()] =
241+ output_config.modes[output_config.current_mode_index];
242 });
243
244+ ASSERT_FALSE(current_mode.empty());
245+
246 set_event_filter(mir_event_type_surface_output);
247 reset_last_event();
248
249@@ -290,6 +296,10 @@
250
251 EXPECT_THAT(mir_surface_output_event_get_form_factor(output_event), Eq(form_factor));
252 EXPECT_THAT(mir_surface_output_event_get_scale(output_event), FloatEq(scale));
253+
254+ auto id = mir_surface_output_event_get_output_id(output_event);
255+ ASSERT_THAT(current_mode.find(id), Ne(current_mode.end()));
256+ EXPECT_THAT(mir_surface_output_event_get_refresh_rate(output_event), Eq(current_mode[id].vrefresh_hz));
257 }
258
259 TEST_F(ClientSurfaceEvents, can_unset_surface_event_handler)
260@@ -526,6 +536,7 @@
261 float constexpr scale = 2.15f;
262
263 std::vector<uint32_t> display_ids;
264+ std::unordered_map<unsigned,mg::DisplayConfigurationMode> current_mode;
265
266 {
267 mt::Signal display_config_changed;
268@@ -535,13 +546,17 @@
269 std::shared_ptr<mg::DisplayConfiguration> const display_configuration{server.the_display()->configuration()};
270
271 display_configuration->for_each_output(
272- [&display_ids](mg::UserDisplayConfigurationOutput& output_config)
273+ [&display_ids,&current_mode](mg::UserDisplayConfigurationOutput& output_config)
274 {
275 output_config.scale = scale;
276 output_config.form_factor = form_factor;
277 display_ids.push_back(static_cast<uint32_t>(output_config.id.as_value()));
278+ current_mode[output_config.id.as_value()] =
279+ output_config.modes[output_config.current_mode_index];
280 });
281
282+ ASSERT_FALSE(current_mode.empty());
283+
284 set_event_filter(mir_event_type_surface_output);
285 reset_last_event();
286
287@@ -568,7 +583,11 @@
288 auto surface_event = mir_event_get_surface_output_event(context.event);
289 EXPECT_THAT(mir_surface_output_event_get_form_factor(surface_event), Eq(form_factor));
290 EXPECT_THAT(mir_surface_output_event_get_scale(surface_event), Eq(scale));
291- EXPECT_THAT(display_ids, Contains(Eq(mir_surface_output_event_get_output_id(surface_event))));
292+ auto id = mir_surface_output_event_get_output_id(surface_event);
293+ EXPECT_THAT(display_ids, Contains(Eq(id)));
294+ ASSERT_THAT(current_mode.find(id), Ne(current_mode.end()));
295+ EXPECT_THAT(mir_surface_output_event_get_refresh_rate(surface_event),
296+ Eq(current_mode[id].vrefresh_hz));
297
298 mir_surface_release_sync(surface);
299 }
300
301=== modified file 'tests/unit-tests/scene/test_application_session.cpp'
302--- tests/unit-tests/scene/test_application_session.cpp 2016-09-28 00:41:48 +0000
303+++ tests/unit-tests/scene/test_application_session.cpp 2016-10-04 08:31:47 +0000
304@@ -836,8 +836,8 @@
305 struct ApplicationSessionSurfaceOutput : public ApplicationSession
306 {
307 ApplicationSessionSurfaceOutput() :
308- high_dpi(static_cast<mg::DisplayConfigurationOutputId>(5), {3840, 2160}, {509, 286}, 2.5f, mir_form_factor_monitor),
309- projector(static_cast<mg::DisplayConfigurationOutputId>(2), {1280, 1024}, {800, 600}, 0.5f, mir_form_factor_projector),
310+ high_dpi(static_cast<mg::DisplayConfigurationOutputId>(5), {3840, 2160}, {509, 286}, 2.5f, 60.0, mir_form_factor_monitor),
311+ projector(static_cast<mg::DisplayConfigurationOutputId>(2), {1280, 1024}, {800, 600}, 0.5f, 50.0, mir_form_factor_projector),
312 stub_surface_factory{std::make_shared<ObserverPreservingSurfaceFactory>()},
313 sender{std::make_shared<testing::NiceMock<mtd::MockEventSink>>()},
314 app_session(
315@@ -860,8 +860,9 @@
316 geom::Size const& resolution,
317 geom::Size const& physical_size,
318 float scale,
319+ double hz,
320 MirFormFactor form_factor) :
321- output{id, resolution, physical_size, mir_pixel_format_argb_8888, 60.0, true},
322+ output{id, resolution, physical_size, mir_pixel_format_argb_8888, hz, true},
323 form_factor{form_factor},
324 scale{scale},
325 dpi{calculate_dpi(resolution, physical_size)},
326@@ -902,6 +903,11 @@
327
328 auto const event = mir_event_get_surface_output_event(arg);
329
330+ if (output.output.current_mode_index >= output.output.modes.size())
331+ return false;
332+
333+ auto const& mode = output.output.modes[output.output.current_mode_index];
334+
335 return
336 ExplainMatchResult(
337 Eq(output.dpi),
338@@ -916,6 +922,10 @@
339 mir_surface_output_event_get_scale(event),
340 result_listener) &&
341 ExplainMatchResult(
342+ Eq(mode.vrefresh_hz),
343+ mir_surface_output_event_get_refresh_rate(event),
344+ result_listener) &&
345+ ExplainMatchResult(
346 Eq(output.id),
347 mir_surface_output_event_get_output_id(event),
348 result_listener);

Subscribers

People subscribed via source and target branches