Mir

Merge lp:~kdub/mir/report-vsync into lp:mir

Proposed by Kevin DuBois
Status: Merged
Approved by: Kevin DuBois
Approved revision: no longer in the source branch.
Merged at revision: 2361
Proposed branch: lp:~kdub/mir/report-vsync
Merge into: lp:mir
Diff against target: 782 lines (+228/-89)
26 files modified
src/include/platform/mir/graphics/display_report.h (+2/-0)
src/platforms/android/server/display.cpp (+9/-1)
src/platforms/android/server/display.h (+2/-0)
src/platforms/android/server/fb_device.cpp (+3/-1)
src/platforms/android/server/fb_device.h (+3/-1)
src/platforms/android/server/hwc_blanking_control.cpp (+4/-3)
src/platforms/android/server/hwc_configuration.h (+6/-2)
src/platforms/mesa/server/display.cpp (+1/-1)
src/platforms/mesa/server/kms_page_flipper.cpp (+19/-10)
src/platforms/mesa/server/kms_page_flipper.h (+5/-2)
src/server/report/logging/display_report.cpp (+26/-1)
src/server/report/logging/display_report.h (+24/-13)
src/server/report/logging/logging_report_factory.cpp (+1/-1)
src/server/report/lttng/display_report.cpp (+2/-6)
src/server/report/lttng/display_report.h (+10/-11)
src/server/report/lttng/display_report_tp.h (+9/-0)
src/server/report/null/display_report.cpp (+1/-0)
src/server/report/null/display_report.h (+1/-0)
tests/include/mir_test_doubles/mock_display_report.h (+1/-2)
tests/include/mir_test_doubles/stub_display_builder.h (+5/-4)
tests/unit-tests/graphics/android/test_display.cpp (+26/-4)
tests/unit-tests/graphics/android/test_display_hotplug.cpp (+3/-3)
tests/unit-tests/graphics/android/test_hwc_configuration.cpp (+13/-7)
tests/unit-tests/graphics/mesa/test_display.cpp (+5/-4)
tests/unit-tests/graphics/mesa/test_kms_page_flipper.cpp (+20/-1)
tests/unit-tests/logging/test_display_report.cpp (+27/-11)
To merge this branch: bzr merge lp:~kdub/mir/report-vsync
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Robert Carr (community) Approve
Alan Griffiths Approve
Andreas Pokorny (community) Approve
Alexandros Frantzis (community) Approve
Daniel van Vugt Abstain
Review via email: mp+251532@code.launchpad.net

Commit message

graphics: add a report_vsync method for android and mesa in mg::DisplayReport with logging, null, and lttng implementations of function.

Description of the change

graphics: add a report_vsync method for android and mesa in mg::DisplayReport with logging, null, and lttng implementations of function.

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

Suggest "needs fixing", but not strictly.

(1) The name arguably needs fixing because "vsync" is not an event. The two events are (a) vblank and then (about 50-60 microseconds later); (b) page flip completed. Although not all platforms will implement it as a "page flip" so the generic term we invented "post" could be used.

(2) These two equivalent reporting points would be less confusing if unified:

180 /* If the page flip we are waiting for has arrived we are done. */
181 if (page_flip_is_done(crtc_id))
182 + {
183 + report->report_vsync(std::to_string(crtc_id));
184 return;
185 + }
186
187 /* ...otherwise we become the worker */
188 worker_tid = std::this_thread::get_id();
189 @@ -140,6 +146,7 @@
190 */
191 pf_cv.notify_all();
192 }
193 + report->report_vsync(std::to_string(crtc_id));

You can do this by making ::page_flip_handler call a new `KMSPageFlipper::page_flip_handler()', as that would have access to the `report' and other private fields. And then you correctly only have to call `report_vsync' in one place.

This is fresh in my mind as I spent much of the past few days hacking this code :)

review: Needs Fixing
Revision history for this message
Daniel van Vugt (vanvugt) :
review: Abstain
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

(1) Whoops, don't call it "post". "post" is the push event at the back of the DisplayBuffer's queue, whereas you're actually measuring the pop from the front. So yeah call it "vsync" if not "scan-out" etc.

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

45 + display_report->report_vsync(std::to_string(name));

The report interfaces shouldn't force any unnecessary object creation. (Like creating a string here.) In practice we've got an int - so can't we pass that and stream that to output only if reporting?

review: Needs Fixing
Revision history for this message
Kevin DuBois (kdub) wrote :

@Daniel,
1) seems like were keeping report_vsync() then?
2) good idea, we now call the report from the pageflip callback.

@Alan, corrected to take an int as a display id.

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
Kevin DuBois (kdub) wrote :

Looks like a transient error:
subprocess.CalledProcessError: Command 'phablet-network --skip-setup' returned non-zero exit status 124

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

(3) You don't need to pass pending_page_flips into the callback any more. Just do the erase in notify_page_flip instead...
156 + page_flip_data->flipper->notify_page_flip(page_flip_data->crtc_id);
157 page_flip_data->pending->erase(page_flip_data->crtc_id);
~~
180 - pending_page_flips[crtc_id] = PageFlipEventData{&pending_page_flips, crtc_id};
181 + pending_page_flips[crtc_id] = PageFlipEventData{&pending_page_flips, crtc_id, this};

(4) The timing is slightly off, but it's probably negligible. The report will be called after the actual page flip happened, because we're calling it from our wait function which could be anything up to a frame later than when the flip "vsync" occurred. To get accurate timings into the report, use the (presently unused) timestamp parameters in the page flip callback (which is a kernel timestamp relative to CLOCK_MONOTONIC). Although the complexity this creates might be worse than any inaccuracies in the current approach. It's also platform-specific unless you convert between clocks. So maybe not...

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

OK

One thought though...

239 +void mrl::DisplayReport::report_vsync(unsigned int display_id)
240 +{
241 + logger->log(ml::Severity::informational, "vsync event on [" + std::to_string(display_id) + "]", component());
242 +}

...is the raw "vsync event on [...]" log message useful or should the report be collating statistical information?

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

Looks good.

> (3) You don't need to pass pending_page_flips into the callback any more.

+1 but not a blocker

review: Approve
Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote :

looks good, yes and agree.. that might be to much spam to be interesting. I think it might also be fine to just omit it for now, until we figure out what information might be worth interpreting.

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

(3) is a good improvement, added to this branch
(4) true, although I think it would be neglible as well (I'm interested in hundreds-of-microsecond resolution)

Also collated the vsync data so it would be reported at most once per second.

Revision history for this message
Kevin DuBois (kdub) wrote :

> (3) is a good improvement, added to this branch
> (4) true, although I think it would be neglible as well (I'm interested in
> hundreds-of-microsecond resolution)
>
> Also collated the vsync data so it would be reported at most once per second.

example output:
[1425479039.147480] graphics: 42 vsync events on [0] over 1004ms
[1425479040.148487] graphics: 60 vsync events on [0] over 1001ms
[1425479041.149372] graphics: 60 vsync events on [0] over 1000ms

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

263 + event_map[display_id]++;
264 + if (now > last_report + report_interval)
265 + {
266 + for(auto const& event : event_map)
267 + logger->log(ml::Severity::informational,
268 + std::to_string(event.second) + " vsync events on [" +
269 + std::to_string(event.first) + "] over " +
270 + std::to_string(duration_cast<milliseconds>(now - last_report).count()) + "ms",
271 + component());
272 + event_map.clear();
273 + last_report = now;
274 + }

Needs a mutex & lock

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

LGTM

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

^^manually cancelled

Revision history for this message
Robert Carr (robertcarr) wrote :

LGTM.

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/include/platform/mir/graphics/display_report.h'
2--- src/include/platform/mir/graphics/display_report.h 2015-01-21 07:34:50 +0000
3+++ src/include/platform/mir/graphics/display_report.h 2015-03-04 14:36:55 +0000
4@@ -35,6 +35,8 @@
5 virtual void report_successful_egl_buffer_swap_on_construction() = 0;
6 virtual void report_successful_display_construction() = 0;
7 virtual void report_egl_configuration(EGLDisplay disp, EGLConfig cfg) = 0;
8+ virtual void report_vsync(unsigned int display_id) = 0;
9+
10 /* gbm specific */
11 virtual void report_successful_drm_mode_set_crtc_on_construction() = 0;
12 virtual void report_drm_master_failure(int error) = 0;
13
14=== modified file 'src/platforms/android/server/display.cpp'
15--- src/platforms/android/server/display.cpp 2015-03-03 06:56:37 +0000
16+++ src/platforms/android/server/display.cpp 2015-03-04 14:36:55 +0000
17@@ -135,9 +135,12 @@
18 std::shared_ptr<GLConfig> const& gl_config,
19 std::shared_ptr<DisplayReport> const& display_report,
20 mga::OverlayOptimization overlay_option) :
21+ display_report{display_report},
22 display_buffer_builder{display_buffer_builder},
23 hwc_config{display_buffer_builder->create_hwc_configuration()},
24- hotplug_subscription{hwc_config->subscribe_to_config_changes(std::bind(&mga::Display::on_hotplug, this))},
25+ hotplug_subscription{hwc_config->subscribe_to_config_changes(
26+ std::bind(&mga::Display::on_hotplug, this),
27+ std::bind(&mga::Display::on_vsync, this, std::placeholders::_1))},
28 primary_attribs(hwc_config->active_attribs_for(mga::DisplayName::primary)),
29 external_attribs(hwc_config->active_attribs_for(mga::DisplayName::external)),
30 config(
31@@ -269,6 +272,11 @@
32 display_change_pipe->notify_change();
33 }
34
35+void mga::Display::on_vsync(DisplayName name) const
36+{
37+ display_report->report_vsync(name);
38+}
39+
40 void mga::Display::register_configuration_change_handler(
41 EventHandlerRegister& event_handler,
42 DisplayConfigurationChangeHandler const& change_handler)
43
44=== modified file 'src/platforms/android/server/display.h'
45--- src/platforms/android/server/display.h 2015-03-03 06:56:37 +0000
46+++ src/platforms/android/server/display.h 2015-03-04 14:36:55 +0000
47@@ -80,7 +80,9 @@
48
49 private:
50 void on_hotplug();
51+ void on_vsync(DisplayName) const;
52
53+ std::shared_ptr<DisplayReport> const display_report;
54 std::shared_ptr<DisplayComponentFactory> const display_buffer_builder;
55 std::mutex mutable configuration_mutex;
56 bool mutable configuration_dirty{false};
57
58=== modified file 'src/platforms/android/server/fb_device.cpp'
59--- src/platforms/android/server/fb_device.cpp 2015-03-03 06:56:37 +0000
60+++ src/platforms/android/server/fb_device.cpp 2015-03-04 14:36:55 +0000
61@@ -68,7 +68,9 @@
62 fb_num};
63 }
64
65-mga::ConfigChangeSubscription mga::FbControl::subscribe_to_config_changes(std::function<void()> const&)
66+mga::ConfigChangeSubscription mga::FbControl::subscribe_to_config_changes(
67+ std::function<void()> const&,
68+ std::function<void(DisplayName)> const&)
69 {
70 return nullptr;
71 }
72
73=== modified file 'src/platforms/android/server/fb_device.h'
74--- src/platforms/android/server/fb_device.h 2015-03-03 06:56:37 +0000
75+++ src/platforms/android/server/fb_device.h 2015-03-04 14:36:55 +0000
76@@ -37,7 +37,9 @@
77 FbControl(std::shared_ptr<framebuffer_device_t> const& fbdev);
78 void power_mode(DisplayName, MirPowerMode) override;
79 DisplayAttribs active_attribs_for(DisplayName) override;
80- ConfigChangeSubscription subscribe_to_config_changes(std::function<void()> const& cb) override;
81+ ConfigChangeSubscription subscribe_to_config_changes(
82+ std::function<void()> const& hotplug_cb,
83+ std::function<void(DisplayName)> const& vsync_cb) override;
84 private:
85 std::shared_ptr<framebuffer_device_t> const fb_device;
86 };
87
88=== modified file 'src/platforms/android/server/hwc_blanking_control.cpp'
89--- src/platforms/android/server/hwc_blanking_control.cpp 2015-03-03 06:56:37 +0000
90+++ src/platforms/android/server/hwc_blanking_control.cpp 2015-03-04 14:36:55 +0000
91@@ -146,13 +146,14 @@
92 }
93
94 mga::ConfigChangeSubscription mga::HwcBlankingControl::subscribe_to_config_changes(
95- std::function<void()> const& hotplug)
96+ std::function<void()> const& hotplug,
97+ std::function<void(DisplayName)> const& vsync)
98 {
99 return std::make_shared<
100 mir::raii::PairedCalls<std::function<void()>, std::function<void()>>>(
101- [hotplug, this]{
102+ [hotplug, vsync, this]{
103 hwc_device->subscribe_to_events(this,
104- [](DisplayName, std::chrono::nanoseconds){},
105+ [vsync](DisplayName name, std::chrono::nanoseconds){ vsync(name); },
106 [hotplug](DisplayName, bool){ hotplug(); },
107 []{});
108 },
109
110=== modified file 'src/platforms/android/server/hwc_configuration.h'
111--- src/platforms/android/server/hwc_configuration.h 2015-02-13 06:12:34 +0000
112+++ src/platforms/android/server/hwc_configuration.h 2015-03-04 14:36:55 +0000
113@@ -50,7 +50,9 @@
114 virtual ~HwcConfiguration() = default;
115 virtual void power_mode(DisplayName, MirPowerMode) = 0;
116 virtual DisplayAttribs active_attribs_for(DisplayName) = 0;
117- virtual ConfigChangeSubscription subscribe_to_config_changes(std::function<void()> const& cb) = 0;
118+ virtual ConfigChangeSubscription subscribe_to_config_changes(
119+ std::function<void()> const& hotplug_cb,
120+ std::function<void(DisplayName)> const& vsync_cb) = 0;
121
122 protected:
123 HwcConfiguration() = default;
124@@ -65,7 +67,9 @@
125 HwcBlankingControl(std::shared_ptr<HwcWrapper> const&);
126 void power_mode(DisplayName, MirPowerMode) override;
127 DisplayAttribs active_attribs_for(DisplayName) override;
128- ConfigChangeSubscription subscribe_to_config_changes(std::function<void()> const& cb) override;
129+ ConfigChangeSubscription subscribe_to_config_changes(
130+ std::function<void()> const& hotplug_cb,
131+ std::function<void(DisplayName)> const& vsync_cb) override;
132
133 private:
134 DeviceQuirks quirks{PropertiesOps{}};
135
136=== modified file 'src/platforms/mesa/server/display.cpp'
137--- src/platforms/mesa/server/display.cpp 2015-02-26 03:20:09 +0000
138+++ src/platforms/mesa/server/display.cpp 2015-03-04 14:36:55 +0000
139@@ -88,7 +88,7 @@
140 monitor(mir::udev::Context()),
141 shared_egl{*gl_config},
142 output_container{platform->drm->fd,
143- std::make_shared<KMSPageFlipper>(platform->drm->fd)},
144+ std::make_shared<KMSPageFlipper>(platform->drm->fd, listener)},
145 current_display_configuration{platform->drm->fd},
146 gl_config{gl_config}
147 {
148
149=== modified file 'src/platforms/mesa/server/kms_page_flipper.cpp'
150--- src/platforms/mesa/server/kms_page_flipper.cpp 2015-01-22 09:00:14 +0000
151+++ src/platforms/mesa/server/kms_page_flipper.cpp 2015-03-04 14:36:55 +0000
152@@ -37,15 +37,18 @@
153 void* data)
154 {
155 auto page_flip_data = static_cast<mgm::PageFlipEventData*>(data);
156- page_flip_data->pending->erase(page_flip_data->crtc_id);
157-}
158-
159-}
160-
161-mgm::KMSPageFlipper::KMSPageFlipper(int drm_fd)
162- : drm_fd{drm_fd},
163- pending_page_flips(),
164- worker_tid()
165+ page_flip_data->flipper->notify_page_flip(page_flip_data->crtc_id);
166+}
167+
168+}
169+
170+mgm::KMSPageFlipper::KMSPageFlipper(
171+ int drm_fd,
172+ std::shared_ptr<DisplayReport> const& report) :
173+ drm_fd{drm_fd},
174+ report{report},
175+ pending_page_flips(),
176+ worker_tid()
177 {
178 }
179
180@@ -56,7 +59,7 @@
181 if (pending_page_flips.find(crtc_id) != pending_page_flips.end())
182 BOOST_THROW_EXCEPTION(std::logic_error("Page flip for crtc_id is already scheduled"));
183
184- pending_page_flips[crtc_id] = PageFlipEventData{&pending_page_flips, crtc_id};
185+ pending_page_flips[crtc_id] = PageFlipEventData{crtc_id, this};
186
187 auto ret = drmModePageFlip(drm_fd, crtc_id, fb_id,
188 DRM_MODE_PAGE_FLIP_EVENT,
189@@ -154,3 +157,9 @@
190 {
191 return pending_page_flips.find(crtc_id) == pending_page_flips.end();
192 }
193+
194+void mgm::KMSPageFlipper::notify_page_flip(uint32_t crtc_id)
195+{
196+ report->report_vsync(crtc_id);
197+ pending_page_flips.erase(crtc_id);
198+}
199
200=== modified file 'src/platforms/mesa/server/kms_page_flipper.h'
201--- src/platforms/mesa/server/kms_page_flipper.h 2015-01-22 09:00:14 +0000
202+++ src/platforms/mesa/server/kms_page_flipper.h 2015-03-04 14:36:55 +0000
203@@ -39,26 +39,29 @@
204 namespace mesa
205 {
206
207+class KMSPageFlipper;
208 struct PageFlipEventData
209 {
210- std::unordered_map<uint32_t,PageFlipEventData>* pending;
211 uint32_t crtc_id;
212+ KMSPageFlipper* flipper;
213 };
214
215 class KMSPageFlipper : public PageFlipper
216 {
217 public:
218- KMSPageFlipper(int drm_fd);
219+ KMSPageFlipper(int drm_fd, std::shared_ptr<DisplayReport> const& report);
220
221 bool schedule_flip(uint32_t crtc_id, uint32_t fb_id);
222 void wait_for_flip(uint32_t crtc_id);
223
224 std::thread::id debug_get_worker_tid();
225
226+ void notify_page_flip(uint32_t crtc_id);
227 private:
228 bool page_flip_is_done(uint32_t crtc_id);
229
230 int const drm_fd;
231+ std::shared_ptr<DisplayReport> const report;
232 std::unordered_map<uint32_t,PageFlipEventData> pending_page_flips;
233 std::mutex pf_mutex;
234 std::condition_variable pf_cv;
235
236=== modified file 'src/server/report/logging/display_report.cpp'
237--- src/server/report/logging/display_report.cpp 2015-01-21 07:34:50 +0000
238+++ src/server/report/logging/display_report.cpp 2015-03-04 14:36:55 +0000
239@@ -25,7 +25,12 @@
240 namespace ml=mir::logging;
241 namespace mrl=mir::report::logging;
242
243-mrl::DisplayReport::DisplayReport(const std::shared_ptr<ml::Logger>& logger) : logger(logger)
244+mrl::DisplayReport::DisplayReport(
245+ std::shared_ptr<ml::Logger> const& logger,
246+ std::shared_ptr<time::Clock> const& clock) :
247+ logger(logger),
248+ clock(clock),
249+ last_report(clock->now())
250 {
251 }
252
253@@ -141,3 +146,23 @@
254 " [" + i.name + "] : " + std::to_string(value), component());
255 }
256 }
257+
258+void mrl::DisplayReport::report_vsync(unsigned int display_id)
259+{
260+ using namespace std::chrono;
261+ seconds const static report_interval{1};
262+ std::unique_lock<decltype(vsync_event_mutex)> lk(vsync_event_mutex);
263+ auto now = clock->now();
264+ event_map[display_id]++;
265+ if (now > last_report + report_interval)
266+ {
267+ for(auto const& event : event_map)
268+ logger->log(ml::Severity::informational,
269+ std::to_string(event.second) + " vsync events on [" +
270+ std::to_string(event.first) + "] over " +
271+ std::to_string(duration_cast<milliseconds>(now - last_report).count()) + "ms",
272+ component());
273+ event_map.clear();
274+ last_report = now;
275+ }
276+}
277
278=== modified file 'src/server/report/logging/display_report.h'
279--- src/server/report/logging/display_report.h 2015-01-21 07:34:50 +0000
280+++ src/server/report/logging/display_report.h 2015-03-04 14:36:55 +0000
281@@ -21,8 +21,11 @@
282 #define MIR_REPORT_LOGGING_DISPLAY_REPORTER_H_
283
284 #include "mir/graphics/display_report.h"
285+#include "mir/time/clock.h"
286
287+#include <unordered_map>
288 #include <memory>
289+#include <mutex>
290
291 namespace mir
292 {
293@@ -41,25 +44,33 @@
294
295 static const char* component();
296
297- DisplayReport(const std::shared_ptr<mir::logging::Logger>& logger);
298+ DisplayReport(
299+ std::shared_ptr<mir::logging::Logger> const& logger,
300+ std::shared_ptr<time::Clock> const& clock);
301+
302 virtual ~DisplayReport();
303
304- virtual void report_successful_setup_of_native_resources();
305- virtual void report_successful_egl_make_current_on_construction();
306- virtual void report_successful_egl_buffer_swap_on_construction();
307- virtual void report_successful_drm_mode_set_crtc_on_construction();
308- virtual void report_successful_display_construction();
309- virtual void report_drm_master_failure(int error);
310- virtual void report_vt_switch_away_failure();
311- virtual void report_vt_switch_back_failure();
312- virtual void report_egl_configuration(EGLDisplay disp, EGLConfig cfg);
313+ virtual void report_successful_setup_of_native_resources() override;
314+ virtual void report_successful_egl_make_current_on_construction() override;
315+ virtual void report_successful_egl_buffer_swap_on_construction() override;
316+ virtual void report_successful_drm_mode_set_crtc_on_construction() override;
317+ virtual void report_successful_display_construction() override;
318+ virtual void report_vsync(unsigned int display_id) override;
319+ virtual void report_drm_master_failure(int error) override;
320+ virtual void report_vt_switch_away_failure() override;
321+ virtual void report_vt_switch_back_failure() override;
322+ virtual void report_egl_configuration(EGLDisplay disp, EGLConfig cfg) override;
323
324 protected:
325- DisplayReport(const DisplayReport&) = delete;
326- DisplayReport& operator=(const DisplayReport&) = delete;
327+ DisplayReport(DisplayReport const&) = delete;
328+ DisplayReport& operator=(DisplayReport const&) = delete;
329
330 private:
331- std::shared_ptr<mir::logging::Logger> logger;
332+ std::shared_ptr<mir::logging::Logger> const logger;
333+ std::shared_ptr<time::Clock> const clock;
334+ std::mutex vsync_event_mutex;
335+ mir::time::Timestamp last_report;
336+ std::unordered_map<unsigned int, unsigned int> event_map;
337 };
338 }
339 }
340
341=== modified file 'src/server/report/logging/logging_report_factory.cpp'
342--- src/server/report/logging/logging_report_factory.cpp 2015-02-13 06:12:34 +0000
343+++ src/server/report/logging/logging_report_factory.cpp 2015-03-04 14:36:55 +0000
344@@ -45,7 +45,7 @@
345
346 std::shared_ptr<mir::graphics::DisplayReport> mr::LoggingReportFactory::create_display_report()
347 {
348- return std::make_shared<logging::DisplayReport>(logger);
349+ return std::make_shared<logging::DisplayReport>(logger, clock);
350 }
351
352 std::shared_ptr<mir::scene::SceneReport> mr::LoggingReportFactory::create_scene_report()
353
354=== modified file 'src/server/report/lttng/display_report.cpp'
355--- src/server/report/lttng/display_report.cpp 2014-02-09 16:18:16 +0000
356+++ src/server/report/lttng/display_report.cpp 2015-03-04 14:36:55 +0000
357@@ -35,7 +35,6 @@
358 DISPLAY_REPORT_TRACE_CALL(report_successful_drm_mode_set_crtc_on_construction)
359 DISPLAY_REPORT_TRACE_CALL(report_vt_switch_away_failure)
360 DISPLAY_REPORT_TRACE_CALL(report_vt_switch_back_failure)
361-DISPLAY_REPORT_TRACE_CALL(report_gpu_composition_in_use)
362
363 #undef DISPLAY_REPORT_TRACE_CALL
364
365@@ -43,15 +42,12 @@
366 {
367 }
368
369-
370 void mir::report::lttng::DisplayReport::report_drm_master_failure(int error)
371 {
372 mir_tracepoint(mir_server_display, report_drm_master_failure, strerror(error));
373 }
374
375-
376-void mir::report::lttng::DisplayReport::report_hwc_composition_in_use(int major, int minor)
377+void mir::report::lttng::DisplayReport::report_vsync(unsigned int display_id)
378 {
379- mir_tracepoint(mir_server_display, report_hwc_composition_in_use, major, minor);
380+ mir_tracepoint(mir_server_display, report_vsync, display_id);
381 }
382-
383
384=== modified file 'src/server/report/lttng/display_report.h'
385--- src/server/report/lttng/display_report.h 2014-02-17 22:35:23 +0000
386+++ src/server/report/lttng/display_report.h 2015-03-04 14:36:55 +0000
387@@ -36,17 +36,16 @@
388 DisplayReport() = default;
389 virtual ~DisplayReport() noexcept(true) = default;
390
391- virtual void report_successful_setup_of_native_resources();
392- virtual void report_successful_egl_make_current_on_construction();
393- virtual void report_successful_egl_buffer_swap_on_construction();
394- virtual void report_successful_display_construction();
395- virtual void report_egl_configuration(EGLDisplay disp, EGLConfig cfg);
396- virtual void report_successful_drm_mode_set_crtc_on_construction();
397- virtual void report_drm_master_failure(int error);
398- virtual void report_vt_switch_away_failure();
399- virtual void report_vt_switch_back_failure();
400- virtual void report_hwc_composition_in_use(int major, int minor);
401- virtual void report_gpu_composition_in_use();
402+ virtual void report_successful_setup_of_native_resources() override;
403+ virtual void report_successful_egl_make_current_on_construction() override;
404+ virtual void report_successful_egl_buffer_swap_on_construction() override;
405+ virtual void report_successful_display_construction() override;
406+ virtual void report_egl_configuration(EGLDisplay disp, EGLConfig cfg) override;
407+ virtual void report_successful_drm_mode_set_crtc_on_construction() override;
408+ virtual void report_drm_master_failure(int error) override;
409+ virtual void report_vt_switch_away_failure() override;
410+ virtual void report_vt_switch_back_failure() override;
411+ virtual void report_vsync(unsigned int display_id) override;
412
413 private:
414 ServerTracepointProvider tp_provider;
415
416=== modified file 'src/server/report/lttng/display_report_tp.h'
417--- src/server/report/lttng/display_report_tp.h 2015-01-21 07:34:50 +0000
418+++ src/server/report/lttng/display_report_tp.h 2015-03-04 14:36:55 +0000
419@@ -62,6 +62,15 @@
420 )
421 )
422
423+TRACEPOINT_EVENT(
424+ mir_server_display,
425+ report_vsync,
426+ TP_ARGS(int, id),
427+ TP_FIELDS(
428+ ctf_integer(int, id, id)
429+ )
430+)
431+
432 #endif /* MIR_LTTNG_DISPLAY_REPORT_TP_H_ */
433
434 #include <lttng/tracepoint-event.h>
435
436=== modified file 'src/server/report/null/display_report.cpp'
437--- src/server/report/null/display_report.cpp 2015-01-21 07:34:50 +0000
438+++ src/server/report/null/display_report.cpp 2015-03-04 14:36:55 +0000
439@@ -29,3 +29,4 @@
440 void mrn::DisplayReport::report_vt_switch_away_failure() {}
441 void mrn::DisplayReport::report_vt_switch_back_failure() {}
442 void mrn::DisplayReport::report_egl_configuration(EGLDisplay, EGLConfig) {}
443+void mrn::DisplayReport::report_vsync(unsigned int) {}
444
445=== modified file 'src/server/report/null/display_report.h'
446--- src/server/report/null/display_report.h 2015-01-21 07:34:50 +0000
447+++ src/server/report/null/display_report.h 2015-03-04 14:36:55 +0000
448@@ -43,6 +43,7 @@
449 void report_vt_switch_away_failure() override;
450 void report_vt_switch_back_failure() override;
451 void report_egl_configuration(EGLDisplay disp, EGLConfig cfg) override;
452+ void report_vsync(unsigned int display_id) override;
453 };
454 }
455 }
456
457=== modified file 'tests/include/mir_test_doubles/mock_display_report.h'
458--- tests/include/mir_test_doubles/mock_display_report.h 2013-05-10 18:16:51 +0000
459+++ tests/include/mir_test_doubles/mock_display_report.h 2015-03-04 14:36:55 +0000
460@@ -41,9 +41,8 @@
461 MOCK_METHOD1(report_drm_master_failure, void(int));
462 MOCK_METHOD0(report_vt_switch_away_failure, void());
463 MOCK_METHOD0(report_vt_switch_back_failure, void());
464- MOCK_METHOD2(report_hwc_composition_in_use, void(int,int));
465- MOCK_METHOD0(report_gpu_composition_in_use, void());
466 MOCK_METHOD2(report_egl_configuration, void(EGLDisplay,EGLConfig));
467+ MOCK_METHOD1(report_vsync, void(unsigned int));
468 };
469
470 }
471
472=== modified file 'tests/include/mir_test_doubles/stub_display_builder.h'
473--- tests/include/mir_test_doubles/stub_display_builder.h 2015-02-26 03:20:09 +0000
474+++ tests/include/mir_test_doubles/stub_display_builder.h 2015-03-04 14:36:55 +0000
475@@ -47,7 +47,7 @@
476 MockHwcConfiguration()
477 {
478 using namespace testing;
479- ON_CALL(*this, subscribe_to_config_changes(_)).WillByDefault(Return(nullptr));
480+ ON_CALL(*this, subscribe_to_config_changes(_,_)).WillByDefault(Return(nullptr));
481 ON_CALL(*this, active_attribs_for(graphics::android::DisplayName::primary))
482 .WillByDefault(testing::Return(graphics::android::DisplayAttribs{
483 {0,0},{0,0}, 0.0, true, mir_pixel_format_abgr_8888, 2}));
484@@ -57,8 +57,9 @@
485 }
486 MOCK_METHOD2(power_mode, void(graphics::android::DisplayName, MirPowerMode));
487 MOCK_METHOD1(active_attribs_for, graphics::android::DisplayAttribs(graphics::android::DisplayName));
488- MOCK_METHOD1(subscribe_to_config_changes,
489- graphics::android::ConfigChangeSubscription(std::function<void()> const&));
490+ MOCK_METHOD2(subscribe_to_config_changes,
491+ graphics::android::ConfigChangeSubscription(
492+ std::function<void()> const&, std::function<void(graphics::android::DisplayName)> const&));
493 };
494
495 struct StubHwcConfiguration : public graphics::android::HwcConfiguration
496@@ -77,7 +78,7 @@
497
498
499 graphics::android::ConfigChangeSubscription subscribe_to_config_changes(
500- std::function<void()> const&) override
501+ std::function<void()> const&, std::function<void(graphics::android::DisplayName)> const&) override
502 {
503 return nullptr;
504 }
505
506=== modified file 'tests/unit-tests/graphics/android/test_display.cpp'
507--- tests/unit-tests/graphics/android/test_display.cpp 2015-03-03 06:56:37 +0000
508+++ tests/unit-tests/graphics/android/test_display.cpp 2015-03-04 14:36:55 +0000
509@@ -554,7 +554,7 @@
510 auto use_count_before = subscription.use_count();
511 stub_db_factory->with_next_config([&](mtd::MockHwcConfiguration& mock_config)
512 {
513- EXPECT_CALL(mock_config, subscribe_to_config_changes(_))
514+ EXPECT_CALL(mock_config, subscribe_to_config_changes(_,_))
515 .WillOnce(Return(subscription));
516 });
517 {
518@@ -596,7 +596,7 @@
519
520 stub_db_factory->with_next_config([&](mtd::MockHwcConfiguration& mock_config)
521 {
522- EXPECT_CALL(mock_config, subscribe_to_config_changes(_))
523+ EXPECT_CALL(mock_config, subscribe_to_config_changes(_,_))
524 .WillOnce(DoAll(SaveArg<0>(&hotplug_fn), Return(subscription)));
525 EXPECT_CALL(mock_config, active_attribs_for(mga::DisplayName::primary))
526 .Times(2)
527@@ -645,7 +645,7 @@
528 return mga::DisplayAttribs{
529 {20,20}, {4,4}, 50.0f, external_connected, mir_pixel_format_abgr_8888, 2};
530 }));
531- EXPECT_CALL(mock_config, subscribe_to_config_changes(_))
532+ EXPECT_CALL(mock_config, subscribe_to_config_changes(_,_))
533 .WillOnce(DoAll(SaveArg<0>(&hotplug_fn), Return(std::make_shared<char>('2'))));
534 });
535
536@@ -694,7 +694,7 @@
537 bool external_connected = true;
538 stub_db_factory->with_next_config([&](mtd::MockHwcConfiguration& mock_config)
539 {
540- EXPECT_CALL(mock_config, subscribe_to_config_changes(_))
541+ EXPECT_CALL(mock_config, subscribe_to_config_changes(_,_))
542 .WillOnce(DoAll(SaveArg<0>(&hotplug_fn), Return(std::make_shared<char>('2'))));
543 ON_CALL(mock_config, active_attribs_for(mga::DisplayName::primary))
544 .WillByDefault(Return(
545@@ -779,3 +779,25 @@
546 });
547 display.configure(*configuration);
548 }
549+
550+TEST_F(Display, reports_vsync)
551+{
552+ using namespace testing;
553+ std::function<void(mga::DisplayName)> vsync_fn = [](mga::DisplayName){};
554+ auto report = std::make_shared<NiceMock<mtd::MockDisplayReport>>();
555+ EXPECT_CALL(*report, report_vsync(_));
556+ stub_db_factory->with_next_config([&](mtd::MockHwcConfiguration& mock_config)
557+ {
558+ EXPECT_CALL(mock_config, subscribe_to_config_changes(_,_))
559+ .WillOnce(DoAll(SaveArg<1>(&vsync_fn), Return(std::make_shared<char>('2'))));
560+ });
561+
562+ mga::Display display(
563+ stub_db_factory,
564+ stub_gl_program_factory,
565+ stub_gl_config,
566+ report,
567+ mga::OverlayOptimization::enabled);
568+
569+ vsync_fn(mga::DisplayName::primary);
570+}
571
572=== modified file 'tests/unit-tests/graphics/android/test_display_hotplug.cpp'
573--- tests/unit-tests/graphics/android/test_display_hotplug.cpp 2015-02-13 06:12:34 +0000
574+++ tests/unit-tests/graphics/android/test_display_hotplug.cpp 2015-03-04 14:36:55 +0000
575@@ -47,7 +47,7 @@
576 return mga::DisplayAttribs{{0,0}, {0,0}, 0.0, true, mir_pixel_format_abgr_8888, 2};
577 }
578 mga::ConfigChangeSubscription subscribe_to_config_changes(
579- std::function<void()> const& cb) override
580+ std::function<void()> const& cb, std::function<void(mga::DisplayName)> const&) override
581 {
582 hotplug_fn = cb;
583 return {};
584@@ -72,9 +72,9 @@
585 return wrapped.active_attribs_for(d);
586 }
587 mga::ConfigChangeSubscription subscribe_to_config_changes(
588- std::function<void()> const& cb) override
589+ std::function<void()> const& hotplug, std::function<void(mga::DisplayName)> const& vsync) override
590 {
591- return wrapped.subscribe_to_config_changes(cb);
592+ return wrapped.subscribe_to_config_changes(hotplug, vsync);
593 }
594 mga::HwcConfiguration& wrapped;
595 };
596
597=== modified file 'tests/unit-tests/graphics/android/test_hwc_configuration.cpp'
598--- tests/unit-tests/graphics/android/test_hwc_configuration.cpp 2015-03-03 06:56:37 +0000
599+++ tests/unit-tests/graphics/android/test_hwc_configuration.cpp 2015-03-04 14:36:55 +0000
600@@ -228,17 +228,23 @@
601 EXPECT_THAT(attribs.vrefresh_hz, Eq(0.0f));
602 }
603
604-TEST_F(HwcConfiguration, subscribes_to_hotplug)
605+TEST_F(HwcConfiguration, subscribes_to_hotplug_and_vsync)
606 {
607 using namespace testing;
608 std::function<void(mga::DisplayName, bool)> hotplug_fn([](mga::DisplayName, bool){});
609+ std::function<void(mga::DisplayName, std::chrono::nanoseconds)> vsync_fn(
610+ [](mga::DisplayName, std::chrono::nanoseconds){});
611 EXPECT_CALL(*mock_hwc_wrapper, subscribe_to_events(_,_,_,_))
612- .WillOnce(SaveArg<2>(&hotplug_fn));
613+ .WillOnce(DoAll(SaveArg<1>(&vsync_fn), SaveArg<2>(&hotplug_fn)));
614 EXPECT_CALL(*mock_hwc_wrapper, unsubscribe_from_events_(_));
615
616- unsigned int call_count{0};
617- auto subscription = config.subscribe_to_config_changes([&]{ call_count++; });
618- hotplug_fn(mga::DisplayName::primary, true);
619- hotplug_fn(mga::DisplayName::primary, true);
620- EXPECT_THAT(call_count, Eq(2));
621+ unsigned int hotplug_call_count{0};
622+ unsigned int vsync_call_count{0};
623+ auto subscription = config.subscribe_to_config_changes(
624+ [&]{ hotplug_call_count++; }, [&](mga::DisplayName){ vsync_call_count++; });
625+ hotplug_fn(mga::DisplayName::primary, true);
626+ hotplug_fn(mga::DisplayName::primary, true);
627+ vsync_fn(mga::DisplayName::primary, std::chrono::nanoseconds(33));
628+ EXPECT_THAT(hotplug_call_count, Eq(2));
629+ EXPECT_THAT(vsync_call_count, Eq(1));
630 }
631
632=== modified file 'tests/unit-tests/graphics/mesa/test_display.cpp'
633--- tests/unit-tests/graphics/mesa/test_display.cpp 2015-02-26 03:20:09 +0000
634+++ tests/unit-tests/graphics/mesa/test_display.cpp 2015-03-04 14:36:55 +0000
635@@ -28,6 +28,7 @@
636
637 #include "mir_test_doubles/mock_egl.h"
638 #include "mir_test_doubles/mock_gl.h"
639+#include "mir_test_doubles/advanceable_clock.h"
640 #include "src/server/report/null_report_factory.h"
641 #include "mir_test_doubles/mock_display_report.h"
642 #include "mir_test_doubles/null_virtual_terminal.h"
643@@ -525,7 +526,7 @@
644 using namespace ::testing;
645
646 auto logger = std::make_shared<MockLogger>();
647- auto reporter = std::make_shared<mrl::DisplayReport>(logger);
648+ auto reporter = std::make_shared<mrl::DisplayReport>(logger, std::make_shared<mtd::AdvanceableClock>());
649
650 EXPECT_CALL(
651 *logger,
652@@ -541,7 +542,7 @@
653 using namespace ::testing;
654
655 auto logger = std::make_shared<MockLogger>();
656- auto reporter = std::make_shared<mrl::DisplayReport>(logger);
657+ auto reporter = std::make_shared<mrl::DisplayReport>(logger, std::make_shared<mtd::AdvanceableClock>());
658
659 EXPECT_CALL(
660 *logger,
661@@ -557,7 +558,7 @@
662 using namespace ::testing;
663
664 auto logger = std::make_shared<MockLogger>();
665- auto reporter = std::make_shared<mrl::DisplayReport>(logger);
666+ auto reporter = std::make_shared<mrl::DisplayReport>(logger, std::make_shared<mtd::AdvanceableClock>());
667
668 EXPECT_CALL(
669 *logger,
670@@ -573,7 +574,7 @@
671 using namespace ::testing;
672
673 auto logger = std::make_shared<MockLogger>();
674- auto reporter = std::make_shared<mrl::DisplayReport>(logger);
675+ auto reporter = std::make_shared<mrl::DisplayReport>(logger, std::make_shared<mtd::AdvanceableClock>());
676
677 EXPECT_CALL(
678 *logger,
679
680=== modified file 'tests/unit-tests/graphics/mesa/test_kms_page_flipper.cpp'
681--- tests/unit-tests/graphics/mesa/test_kms_page_flipper.cpp 2015-01-22 09:00:14 +0000
682+++ tests/unit-tests/graphics/mesa/test_kms_page_flipper.cpp 2015-03-04 14:36:55 +0000
683@@ -45,10 +45,11 @@
684 {
685 public:
686 KMSPageFlipperTest()
687- : page_flipper{mock_drm.fake_drm.fd()}
688+ : page_flipper{mock_drm.fake_drm.fd(), mt::fake_shared(report)}
689 {
690 }
691
692+ testing::NiceMock<mtd::MockDisplayReport> report;
693 testing::NiceMock<mtd::MockDRM> mock_drm;
694 mgm::KMSPageFlipper page_flipper;
695 };
696@@ -121,6 +122,24 @@
697 page_flipper.wait_for_flip(crtc_id);
698 }
699
700+TEST_F(KMSPageFlipperTest, wait_for_flip_reports_vsync)
701+{
702+ using namespace testing;
703+ uint32_t const crtc_id{10};
704+ uint32_t const fb_id{101};
705+ void* user_data{nullptr};
706+ ON_CALL(mock_drm, drmModePageFlip(_, _, _, _, _))
707+ .WillByDefault(DoAll(SaveArg<4>(&user_data), Return(0)));
708+ ON_CALL(mock_drm, drmHandleEvent(_, _))
709+ .WillByDefault(DoAll(InvokePageFlipHandler(&user_data), Return(0)));
710+
711+ EXPECT_CALL(report, report_vsync(crtc_id));
712+
713+ page_flipper.schedule_flip(crtc_id, fb_id);
714+ EXPECT_EQ(1, write(mock_drm.fake_drm.write_fd(), "a", 1));
715+ page_flipper.wait_for_flip(crtc_id);
716+}
717+
718 TEST_F(KMSPageFlipperTest, wait_for_non_scheduled_page_flip_doesnt_block)
719 {
720 using namespace testing;
721
722=== modified file 'tests/unit-tests/logging/test_display_report.cpp'
723--- tests/unit-tests/logging/test_display_report.cpp 2015-01-21 07:34:50 +0000
724+++ tests/unit-tests/logging/test_display_report.cpp 2015-03-04 14:36:55 +0000
725@@ -19,6 +19,7 @@
726 #include "src/server/report/logging/display_report.h"
727 #include "mir/logging/logger.h"
728 #include "mir_test_doubles/mock_egl.h"
729+#include "mir_test_doubles/advanceable_clock.h"
730
731 #include <gtest/gtest.h>
732 #include <gmock/gmock.h>
733@@ -39,16 +40,8 @@
734
735 struct DisplayReport : public testing::Test
736 {
737- DisplayReport()
738- {
739- }
740-
741- void SetUp()
742- {
743- logger = std::make_shared<MockLogger>();
744- }
745-
746- std::shared_ptr<MockLogger> logger;
747+ std::shared_ptr<mtd::AdvanceableClock> const clock{std::make_shared<mtd::AdvanceableClock>()};
748+ std::shared_ptr<MockLogger> logger{std::make_shared<MockLogger>()};
749 mtd::MockEGL mock_egl;
750 };
751
752@@ -123,6 +116,29 @@
753 component));
754 }
755
756- mrl::DisplayReport report(logger);
757+ mrl::DisplayReport report(logger, clock);
758 report.report_egl_configuration(disp, config);
759 }
760+
761+TEST_F(DisplayReport, reports_vsync)
762+{
763+ std::chrono::milliseconds interval(1500);
764+ unsigned int display1_id {1223};
765+ unsigned int display2_id {4492};
766+ std::string display1_name(std::to_string(display1_id));
767+ std::string display2_name(std::to_string(display2_id));
768+ EXPECT_CALL(*logger, log(
769+ ml::Severity::informational,
770+ "2 vsync events on [" + display1_name + "] over " + std::to_string(interval.count()) + "ms",
771+ component));
772+ EXPECT_CALL(*logger, log(
773+ ml::Severity::informational,
774+ "1 vsync events on [" + display2_name + "] over " + std::to_string(interval.count()) + "ms",
775+ component));
776+ mrl::DisplayReport report(logger, clock);
777+
778+ report.report_vsync(display1_id);
779+ report.report_vsync(display2_id);
780+ clock->advance_by(interval);
781+ report.report_vsync(display1_id);
782+}

Subscribers

People subscribed via source and target branches