Mir

Merge lp:~mir-team/mir/vsync-timings-from-server into lp:mir

Proposed by Robert Carr
Status: Work in progress
Proposed branch: lp:~mir-team/mir/vsync-timings-from-server
Merge into: lp:mir
Diff against target: 2744 lines (+983/-227)
77 files modified
benchmarks/frame-uniformity/vsync_simulating_graphics_platform.cpp (+36/-4)
client-ABI-sha1sums (+1/-1)
common-ABI-sha1sums (+1/-1)
include/client/mir_toolkit/mir_surface.h (+7/-0)
include/common/mir/input/input_receiver_thread.h (+4/-0)
include/platform/mir/graphics/display.h (+10/-0)
include/server/mir/default_server_configuration.h (+3/-0)
platform-ABI-sha1sums (+2/-2)
server-ABI-sha1sums (+3/-3)
src/client/mir_surface.cpp (+18/-1)
src/client/mir_surface.h (+5/-1)
src/client/mir_surface_api.cpp (+5/-0)
src/common/input/android/android_input_receiver.cpp (+45/-56)
src/common/input/android/android_input_receiver.h (+7/-0)
src/common/input/android/android_input_receiver_thread.cpp (+5/-0)
src/common/input/android/android_input_receiver_thread.h (+2/-0)
src/include/platform/mir/frontend/vsync_provider.h (+46/-0)
src/platform/graphics/android/display.cpp (+7/-0)
src/platform/graphics/android/display.h (+2/-0)
src/platform/graphics/android/display_builder.h (+3/-0)
src/platform/graphics/android/display_resource_factory.h (+3/-0)
src/platform/graphics/android/hwc_common_device.cpp (+4/-4)
src/platform/graphics/android/hwc_common_device.h (+2/-1)
src/platform/graphics/android/hwc_vsync.cpp (+25/-3)
src/platform/graphics/android/hwc_vsync.h (+10/-1)
src/platform/graphics/android/hwc_vsync_coordinator.h (+7/-2)
src/platform/graphics/android/output_builder.cpp (+6/-0)
src/platform/graphics/android/output_builder.h (+2/-0)
src/platform/graphics/android/platform.cpp (+4/-1)
src/platform/graphics/android/platform.h (+3/-0)
src/platform/graphics/android/resource_factory.cpp (+12/-4)
src/platform/graphics/android/resource_factory.h (+7/-0)
src/platform/graphics/mesa/display.cpp (+18/-1)
src/platform/graphics/mesa/display.h (+2/-0)
src/protobuf/mir_protobuf.proto (+2/-0)
src/server/frontend/default_configuration.cpp (+21/-9)
src/server/frontend/default_ipc_factory.cpp (+6/-2)
src/server/frontend/default_ipc_factory.h (+5/-1)
src/server/frontend/session_mediator.cpp (+8/-0)
src/server/frontend/session_mediator.h (+3/-0)
src/server/graphics/nested/CMakeLists.txt (+1/-0)
src/server/graphics/nested/host_connection.h (+3/-0)
src/server/graphics/nested/mir_client_host_connection.cpp (+5/-0)
src/server/graphics/nested/nested_display.cpp (+9/-1)
src/server/graphics/nested/nested_display.h (+4/-0)
src/server/graphics/nested/nested_output.cpp (+9/-2)
src/server/graphics/nested/nested_output.h (+9/-1)
src/server/graphics/nested/nested_platform.cpp (+2/-0)
src/server/graphics/nested/nested_vsync_provider.cpp (+45/-0)
src/server/graphics/nested/nested_vsync_provider.h (+49/-0)
src/server/graphics/offscreen/display.cpp (+16/-0)
src/server/graphics/offscreen/display.h (+2/-0)
src/server/symbols.map (+2/-0)
tests/acceptance-tests/test_client_library.cpp (+18/-13)
tests/include/mir_test_doubles/mock_display.h (+1/-0)
tests/include/mir_test_doubles/mock_hwc_vsync_coordinator.h (+3/-1)
tests/include/mir_test_doubles/null_display.h (+5/-0)
tests/include/mir_test_doubles/stub_display.h (+6/-0)
tests/include/mir_test_doubles/stub_display_builder.h (+5/-0)
tests/include/mir_test_doubles/stub_host_connection.h (+1/-0)
tests/include/mir_test_doubles/stub_vsync_provider.h (+43/-0)
tests/include/mir_test_framework/using_stub_client_platform.h (+2/-0)
tests/integration-tests/CMakeLists.txt (+1/-0)
tests/integration-tests/graphics/android/test_display_integration.cpp (+1/-0)
tests/integration-tests/test_surfaceloop.cpp (+7/-0)
tests/integration-tests/test_vsync_to_client.cpp (+225/-0)
tests/mir_test_framework/stubbed_graphics_platform.cpp (+2/-0)
tests/unit-tests/client/input/test_android_input_receiver.cpp (+0/-96)
tests/unit-tests/client/test_client_mir_surface.cpp (+1/-0)
tests/unit-tests/frontend/test_session_mediator.cpp (+48/-5)
tests/unit-tests/graphics/android/CMakeLists.txt (+1/-0)
tests/unit-tests/graphics/android/test_hwc_common_device.cpp (+5/-3)
tests/unit-tests/graphics/android/test_hwc_vsync.cpp (+68/-0)
tests/unit-tests/graphics/android/test_output_builder.cpp (+2/-0)
tests/unit-tests/graphics/android/test_resource_factory.cpp (+6/-3)
tests/unit-tests/graphics/nested/test_nested_display.cpp (+1/-0)
tests/unit-tests/graphics/nested/test_nested_display_buffer.cpp (+13/-4)
To merge this branch: bzr merge lp:~mir-team/mir/vsync-timings-from-server
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Needs Fixing
Alberto Aguirre (community) Abstain
Kevin DuBois (community) Needs Fixing
Alan Griffiths Abstain
Daniel van Vugt Needs Fixing
Review via email: mp+240789@code.launchpad.net

Commit message

Send vsync times from server and use in input resampling

Description of the change

Implement vsync timed input resampling as discussed in DC. Lots of noise in the test framework generated by the discovery that UsingStubClientAPI was not working (discovered by the vsync->input thread integration test).

Please test on device and tell me what you think.

To post a comment you must log in.
2024. By Robert Carr

Cleanup

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

The score is consistently better on the frame uniformity test but still not as good as you would want...if you look at distance per sample you see it go down to near zero pixels, but then slowly creep back up 1 pixel at a time. Still its both more responsive and uniform than the existing code or the code before the "synthetic vsync interval" sort of approach.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:2023
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~mir-team/mir/vsync-timings-from-server/+merge/240789/+edit-commit-message

http://jenkins.qa.ubuntu.com/job/mir-ci/2012/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-android-vivid-i386-build/1
    FAILURE: http://jenkins.qa.ubuntu.com/job/mir-clang-vivid-amd64-build/1/console
    FAILURE: http://jenkins.qa.ubuntu.com/job/mir-vivid-amd64-ci/1/console

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Robert Carr (robertcarr) wrote :

When testing you may notice that shell elements, i.e. indicator bar seem more responsive than client elements...ultimately I think this is due to nesting.

I believe

https://code.launchpad.net/~mir-team/qtubuntu/dont-use-raw-pc/+merge/240796

presents some improvement though

2025. By Robert Carr

Update ABI sha1sums

2026. By Robert Carr

Fix lgpl license on vsync provideR

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
Daniel van Vugt (vanvugt) wrote :

Slightly scary diff size right now, but could prove worthwhile. Initial thoughts:

(1) Avoid naming anything "*Provider". If a more concrete noun can't be found for such classes then that's an indication the design needs improving.

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

Perhaps just a rename "VsyncSource". *shrug*

2027. By Robert Carr

Merge lp:mir

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

(2) Some very important regression tests have been deleted. I suspect it's possible to retain (convert?) them, so we should:
tests/unit-tests/client/input/test_android_input_receiver.cpp:
2488 -TEST_F(AndroidInputReceiverSetup, slow_raw_input_doesnt_cause_frameskipping)
2536 -TEST_F(AndroidInputReceiverSetup, rendering_does_not_lag_behind_input)

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

(3) Spurious line appears in a few files:
+e1be9faee8b844ca2ce617f8fd82c9ee08d56bed include/common/mir/graphics/#native_buffer.h#

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
2028. By Robert Carr

Fix swap files in sha1sums

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
2029. By Robert Carr

Remove backup file from sha1sums

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

Now tested manually (Nexus4 nested and non-nested), but needs work...

(1) VsyncProvider: name could be better. VsyncSource? But see also (4)

(2) Some very important regression tests have been deleted. I suspect it's possible to retain (convert?) them, so we should:
tests/unit-tests/client/input/test_android_input_receiver.cpp:
2488 -TEST_F(AndroidInputReceiverSetup, slow_raw_input_doesnt_cause_frameskipping)
2536 -TEST_F(AndroidInputReceiverSetup, rendering_does_not_lag_behind_input)

(3) Nested input (fingerpaint -w) is visibly more laggy with this branch. That probably would have been shown by the test cases (2) had they not been deleted.

(4) Input event spacing is significantly less smooth and irregular (both nested and non-nested) with this branch. Same kind of irregularity pictured in bug 1373692. Also the same kind of irregularity I encountered when I experimented with a virtual vsync timer (when the client receives the buffer). So there's presently no visible advantage to getting timings from the server over what you can calculate within the client.

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

(5) This looks like a bug and will cause resampling/prediction to be disabled:
480 + has_new_frame_time = false;

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

Actually (4) could easily be explained by (5) :) There always is a last frame time; it should be perfectly regular and always known (be it real or artificial). And fixing (5) might fix the lag too (3).

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
2030. By Robert Carr

Merge lp:mir

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
2031. By Robert Carr

Forjenkins

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
2032. By Robert Carr

Jenkins

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

CI failures logged as lp:1391488 (new) and lp:1391261 (confirmed)

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

71 + last_sync = std::chrono::high_resolution_clock::now();
72 + vsync_provider.notify_of_vsync(last_sync.time_since_epoch());

I note the use of real time within the tests - which is always a recipe for intermittent failures. I'd prefer to see a stubbed time source.

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

First pass:

Could VsyncProvider be in mir::graphics instead of mir::frontend?

new whitespace
324 +

int64_t mir_surface_get_last_display_time(MirSurface *surface)
The naming has some interesting implications... like could the client api user rely on this to roughly see how long the screen has been off? Also, I'd think that the vsync stuff would be in mir_connection with the rest of the display stuff.

599 + virtual std::chrono::nanoseconds last_vsync_for(graphics::DisplayConfigurationOutputId output) = 0;
and
204 + virtual std::shared_ptr<frontend::VsyncProvider> the_vsync_provider();
and
184 + virtual std::shared_ptr<frontend::VsyncProvider> vsync_provider() = 0;

Seems like a lot of rigging where we could just have
mg::Display::last_vsync_for(graphics::DisplayConfigurationOutputId output) = 0;
and the server code could just use the existing the_display() function.

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

int64_t mir_surface_get_last_display_time(MirSurface *surface)
Somewhat related to my previous comment on this function, but is this exposing too much to the user? Is there some client-side processing that could be done in libmirclient without exposing the timing details?

The driving test looks like:
 2184 +TEST_F(VsyncProviderTest, last_display_time)
but could the test make use of mir client internals to check the vsync timing? (or, an uglier compromise could be for this to be in the debug library)

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

1098 + optional int64 vsync_time = 9;

Related to my comment about whether vsync info lives in the mir_surface_ vs mir_connection_ functions, it also seems to me that vsync is an event that can we can asynchronously notify clients of, as opposed to having this be synchronous with the exchange_buffer rpc call. This would also let us untie the buffer swapping from the vsync notification. (in case input processing is needed without the client wanting to swap a buffer)

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

Vsync is more system-wide, certainly not per-connection. On the other hand you do need to avoid waking up all clients 60 times per second so querying per surface is a good compromise.

An even better solution is not having to get info from the server at all. So far there's no visible benefit in doing so, but if this branch gets fixed up and starts performing as well as trunk (or better!) then it could be justified.

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

> Vsync is more system-wide, certainly not per-connection. On the other hand you
> do need to avoid waking up all clients 60 times per second so querying per
> surface is a good compromise.

Sure, from a clients perspective though, the connection is the system wide graphics configuration. Its a good point that this would wake up the clients every time, perhaps that could be mitigated by the clients registering and deregistering a callback if they are interested.

If we tie the vsync to the buffers, we tie input processing tightly to the clients decision to submit new frames. (and the clients might submit dummy buffers they don't care about, just to get the vsync info)

> An even better solution is not having to get info from the server at all. So
> far there's no visible benefit in doing so, but if this branch gets fixed up
> and starts performing as well as trunk (or better!) then it could be
> justified.

Yes, this could be appropriate, but its tricky from the android platform at least (which only provides the vsync information from the hwc interface). Perhaps batching input at the same rate as one of the displays could be a way around.

Revision history for this message
Alberto Aguirre (albaguirre) wrote :

Text conflict in src/client/mir_surface_api.cpp

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

Remember "batching" happens on the client side, which is surprising at first but actually very desirable. It means we have the option in future of letting clients turn off resampling if they're competent to deal with the raw events.

Revision history for this message
Alberto Aguirre (albaguirre) wrote :

These are some videos I took.

I don't notice any significant difference

Vivid #19 in mako:
https://drive.google.com/file/d/0B0EbX_l-W2rBOTZMSS0xamhWNXM/view?usp=sharing

Vivid #19 in mako + this branch:
https://drive.google.com/file/d/0B0EbX_l-W2rBMHhnajVqX3FJT0E/view?usp=sharing

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

Alberto:
As racarr pointed out, native shell shell elements do perform OK still. However nested elements suffer significantly from this branch. To test nested elements you'll need to video something like a client (Ebay?), and not the shell itself.

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

Oh I can see the terminology I used is misleading and confusing.

What we're actually talking about is _clients_ of nested servers having lag problems. And on the phone, that's most of what people are touching.

Revision history for this message
Alberto Aguirre (albaguirre) wrote :

@Daniel,

I used that more as an illustration that I don't see any visual benefits from this branch so far.

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

Doesn't seem unreasonable. I'm with Kevin though - is there a particular reason why get_last_vsync_for isn't a part of the Display interface?

It's a bit annoying that it needs to be exposed through the client API though. There are lots and lots of different interesting time values (see, for example, https://www.opengl.org/registry/specs/OML/glx_sync_control.txt) that we'll probably want to expose at some point - EGL/GL Next look like they'll want access to those things in the nearish future. I guess we can expose them (and possibly deprecate this API) when we come to that.

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

Sad that no one else experiences the performance the way I do. I experience it basically the same except during fast scrolls where I believe it is significantly more accurate in finger tracking. This is agreed with by frame uniformity test results.

Still I will continue working to produce a more convincing metric.

It is frustrating that mir_surface_get_last_display_time has to be exposed for nested. I agree it has some weird semantics if you think of it as vsync time, hence why I chose this name.

As chris references some clients are interested in this, Chromium uses VSync times + prediction to do...something! not sure beyond that.

>> sn't seem unreasonable. I'm with Kevin though - is there a particular reason why
>> get_last_vsync_for isn't a part of the Display interface?

I think putting it on the "Display" interface just further confuses the "Display"/"Output" terminology further...if Display why not DisplayBuffer?

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

Will switch to work in progress in a day or two if I dont make any progress.

Has anyone besides alberto and daniel tested?

Daniel: I wonder if in testing the nested clients you used the recommended qtubuntu branch? https://code.launchpad.net/~mir-team/qtubuntu/dont-use-raw-pc

Alberto: Maybe you could try some videos with some fast scrolls if its not too hard to setup?

2033. By Robert Carr

Merge lp:mir

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
2034. By Robert Carr

Update sha1sums

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

Also note -- if QtMir switches to using the newish Qt code (if not already?) which apparently does input resampling then we could theoretically just throw away all the resampling logic in Mir itself for now :)

I could be persuaded that fingerpaint being very laggy is a non-issue, but only if it's proven that QtMir is now using the in-toolkit input resampling feature. But if that's true then we're better off just deleting the resampling logic from Mir instead of growing it here.

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

I believe Qt is just doing a subset that we would call event compression. Will confirm.

2035. By Robert Carr

Merge lp:mir

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

Unmerged revisions

2035. By Robert Carr

Merge lp:mir

2034. By Robert Carr

Update sha1sums

2033. By Robert Carr

Merge lp:mir

2032. By Robert Carr

Jenkins

2031. By Robert Carr

Forjenkins

2030. By Robert Carr

Merge lp:mir

2029. By Robert Carr

Remove backup file from sha1sums

2028. By Robert Carr

Fix swap files in sha1sums

2027. By Robert Carr

Merge lp:mir

2026. By Robert Carr

Fix lgpl license on vsync provideR

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'benchmarks/frame-uniformity/vsync_simulating_graphics_platform.cpp'
--- benchmarks/frame-uniformity/vsync_simulating_graphics_platform.cpp 2014-11-13 16:41:26 +0000
+++ benchmarks/frame-uniformity/vsync_simulating_graphics_platform.cpp 2014-11-18 19:29:59 +0000
@@ -21,17 +21,23 @@
21#include "mir/graphics/buffer_writer.h"21#include "mir/graphics/buffer_writer.h"
22#include "mir/graphics/platform_ipc_operations.h"22#include "mir/graphics/platform_ipc_operations.h"
23#include "mir/graphics/platform_ipc_package.h"23#include "mir/graphics/platform_ipc_package.h"
24#include "mir/frontend/vsync_provider.h"
25
26#include "mir_test/fake_shared.h"
2427
25#include "mir_test_doubles/stub_buffer_allocator.h"28#include "mir_test_doubles/stub_buffer_allocator.h"
26#include "mir_test_doubles/stub_display.h"29#include "mir_test_doubles/stub_display.h"
2730
28#include <chrono>31#include <chrono>
29#include <functional>32#include <functional>
33#include <mutex>
3034
35namespace mf = mir::frontend;
31namespace mg = mir::graphics;36namespace mg = mir::graphics;
32namespace geom = mir::geometry;37namespace geom = mir::geometry;
3338
34namespace mtd = mir::test::doubles;39namespace mt = mir::test;
40namespace mtd = mt::doubles;
3541
36namespace42namespace
37{43{
@@ -43,7 +49,7 @@
43 }49 }
44};50};
4551
46class StubIpcOps : public mg::PlatformIpcOperations52struct StubIpcOps : public mg::PlatformIpcOperations
47{53{
48 void pack_buffer(54 void pack_buffer(
49 mg::BufferIpcMessage&,55 mg::BufferIpcMessage&,
@@ -68,6 +74,25 @@
68 }74 }
69};75};
7076
77struct StubVsyncProvider : public mf::VsyncProvider
78{
79 std::chrono::nanoseconds last_vsync_for(mg::DisplayConfigurationOutputId /* output */)
80 {
81 std::unique_lock<std::mutex> lg(last_vsync_guard);
82
83 return last_vsync;
84 }
85
86 void notify_of_vsync(std::chrono::nanoseconds vsync)
87 {
88 std::unique_lock<std::mutex> lg(last_vsync_guard);
89
90 last_vsync = vsync;
91 }
92 std::mutex last_vsync_guard;
93 std::chrono::nanoseconds last_vsync;
94};
95
71struct StubDisplayBuffer : mtd::StubDisplayBuffer96struct StubDisplayBuffer : mtd::StubDisplayBuffer
72{97{
73 StubDisplayBuffer(geom::Size output_size, int vsync_rate_in_hz)98 StubDisplayBuffer(geom::Size output_size, int vsync_rate_in_hz)
@@ -84,13 +109,15 @@
84 109
85 if (now < next_sync)110 if (now < next_sync)
86 std::this_thread::sleep_for(next_sync - now);111 std::this_thread::sleep_for(next_sync - now);
87 112
88 last_sync = now;113 last_sync = std::chrono::high_resolution_clock::now();
114 vsync_provider.notify_of_vsync(last_sync.time_since_epoch());
89 }115 }
90 116
91 double const vsync_rate_in_hz;117 double const vsync_rate_in_hz;
92118
93 std::chrono::high_resolution_clock::time_point last_sync;119 std::chrono::high_resolution_clock::time_point last_sync;
120 StubVsyncProvider vsync_provider;
94};121};
95122
96struct StubDisplay : public mtd::StubDisplay123struct StubDisplay : public mtd::StubDisplay
@@ -105,6 +132,11 @@
105 {132 {
106 exec(buffer);133 exec(buffer);
107 }134 }
135
136 std::shared_ptr<mf::VsyncProvider> vsync_provider() override
137 {
138 return mt::fake_shared(buffer.vsync_provider);
139 }
108140
109 StubDisplayBuffer buffer;141 StubDisplayBuffer buffer;
110};142};
111143
=== modified file 'client-ABI-sha1sums'
--- client-ABI-sha1sums 2014-11-12 05:01:53 +0000
+++ client-ABI-sha1sums 2014-11-18 19:29:59 +0000
@@ -5,7 +5,7 @@
51ef8f51a3e3f8d1559266c5af58fbfde7cfabf0a include/client/mir_toolkit/mir_cursor_configuration.h51ef8f51a3e3f8d1559266c5af58fbfde7cfabf0a include/client/mir_toolkit/mir_cursor_configuration.h
69d50df5a141ca03ee8a79f7e844ed4b8b3b7d5d3 include/client/mir_toolkit/mir_prompt_session.h69d50df5a141ca03ee8a79f7e844ed4b8b3b7d5d3 include/client/mir_toolkit/mir_prompt_session.h
721d07e655e85eeec8a3523e1c6f9c2252176ec01 include/client/mir_toolkit/mir_screencast.h721d07e655e85eeec8a3523e1c6f9c2252176ec01 include/client/mir_toolkit/mir_screencast.h
84f85e3d00314a7df869e56c3701a45310909fae2 include/client/mir_toolkit/mir_surface.h81bacb90ea11be9c8fec6113a68391027ce518707 include/client/mir_toolkit/mir_surface.h
9b141c4d79802ad626d969249c0004744e5c2a525 include/client/mir_toolkit/mir_wait.h9b141c4d79802ad626d969249c0004744e5c2a525 include/client/mir_toolkit/mir_wait.h
109907751d046e4aea81881cf19e5df52c7a6a813e include/common/mir_toolkit/client_types.h109907751d046e4aea81881cf19e5df52c7a6a813e include/common/mir_toolkit/client_types.h
112100c0674d9d882c1845550847357f6a5de5af66 include/common/mir_toolkit/common.h112100c0674d9d882c1845550847357f6a5de5af66 include/common/mir_toolkit/common.h
1212
=== modified file 'common-ABI-sha1sums'
--- common-ABI-sha1sums 2014-11-11 07:34:31 +0000
+++ common-ABI-sha1sums 2014-11-18 19:29:59 +0000
@@ -7,7 +7,7 @@
742646c2367b9821e3aa71feff6e31cf50526acaa include/common/mir/geometry/size.h742646c2367b9821e3aa71feff6e31cf50526acaa include/common/mir/geometry/size.h
8e1be9faee8b844ca2ce617f8fd82c9ee08d56bed include/common/mir/graphics/native_buffer.h8e1be9faee8b844ca2ce617f8fd82c9ee08d56bed include/common/mir/graphics/native_buffer.h
9dcf8b8982f138bdde39a241825c610e955cd5e33 include/common/mir/input/input_platform.h9dcf8b8982f138bdde39a241825c610e955cd5e33 include/common/mir/input/input_platform.h
10208cd6aed5ef5f8f39b3eb86604e4133cb840485 include/common/mir/input/input_receiver_thread.h10fc96edf0f28451af2009aff58b9da8c0d462a604 include/common/mir/input/input_receiver_thread.h
11be7d58c9fde2ce91cc66dd6144b76e08b536266b include/common/mir/int_wrapper.h11be7d58c9fde2ce91cc66dd6144b76e08b536266b include/common/mir/int_wrapper.h
129ae8473df05dd9e048a73797f01a2f34f7447554 include/common/mir/time/types.h129ae8473df05dd9e048a73797f01a2f34f7447554 include/common/mir/time/types.h
139907751d046e4aea81881cf19e5df52c7a6a813e include/common/mir_toolkit/client_types.h139907751d046e4aea81881cf19e5df52c7a6a813e include/common/mir_toolkit/client_types.h
1414
=== modified file 'include/client/mir_toolkit/mir_surface.h'
--- include/client/mir_toolkit/mir_surface.h 2014-11-12 05:01:53 +0000
+++ include/client/mir_toolkit/mir_surface.h 2014-11-18 19:29:59 +0000
@@ -289,6 +289,13 @@
289 */289 */
290MirOrientation mir_surface_get_orientation(MirSurface *surface);290MirOrientation mir_surface_get_orientation(MirSurface *surface);
291291
292/**
293 * Returns the last time a buffer from the surface was displayed on screen.
294 * If possible this time will be sampled on the server side from hardware
295 * vsync timings.
296 */
297int64_t mir_surface_get_last_display_time(MirSurface *surface);
298
292#ifdef __cplusplus299#ifdef __cplusplus
293}300}
294/**@}*/301/**@}*/
295302
=== modified file 'include/common/mir/input/input_receiver_thread.h'
--- include/common/mir/input/input_receiver_thread.h 2014-10-01 06:25:56 +0000
+++ include/common/mir/input/input_receiver_thread.h 2014-11-18 19:29:59 +0000
@@ -19,6 +19,8 @@
19#ifndef MIR_INPUT_RECEIVER_RECEIVER_THREAD_H_19#ifndef MIR_INPUT_RECEIVER_RECEIVER_THREAD_H_
20#define MIR_INPUT_RECEIVER_RECEIVER_THREAD_H_20#define MIR_INPUT_RECEIVER_RECEIVER_THREAD_H_
2121
22#include <chrono>
23
22namespace mir24namespace mir
23{25{
24namespace input26namespace input
@@ -34,6 +36,8 @@
34 virtual void start() = 0;36 virtual void start() = 0;
35 virtual void stop() = 0;37 virtual void stop() = 0;
36 virtual void join() = 0;38 virtual void join() = 0;
39
40 virtual void notify_of_frame_time(std::chrono::nanoseconds frame_time) = 0;
3741
38protected:42protected:
39 InputReceiverThread() = default;43 InputReceiverThread() = default;
4044
=== modified file 'include/platform/mir/graphics/display.h'
--- include/platform/mir/graphics/display.h 2014-10-01 06:25:56 +0000
+++ include/platform/mir/graphics/display.h 2014-11-18 19:29:59 +0000
@@ -24,6 +24,10 @@
2424
25namespace mir25namespace mir
26{26{
27namespace frontend
28{
29class VsyncProvider;
30}
2731
28namespace graphics32namespace graphics
29{33{
@@ -101,6 +105,12 @@
101 * Create a hardware cursor object.105 * Create a hardware cursor object.
102 */106 */
103 virtual std::shared_ptr<Cursor> create_hardware_cursor(std::shared_ptr<CursorImage> const& initial_image) = 0;107 virtual std::shared_ptr<Cursor> create_hardware_cursor(std::shared_ptr<CursorImage> const& initial_image) = 0;
108
109 /**
110 * Returns a vsync provider for the display which can provide per-output
111 * information about vsync timings.
112 */
113 virtual std::shared_ptr<frontend::VsyncProvider> vsync_provider() = 0;
104114
105 /**115 /**
106 * Creates a GLContext object that shares resources with the Display's GL context.116 * Creates a GLContext object that shares resources with the Display's GL context.
107117
=== modified file 'include/server/mir/default_server_configuration.h'
--- include/server/mir/default_server_configuration.h 2014-11-18 17:26:29 +0000
+++ include/server/mir/default_server_configuration.h 2014-11-18 19:29:59 +0000
@@ -66,6 +66,7 @@
66class EventSink;66class EventSink;
67class DisplayChanger;67class DisplayChanger;
68class Screencast;68class Screencast;
69class VsyncProvider;
69}70}
7071
71namespace shell72namespace shell
@@ -234,6 +235,7 @@
234 virtual std::shared_ptr<frontend::EventSink> the_global_event_sink();235 virtual std::shared_ptr<frontend::EventSink> the_global_event_sink();
235 virtual std::shared_ptr<frontend::DisplayChanger> the_frontend_display_changer();236 virtual std::shared_ptr<frontend::DisplayChanger> the_frontend_display_changer();
236 virtual std::shared_ptr<frontend::Screencast> the_screencast();237 virtual std::shared_ptr<frontend::Screencast> the_screencast();
238 virtual std::shared_ptr<frontend::VsyncProvider> the_vsync_provider();
237 /** @name frontend configuration - internal dependencies239 /** @name frontend configuration - internal dependencies
238 * internal dependencies of frontend240 * internal dependencies of frontend
239 * @{ */241 * @{ */
@@ -393,6 +395,7 @@
393 CachedPtr<frontend::ConnectionCreator> connection_creator;395 CachedPtr<frontend::ConnectionCreator> connection_creator;
394 CachedPtr<frontend::ConnectionCreator> prompt_connection_creator;396 CachedPtr<frontend::ConnectionCreator> prompt_connection_creator;
395 CachedPtr<frontend::Screencast> screencast;397 CachedPtr<frontend::Screencast> screencast;
398 CachedPtr<frontend::VsyncProvider> vsync_provider;
396 CachedPtr<compositor::RendererFactory> renderer_factory;399 CachedPtr<compositor::RendererFactory> renderer_factory;
397 CachedPtr<compositor::BufferStreamFactory> buffer_stream_factory;400 CachedPtr<compositor::BufferStreamFactory> buffer_stream_factory;
398 CachedPtr<compositor::FrameDroppingPolicyFactory> frame_dropping_policy_factory;401 CachedPtr<compositor::FrameDroppingPolicyFactory> frame_dropping_policy_factory;
399402
=== modified file 'platform-ABI-sha1sums'
--- platform-ABI-sha1sums 2014-11-18 03:21:20 +0000
+++ platform-ABI-sha1sums 2014-11-18 19:29:59 +0000
@@ -7,7 +7,7 @@
742646c2367b9821e3aa71feff6e31cf50526acaa include/common/mir/geometry/size.h742646c2367b9821e3aa71feff6e31cf50526acaa include/common/mir/geometry/size.h
8e1be9faee8b844ca2ce617f8fd82c9ee08d56bed include/common/mir/graphics/native_buffer.h8e1be9faee8b844ca2ce617f8fd82c9ee08d56bed include/common/mir/graphics/native_buffer.h
9dcf8b8982f138bdde39a241825c610e955cd5e33 include/common/mir/input/input_platform.h9dcf8b8982f138bdde39a241825c610e955cd5e33 include/common/mir/input/input_platform.h
10208cd6aed5ef5f8f39b3eb86604e4133cb840485 include/common/mir/input/input_receiver_thread.h10fc96edf0f28451af2009aff58b9da8c0d462a604 include/common/mir/input/input_receiver_thread.h
11be7d58c9fde2ce91cc66dd6144b76e08b536266b include/common/mir/int_wrapper.h11be7d58c9fde2ce91cc66dd6144b76e08b536266b include/common/mir/int_wrapper.h
129ae8473df05dd9e048a73797f01a2f34f7447554 include/common/mir/time/types.h129ae8473df05dd9e048a73797f01a2f34f7447554 include/common/mir/time/types.h
139907751d046e4aea81881cf19e5df52c7a6a813e include/common/mir_toolkit/client_types.h139907751d046e4aea81881cf19e5df52c7a6a813e include/common/mir_toolkit/client_types.h
@@ -28,7 +28,7 @@
28986f5d0d8ea2c6a42cc320f468e682f81fec46ae include/platform/mir/graphics/display_buffer.h28986f5d0d8ea2c6a42cc320f468e682f81fec46ae include/platform/mir/graphics/display_buffer.h
29f53a0020b8f1bd4a941a201eb26271cffee0a7dd include/platform/mir/graphics/display_configuration.h29f53a0020b8f1bd4a941a201eb26271cffee0a7dd include/platform/mir/graphics/display_configuration.h
306fe08da318c920b0d20ea8b8f560f5ac7ed389fe include/platform/mir/graphics/display_configuration_policy.h306fe08da318c920b0d20ea8b8f560f5ac7ed389fe include/platform/mir/graphics/display_configuration_policy.h
3141ea906d208b761e3d5d5056095de9de2d4ffa17 include/platform/mir/graphics/display.h310eb20a383320790016fa22ae969e80fdecd20b8f include/platform/mir/graphics/display.h
32815405c5aee8000bc18c1c9480bac620a451b416 include/platform/mir/graphics/event_handler_register.h32815405c5aee8000bc18c1c9480bac620a451b416 include/platform/mir/graphics/event_handler_register.h
335dc095474ef3e294c0aa4008e9ed997bdb21d34c include/platform/mir/graphics/gl_config.h335dc095474ef3e294c0aa4008e9ed997bdb21d34c include/platform/mir/graphics/gl_config.h
34d0442a5d5d88a4be6e3e1f99e433c1c43a86bfce include/platform/mir/graphics/gl_context.h34d0442a5d5d88a4be6e3e1f99e433c1c43a86bfce include/platform/mir/graphics/gl_context.h
3535
=== modified file 'server-ABI-sha1sums'
--- server-ABI-sha1sums 2014-11-18 17:26:29 +0000
+++ server-ABI-sha1sums 2014-11-18 19:29:59 +0000
@@ -7,7 +7,7 @@
742646c2367b9821e3aa71feff6e31cf50526acaa include/common/mir/geometry/size.h742646c2367b9821e3aa71feff6e31cf50526acaa include/common/mir/geometry/size.h
8e1be9faee8b844ca2ce617f8fd82c9ee08d56bed include/common/mir/graphics/native_buffer.h8e1be9faee8b844ca2ce617f8fd82c9ee08d56bed include/common/mir/graphics/native_buffer.h
9dcf8b8982f138bdde39a241825c610e955cd5e33 include/common/mir/input/input_platform.h9dcf8b8982f138bdde39a241825c610e955cd5e33 include/common/mir/input/input_platform.h
10208cd6aed5ef5f8f39b3eb86604e4133cb840485 include/common/mir/input/input_receiver_thread.h10fc96edf0f28451af2009aff58b9da8c0d462a604 include/common/mir/input/input_receiver_thread.h
11be7d58c9fde2ce91cc66dd6144b76e08b536266b include/common/mir/int_wrapper.h11be7d58c9fde2ce91cc66dd6144b76e08b536266b include/common/mir/int_wrapper.h
129ae8473df05dd9e048a73797f01a2f34f7447554 include/common/mir/time/types.h129ae8473df05dd9e048a73797f01a2f34f7447554 include/common/mir/time/types.h
139907751d046e4aea81881cf19e5df52c7a6a813e include/common/mir_toolkit/client_types.h139907751d046e4aea81881cf19e5df52c7a6a813e include/common/mir_toolkit/client_types.h
@@ -28,7 +28,7 @@
28986f5d0d8ea2c6a42cc320f468e682f81fec46ae include/platform/mir/graphics/display_buffer.h28986f5d0d8ea2c6a42cc320f468e682f81fec46ae include/platform/mir/graphics/display_buffer.h
29f53a0020b8f1bd4a941a201eb26271cffee0a7dd include/platform/mir/graphics/display_configuration.h29f53a0020b8f1bd4a941a201eb26271cffee0a7dd include/platform/mir/graphics/display_configuration.h
306fe08da318c920b0d20ea8b8f560f5ac7ed389fe include/platform/mir/graphics/display_configuration_policy.h306fe08da318c920b0d20ea8b8f560f5ac7ed389fe include/platform/mir/graphics/display_configuration_policy.h
3141ea906d208b761e3d5d5056095de9de2d4ffa17 include/platform/mir/graphics/display.h310eb20a383320790016fa22ae969e80fdecd20b8f include/platform/mir/graphics/display.h
32815405c5aee8000bc18c1c9480bac620a451b416 include/platform/mir/graphics/event_handler_register.h32815405c5aee8000bc18c1c9480bac620a451b416 include/platform/mir/graphics/event_handler_register.h
335dc095474ef3e294c0aa4008e9ed997bdb21d34c include/platform/mir/graphics/gl_config.h335dc095474ef3e294c0aa4008e9ed997bdb21d34c include/platform/mir/graphics/gl_config.h
34d0442a5d5d88a4be6e3e1f99e433c1c43a86bfce include/platform/mir/graphics/gl_context.h34d0442a5d5d88a4be6e3e1f99e433c1c43a86bfce include/platform/mir/graphics/gl_context.h
@@ -50,7 +50,7 @@
50d49eae4f986645b32e29ce2c1f99f524703ba3c0 include/server/mir/compositor/display_buffer_compositor.h50d49eae4f986645b32e29ce2c1f99f524703ba3c0 include/server/mir/compositor/display_buffer_compositor.h
51878ab5c4007d16dac213a3eb0105421d8ffad206 include/server/mir/compositor/scene_element.h51878ab5c4007d16dac213a3eb0105421d8ffad206 include/server/mir/compositor/scene_element.h
524fcf34e424128b87ddc76733594e32e09ebbd486 include/server/mir/compositor/scene.h524fcf34e424128b87ddc76733594e32e09ebbd486 include/server/mir/compositor/scene.h
53bd13887133bab2dfaab764077983311485b233d0 include/server/mir/default_server_configuration.h5367b99ce7b4571bc6141e7a1d6a0ea3e7de93a01b include/server/mir/default_server_configuration.h
54af1ff0714be973ac76d56006a2e5991f68cd1dec include/server/mir/display_server.h54af1ff0714be973ac76d56006a2e5991f68cd1dec include/server/mir/display_server.h
55a35c5495d8fd28fc0e375b17495fc5caab51b329 include/server/mir/emergency_cleanup.h55a35c5495d8fd28fc0e375b17495fc5caab51b329 include/server/mir/emergency_cleanup.h
56938de641cb0e01e1098b007b39b151a7dfe4adc1 include/server/mir/frontend/display_changer.h56938de641cb0e01e1098b007b39b151a7dfe4adc1 include/server/mir/frontend/display_changer.h
5757
=== modified file 'src/client/mir_surface.cpp'
--- src/client/mir_surface.cpp 2014-11-11 15:50:11 +0000
+++ src/client/mir_surface.cpp 2014-11-18 19:29:59 +0000
@@ -87,7 +87,8 @@
87 debug{debug},87 debug{debug},
88 connection(allocating_connection),88 connection(allocating_connection),
89 buffer_depository(std::make_shared<mcl::ClientBufferDepository>(factory, mir::frontend::client_buffer_cache_size)),89 buffer_depository(std::make_shared<mcl::ClientBufferDepository>(factory, mir::frontend::client_buffer_cache_size)),
90 input_platform(input_platform)90 input_platform(input_platform),
91 last_display_time(std::chrono::nanoseconds::zero())
91{92{
92 const char* report_target = getenv("MIR_CLIENT_PERF_REPORT");93 const char* report_target = getenv("MIR_CLIENT_PERF_REPORT");
93 if (report_target && !strcmp(report_target, "log"))94 if (report_target && !strcmp(report_target, "log"))
@@ -248,6 +249,15 @@
248 surface.set_height(buffer.height());249 surface.set_height(buffer.height());
249 }250 }
250251
252 if (buffer.has_vsync_time())
253 {
254 last_display_time = std::chrono::nanoseconds(buffer.vsync_time());
255 if (input_thread)
256 {
257 input_thread->notify_of_frame_time(last_display_time);
258 }
259 }
260
251 auto surface_size = geom::Size{surface.width(), surface.height()};261 auto surface_size = geom::Size{surface.width(), surface.height()};
252 auto surface_pf = convert_ipc_pf_to_geometry(surface.pixel_format());262 auto surface_pf = convert_ipc_pf_to_geometry(surface.pixel_format());
253263
@@ -593,3 +603,10 @@
593603
594 return orientation;604 return orientation;
595}605}
606
607std::chrono::nanoseconds MirSurface::get_last_display_time() const
608{
609 std::lock_guard<decltype(mutex)> lock(mutex);
610
611 return last_display_time;
612}
596613
=== modified file 'src/client/mir_surface.h'
--- src/client/mir_surface.h 2014-11-11 15:50:11 +0000
+++ src/client/mir_surface.h 2014-11-18 19:29:59 +0000
@@ -114,10 +114,12 @@
114 void set_event_handler(MirEventDelegate const* delegate);114 void set_event_handler(MirEventDelegate const* delegate);
115 void handle_event(MirEvent const& e);115 void handle_event(MirEvent const& e);
116116
117 std::chrono::nanoseconds get_last_display_time() const;
118
117 /* mir::client::ClientSurface */119 /* mir::client::ClientSurface */
118 void request_and_wait_for_next_buffer();120 void request_and_wait_for_next_buffer();
119 void request_and_wait_for_configure(MirSurfaceAttrib a, int value);121 void request_and_wait_for_configure(MirSurfaceAttrib a, int value);
120122
121 static bool is_valid(MirSurface* query);123 static bool is_valid(MirSurface* query);
122private:124private:
123 mutable std::mutex mutex; // Protects all members of *this125 mutable std::mutex mutex; // Protects all members of *this
@@ -147,6 +149,8 @@
147 std::shared_ptr<mir::client::MemoryRegion> secured_region;149 std::shared_ptr<mir::client::MemoryRegion> secured_region;
148 std::shared_ptr<mir::client::ClientBufferDepository> buffer_depository;150 std::shared_ptr<mir::client::ClientBufferDepository> buffer_depository;
149 std::shared_ptr<mir::input::receiver::InputPlatform> const input_platform;151 std::shared_ptr<mir::input::receiver::InputPlatform> const input_platform;
152
153 std::chrono::nanoseconds last_display_time;
150154
151 std::shared_ptr<EGLNativeWindowType> accelerated_window;155 std::shared_ptr<EGLNativeWindowType> accelerated_window;
152156
153157
=== modified file 'src/client/mir_surface_api.cpp'
--- src/client/mir_surface_api.cpp 2014-11-12 05:01:53 +0000
+++ src/client/mir_surface_api.cpp 2014-11-18 19:29:59 +0000
@@ -332,3 +332,8 @@
332332
333 return result;333 return result;
334}334}
335
336int64_t mir_surface_get_last_display_time(MirSurface *surface)
337{
338 return surface->get_last_display_time().count();
339}
335340
=== modified file 'src/common/input/android/android_input_receiver.cpp'
--- src/common/input/android/android_input_receiver.cpp 2014-10-21 16:21:14 +0000
+++ src/common/input/android/android_input_receiver.cpp 2014-11-18 19:29:59 +0000
@@ -39,7 +39,9 @@
39 looper(new droidinput::Looper(true)),39 looper(new droidinput::Looper(true)),
40 fd_added(false),40 fd_added(false),
41 xkb_mapper(std::make_shared<mircv::XKBMapper>()),41 xkb_mapper(std::make_shared<mircv::XKBMapper>()),
42 android_clock(clock)42 android_clock(clock),
43 has_new_frame_time(false),
44 frame_time(-1)
43{45{
44}46}
4547
@@ -52,7 +54,9 @@
52 looper(new droidinput::Looper(true)),54 looper(new droidinput::Looper(true)),
53 fd_added(false),55 fd_added(false),
54 xkb_mapper(std::make_shared<mircv::XKBMapper>()),56 xkb_mapper(std::make_shared<mircv::XKBMapper>()),
55 android_clock(clock)57 android_clock(clock),
58 has_new_frame_time(false),
59 frame_time(-1)
56{60{
57}61}
5862
@@ -85,49 +89,27 @@
85 droidinput::InputEvent *android_event;89 droidinput::InputEvent *android_event;
86 uint32_t event_sequence_id;90 uint32_t event_sequence_id;
8791
88 /*92 droidinput::status_t status;
89 * Enable "Project Butter" input resampling in InputConsumer::consume():93
90 * consumeBatches = true, so as to ensure the "cooked" event rate that94 bool result = false;
91 * clients experience is at least the minimum of event_rate_hz95
92 * and the raw device event rate.96 if ((status = input_consumer->consume(&event_factory, true, has_new_frame_time ? frame_time : -1,
93 * frame_time = A regular interval. This provides a virtual frame97 &event_sequence_id, &android_event))
94 * interval during which InputConsumer will collect raw events,98 == droidinput::OK)
95 * resample them and emit a "cooked" event back to us at roughly every
96 * 60th of a second. "cooked" events are both smoothed and
97 * extrapolated/predicted into the future (for tool=finger) giving the
98 * appearance of lower latency. Getting a real frame time from the
99 * graphics logic (which is messy) does not appear to be necessary to
100 * gain significant benefit.
101 *
102 * Note event_rate_hz is only 55Hz. This allows rendering to catch up and
103 * overtake the event rate every ~12th frame (200ms) on a 60Hz display.
104 * Thus on every 12th+1 frame, there will be zero buffer lag in responding
105 * to the cooked input event we have given the client.
106 * This phase control is useful as it eliminates the one frame of lag you
107 * would otherwise never catch up to if the event rate was exactly the same
108 * as the display refresh rate.
109 */
110
111 nsecs_t const now = android_clock(SYSTEM_TIME_MONOTONIC);
112 int const event_rate_hz = 55;
113 nsecs_t const one_frame = 1000000000ULL / event_rate_hz;
114 nsecs_t frame_time = (now / one_frame) * one_frame;
115
116 if (input_consumer->consume(&event_factory, true, frame_time,
117 &event_sequence_id, &android_event)
118 == droidinput::OK)
119 {99 {
120 mia::Lexicon::translate(android_event, ev);100 mia::Lexicon::translate(android_event, ev);
121
122 map_key_event(xkb_mapper, ev);101 map_key_event(xkb_mapper, ev);
123102
124 input_consumer->sendFinishedSignal(event_sequence_id, true);103 input_consumer->sendFinishedSignal(event_sequence_id, true);
125104
126 report->received_event(ev);105 report->received_event(ev);
127106
128 return true;107 result = true;
129 }108 }
130 return false;109
110 has_new_frame_time = false;
111
112 return result;
131}113}
132114
133// TODO: We use a droidinput::Looper here for polling functionality but it might be nice to integrate115// TODO: We use a droidinput::Looper here for polling functionality but it might be nice to integrate
@@ -140,28 +122,22 @@
140 looper->addFd(fd(), fd(), ALOOPER_EVENT_INPUT, nullptr, nullptr);122 looper->addFd(fd(), fd(), ALOOPER_EVENT_INPUT, nullptr, nullptr);
141 fd_added = true;123 fd_added = true;
142 }124 }
143125
144 auto reduced_timeout = timeout;126 auto reduced_timeout = timeout;
145 if (input_consumer->hasDeferredEvent())127
146 {128 if (input_consumer->hasPendingBatch())
147 // consume() didn't finish last time. Retry it immediately.129 reduced_timeout = std::chrono::milliseconds(1);
148 reduced_timeout = std::chrono::milliseconds::zero();130
149 }131 int result = 0;
150 else if (input_consumer->hasPendingBatch())132 if (!input_consumer->hasDeferredEvent())
151 {133 result = looper->pollOnce(reduced_timeout.count());
152 // When in constant motion we will usually "hasPendingBatch".134
153 // But the batch won't get flushed until the next frame interval,135 std::lock_guard<std::mutex> lg(frame_time_guard);
154 // so be sure to use a non-zero sleep time to avoid spinning the CPU136
155 // for the whole interval...137 // If we are awoken and not by a frame time it is for shutdown.
156138 if (result == ALOOPER_POLL_WAKE && has_new_frame_time == false)
157 // During tests with mocked clocks we may already have zero...
158 if (reduced_timeout != std::chrono::milliseconds::zero())
159 reduced_timeout = std::chrono::milliseconds(1);
160 }
161
162 auto result = looper->pollOnce(reduced_timeout.count());
163 if (result == ALOOPER_POLL_WAKE)
164 return false;139 return false;
140
165 if (result == ALOOPER_POLL_ERROR) // TODO: Exception?141 if (result == ALOOPER_POLL_ERROR) // TODO: Exception?
166 return false;142 return false;
167143
@@ -172,3 +148,16 @@
172{148{
173 looper->wake();149 looper->wake();
174}150}
151
152void mircva::InputReceiver::notify_of_frame_time(std::chrono::nanoseconds new_frame_time)
153{
154 {
155 std::lock_guard<std::mutex> lg(frame_time_guard);
156 has_new_frame_time = true;
157 if (new_frame_time != std::chrono::nanoseconds::min())
158 frame_time = new_frame_time.count();
159 else
160 frame_time = -1;
161 }
162 wake();
163}
175164
=== modified file 'src/common/input/android/android_input_receiver.h'
--- src/common/input/android/android_input_receiver.h 2014-10-01 06:25:56 +0000
+++ src/common/input/android/android_input_receiver.h 2014-11-18 19:29:59 +0000
@@ -26,6 +26,7 @@
2626
27#include <memory>27#include <memory>
28#include <chrono>28#include <chrono>
29#include <mutex>
2930
30namespace droidinput = android;31namespace droidinput = android;
3132
@@ -71,6 +72,8 @@
7172
72 /// May be used from any thread to wake an InputReceiver blocked in next_event73 /// May be used from any thread to wake an InputReceiver blocked in next_event
73 virtual void wake();74 virtual void wake();
75
76 virtual void notify_of_frame_time(std::chrono::nanoseconds frame_time);
7477
75protected:78protected:
76 InputReceiver(const InputReceiver&) = delete;79 InputReceiver(const InputReceiver&) = delete;
@@ -89,6 +92,10 @@
89 std::shared_ptr<XKBMapper> xkb_mapper;92 std::shared_ptr<XKBMapper> xkb_mapper;
9093
91 AndroidClock const android_clock;94 AndroidClock const android_clock;
95
96 std::mutex frame_time_guard;
97 bool has_new_frame_time;
98 int64_t frame_time;
9299
93 bool try_next_event(MirEvent &ev);100 bool try_next_event(MirEvent &ev);
94};101};
95102
=== modified file 'src/common/input/android/android_input_receiver_thread.cpp'
--- src/common/input/android/android_input_receiver_thread.cpp 2013-05-13 23:20:52 +0000
+++ src/common/input/android/android_input_receiver_thread.cpp 2014-11-18 19:29:59 +0000
@@ -66,3 +66,8 @@
66 std::this_thread::yield(); // yield() is needed to ensure reasonable runtime under valgrind66 std::this_thread::yield(); // yield() is needed to ensure reasonable runtime under valgrind
67 }67 }
68}68}
69
70void mircva::InputReceiverThread::notify_of_frame_time(std::chrono::nanoseconds frame_time)
71{
72 receiver->notify_of_frame_time(frame_time);
73}
6974
=== modified file 'src/common/input/android/android_input_receiver_thread.h'
--- src/common/input/android/android_input_receiver_thread.h 2014-03-06 06:05:17 +0000
+++ src/common/input/android/android_input_receiver_thread.h 2014-11-18 19:29:59 +0000
@@ -49,6 +49,8 @@
49 void start();49 void start();
50 void stop();50 void stop();
51 void join();51 void join();
52
53 void notify_of_frame_time(std::chrono::nanoseconds frame_time) override;
5254
53protected:55protected:
54 InputReceiverThread(const InputReceiverThread&) = delete;56 InputReceiverThread(const InputReceiverThread&) = delete;
5557
=== added directory 'src/include/platform/mir/frontend'
=== added file 'src/include/platform/mir/frontend/vsync_provider.h'
--- src/include/platform/mir/frontend/vsync_provider.h 1970-01-01 00:00:00 +0000
+++ src/include/platform/mir/frontend/vsync_provider.h 2014-11-18 19:29:59 +0000
@@ -0,0 +1,46 @@
1/*
2 * Copyright © 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Robert Carr <robert.carr@canonical.com>
17 */
18
19#ifndef MIR_FRONTEND_VSYNC_PROVIDER_H_
20#define MIR_FRONTEND_VSYNC_PROVIDER_H_
21
22#include "mir/graphics/display_configuration.h"
23
24#include <chrono>
25
26namespace mir
27{
28namespace frontend
29{
30class VsyncProvider
31{
32public:
33 virtual ~VsyncProvider() = default;
34
35 virtual std::chrono::nanoseconds last_vsync_for(graphics::DisplayConfigurationOutputId output) = 0;
36
37protected:
38 VsyncProvider() = default;
39
40 VsyncProvider& operator=(VsyncProvider const& other) = delete;
41 VsyncProvider(VsyncProvider const& other) = delete;
42};
43}
44}
45
46#endif // MIR_FRONTEND_VSYNC_PROVIDER_H_
047
=== modified file 'src/platform/graphics/android/display.cpp'
--- src/platform/graphics/android/display.cpp 2014-10-01 06:25:56 +0000
+++ src/platform/graphics/android/display.cpp 2014-11-18 19:29:59 +0000
@@ -22,6 +22,7 @@
22#include "mir/graphics/display_buffer.h"22#include "mir/graphics/display_buffer.h"
23#include "mir/graphics/gl_context.h"23#include "mir/graphics/gl_context.h"
24#include "mir/graphics/egl_resources.h"24#include "mir/graphics/egl_resources.h"
25#include "hwc_vsync.h"
25#include "display.h"26#include "display.h"
26#include "display_builder.h"27#include "display_builder.h"
27#include "mir/geometry/rectangle.h"28#include "mir/geometry/rectangle.h"
@@ -30,6 +31,7 @@
3031
31namespace mga=mir::graphics::android;32namespace mga=mir::graphics::android;
32namespace mg=mir::graphics;33namespace mg=mir::graphics;
34namespace mf = mir::frontend;
33namespace geom=mir::geometry;35namespace geom=mir::geometry;
3436
35mga::Display::Display(std::shared_ptr<mga::DisplayBuilder> const& display_builder,37mga::Display::Display(std::shared_ptr<mga::DisplayBuilder> const& display_builder,
@@ -110,3 +112,8 @@
110{112{
111 return std::unique_ptr<mg::GLContext>{new mga::PbufferGLContext(gl_context)};113 return std::unique_ptr<mg::GLContext>{new mga::PbufferGLContext(gl_context)};
112}114}
115
116std::shared_ptr<mf::VsyncProvider> mga::Display::vsync_provider()
117{
118 return display_builder->vsync_coordinator();
119}
113120
=== modified file 'src/platform/graphics/android/display.h'
--- src/platform/graphics/android/display.h 2014-11-03 06:51:26 +0000
+++ src/platform/graphics/android/display.h 2014-11-18 19:29:59 +0000
@@ -67,6 +67,8 @@
6767
68 std::shared_ptr<Cursor> create_hardware_cursor(std::shared_ptr<CursorImage> const& initial_image) override;68 std::shared_ptr<Cursor> create_hardware_cursor(std::shared_ptr<CursorImage> const& initial_image) override;
69 std::unique_ptr<graphics::GLContext> create_gl_context() override;69 std::unique_ptr<graphics::GLContext> create_gl_context() override;
70 std::shared_ptr<frontend::VsyncProvider> vsync_provider() override;
71
7072
71private:73private:
72 std::shared_ptr<DisplayBuilder> const display_builder;74 std::shared_ptr<DisplayBuilder> const display_builder;
7375
=== modified file 'src/platform/graphics/android/display_builder.h'
--- src/platform/graphics/android/display_builder.h 2014-10-01 06:25:56 +0000
+++ src/platform/graphics/android/display_builder.h 2014-11-18 19:29:59 +0000
@@ -31,6 +31,7 @@
31namespace android31namespace android
32{32{
33class GLContext;33class GLContext;
34class HWCVsyncCoordinator;
3435
35class DisplayBuilder36class DisplayBuilder
36{37{
@@ -41,6 +42,8 @@
41 virtual std::unique_ptr<ConfigurableDisplayBuffer> create_display_buffer(42 virtual std::unique_ptr<ConfigurableDisplayBuffer> create_display_buffer(
42 GLProgramFactory const& gl_program_factory, GLContext const& gl_context) = 0;43 GLProgramFactory const& gl_program_factory, GLContext const& gl_context) = 0;
4344
45 virtual std::shared_ptr<HWCVsyncCoordinator> vsync_coordinator() const = 0;
46
44protected:47protected:
45 DisplayBuilder() = default;48 DisplayBuilder() = default;
46 DisplayBuilder(DisplayBuilder const&) = delete;49 DisplayBuilder(DisplayBuilder const&) = delete;
4750
=== modified file 'src/platform/graphics/android/display_resource_factory.h'
--- src/platform/graphics/android/display_resource_factory.h 2014-10-01 06:25:56 +0000
+++ src/platform/graphics/android/display_resource_factory.h 2014-11-18 19:29:59 +0000
@@ -35,6 +35,7 @@
35class DisplayDevice;35class DisplayDevice;
36class FramebufferBundle;36class FramebufferBundle;
37class HwcWrapper;37class HwcWrapper;
38class HWCVsyncCoordinator;
3839
39class DisplayResourceFactory40class DisplayResourceFactory
40{41{
@@ -54,6 +55,8 @@
54 virtual std::shared_ptr<DisplayDevice> create_hwc_fb_device(55 virtual std::shared_ptr<DisplayDevice> create_hwc_fb_device(
55 std::shared_ptr<HwcWrapper> const& hwc_native_device,56 std::shared_ptr<HwcWrapper> const& hwc_native_device,
56 std::shared_ptr<framebuffer_device_t> const& fb_native_device) const = 0;57 std::shared_ptr<framebuffer_device_t> const& fb_native_device) const = 0;
58
59 virtual std::shared_ptr<HWCVsyncCoordinator> create_vsync_coordinator() const = 0;
5760
58protected:61protected:
59 DisplayResourceFactory() = default;62 DisplayResourceFactory() = default;
6063
=== modified file 'src/platform/graphics/android/hwc_common_device.cpp'
--- src/platform/graphics/android/hwc_common_device.cpp 2014-10-01 06:25:56 +0000
+++ src/platform/graphics/android/hwc_common_device.cpp 2014-11-18 19:29:59 +0000
@@ -32,12 +32,12 @@
32{32{
33}33}
3434
35static void vsync_hook(const struct hwc_procs* procs, int /*disp*/, int64_t /*timestamp*/)35static void vsync_hook(const struct hwc_procs* procs, int /*disp*/, int64_t timestamp)
36{36{
37 auto self = reinterpret_cast<mga::HWCCallbacks const*>(procs)->self.load();37 auto self = reinterpret_cast<mga::HWCCallbacks const*>(procs)->self.load();
38 if (!self)38 if (!self)
39 return;39 return;
40 self->notify_vsync();40 self->notify_vsync(std::chrono::nanoseconds(timestamp));
41}41}
4242
43static void hotplug_hook(const struct hwc_procs* /*procs*/, int /*disp*/, int /*connected*/)43static void hotplug_hook(const struct hwc_procs* /*procs*/, int /*disp*/, int /*connected*/)
@@ -84,9 +84,9 @@
84 callbacks->self = nullptr;84 callbacks->self = nullptr;
85}85}
8686
87void mga::HWCCommonDevice::notify_vsync()87void mga::HWCCommonDevice::notify_vsync(std::chrono::nanoseconds timestamp)
88{88{
89 coordinator->notify_vsync();89 coordinator->notify_vsync(timestamp);
90}90}
9191
92void mga::HWCCommonDevice::mode(MirPowerMode mode_request)92void mga::HWCCommonDevice::mode(MirPowerMode mode_request)
9393
=== modified file 'src/platform/graphics/android/hwc_common_device.h'
--- src/platform/graphics/android/hwc_common_device.h 2014-10-01 06:25:56 +0000
+++ src/platform/graphics/android/hwc_common_device.h 2014-11-18 19:29:59 +0000
@@ -26,6 +26,7 @@
26#include <mutex>26#include <mutex>
27#include <condition_variable>27#include <condition_variable>
28#include <atomic>28#include <atomic>
29#include <chrono>
2930
30namespace mir31namespace mir
31{32{
@@ -48,7 +49,7 @@
48public:49public:
49 virtual ~HWCCommonDevice() noexcept;50 virtual ~HWCCommonDevice() noexcept;
5051
51 void notify_vsync();52 void notify_vsync(std::chrono::nanoseconds timestamp);
52 void mode(MirPowerMode mode);53 void mode(MirPowerMode mode);
53 bool apply_orientation(MirOrientation orientation) const;54 bool apply_orientation(MirOrientation orientation) const;
5455
5556
=== modified file 'src/platform/graphics/android/hwc_vsync.cpp'
--- src/platform/graphics/android/hwc_vsync.cpp 2014-03-06 06:05:17 +0000
+++ src/platform/graphics/android/hwc_vsync.cpp 2014-11-18 19:29:59 +0000
@@ -17,10 +17,17 @@
17 */17 */
1818
19#include "hwc_vsync.h"19#include "hwc_vsync.h"
20namespace mga=mir::graphics::android;20
21#include <boost/throw_exception.hpp>
22
23#include <stdexcept>
24
25namespace mg = mir::graphics;
26namespace mga = mg::android;
2127
22mga::HWCVsync::HWCVsync()28mga::HWCVsync::HWCVsync()
23 : vsync_occurred(false)29 : vsync_occurred(false),
30 last_vsync(std::chrono::nanoseconds::zero())
24{31{
25}32}
2633
@@ -34,9 +41,24 @@
34 }41 }
35}42}
3643
37void mga::HWCVsync::notify_vsync()44void mga::HWCVsync::notify_vsync(std::chrono::nanoseconds time)
38{45{
39 std::unique_lock<std::mutex> lk(vsync_wait_mutex);46 std::unique_lock<std::mutex> lk(vsync_wait_mutex);
47
40 vsync_occurred = true;48 vsync_occurred = true;
49 last_vsync = time;
50
41 vsync_trigger.notify_all();51 vsync_trigger.notify_all();
42}52}
53
54std::chrono::nanoseconds mga::HWCVsync::last_vsync_for(mg::DisplayConfigurationOutputId output)
55{
56 if (output != mg::DisplayConfigurationOutputId{0})
57 {
58 BOOST_THROW_EXCEPTION(std::runtime_error(
59 "HWCVsync got non zero output ID but multi-monitor is not yet supported"));
60 }
61
62 std::unique_lock<std::mutex> lk(vsync_wait_mutex);
63 return last_vsync;
64}
4365
=== modified file 'src/platform/graphics/android/hwc_vsync.h'
--- src/platform/graphics/android/hwc_vsync.h 2014-03-06 06:05:17 +0000
+++ src/platform/graphics/android/hwc_vsync.h 2014-11-18 19:29:59 +0000
@@ -19,9 +19,13 @@
19#ifndef MIR_GRAPHICS_ANDROID_HWC_VSYNC_H_19#ifndef MIR_GRAPHICS_ANDROID_HWC_VSYNC_H_
20#define MIR_GRAPHICS_ANDROID_HWC_VSYNC_H_20#define MIR_GRAPHICS_ANDROID_HWC_VSYNC_H_
2121
22#include "mir/frontend/vsync_provider.h"
23
22#include "hwc_vsync_coordinator.h"24#include "hwc_vsync_coordinator.h"
25
23#include <mutex>26#include <mutex>
24#include <condition_variable>27#include <condition_variable>
28#include <chrono>
2529
26namespace mir30namespace mir
27{31{
@@ -36,11 +40,16 @@
36 HWCVsync();40 HWCVsync();
3741
38 void wait_for_vsync();42 void wait_for_vsync();
39 void notify_vsync();43 void notify_vsync(std::chrono::nanoseconds time);
44
45 std::chrono::nanoseconds last_vsync_for(graphics::DisplayConfigurationOutputId output) override;
46
40private:47private:
41 std::mutex vsync_wait_mutex;48 std::mutex vsync_wait_mutex;
42 std::condition_variable vsync_trigger;49 std::condition_variable vsync_trigger;
50
43 bool vsync_occurred;51 bool vsync_occurred;
52 std::chrono::nanoseconds last_vsync;
44};53};
4554
46}55}
4756
=== modified file 'src/platform/graphics/android/hwc_vsync_coordinator.h'
--- src/platform/graphics/android/hwc_vsync_coordinator.h 2014-03-06 06:05:17 +0000
+++ src/platform/graphics/android/hwc_vsync_coordinator.h 2014-11-18 19:29:59 +0000
@@ -19,6 +19,10 @@
19#ifndef MIR_GRAPHICS_ANDROID_HWC_VSYNC_COORDINATOR_H_19#ifndef MIR_GRAPHICS_ANDROID_HWC_VSYNC_COORDINATOR_H_
20#define MIR_GRAPHICS_ANDROID_HWC_VSYNC_COORDINATOR_H_20#define MIR_GRAPHICS_ANDROID_HWC_VSYNC_COORDINATOR_H_
2121
22#include "mir/frontend/vsync_provider.h"
23
24#include <chrono>
25
22namespace mir26namespace mir
23{27{
24namespace graphics28namespace graphics
@@ -26,13 +30,14 @@
26namespace android30namespace android
27{31{
2832
29class HWCVsyncCoordinator33class HWCVsyncCoordinator : public frontend::VsyncProvider
30{34{
31public:35public:
32 virtual ~HWCVsyncCoordinator() = default;36 virtual ~HWCVsyncCoordinator() = default;
3337
34 virtual void wait_for_vsync() = 0;38 virtual void wait_for_vsync() = 0;
35 virtual void notify_vsync() = 0;39 virtual void notify_vsync(std::chrono::nanoseconds time) = 0;
40 virtual std::chrono::nanoseconds last_vsync_for(DisplayConfigurationOutputId id) = 0;
3641
37protected:42protected:
38 HWCVsyncCoordinator() = default;43 HWCVsyncCoordinator() = default;
3944
=== modified file 'src/platform/graphics/android/output_builder.cpp'
--- src/platform/graphics/android/output_builder.cpp 2014-10-01 06:25:56 +0000
+++ src/platform/graphics/android/output_builder.cpp 2014-11-18 19:29:59 +0000
@@ -41,6 +41,7 @@
41 : buffer_allocator(buffer_allocator),41 : buffer_allocator(buffer_allocator),
42 res_factory(res_factory),42 res_factory(res_factory),
43 display_report(display_report),43 display_report(display_report),
44 vsync_coordinator_(res_factory->create_vsync_coordinator()),
44 force_backup_display(false),45 force_backup_display(false),
45 overlay_optimization(overlay_optimization)46 overlay_optimization(overlay_optimization)
46{47{
@@ -118,3 +119,8 @@
118 gl_program_factory,119 gl_program_factory,
119 overlay_optimization));120 overlay_optimization));
120}121}
122
123std::shared_ptr<mga::HWCVsyncCoordinator> mga::OutputBuilder::vsync_coordinator() const
124{
125 return vsync_coordinator_;
126}
121127
=== modified file 'src/platform/graphics/android/output_builder.h'
--- src/platform/graphics/android/output_builder.h 2014-10-01 06:25:56 +0000
+++ src/platform/graphics/android/output_builder.h 2014-11-18 19:29:59 +0000
@@ -52,11 +52,13 @@
52 std::unique_ptr<ConfigurableDisplayBuffer> create_display_buffer(52 std::unique_ptr<ConfigurableDisplayBuffer> create_display_buffer(
53 GLProgramFactory const& gl_program_factory,53 GLProgramFactory const& gl_program_factory,
54 GLContext const& gl_context);54 GLContext const& gl_context);
55 std::shared_ptr<HWCVsyncCoordinator> vsync_coordinator() const;
5556
56private:57private:
57 std::shared_ptr<GraphicBufferAllocator> const buffer_allocator;58 std::shared_ptr<GraphicBufferAllocator> const buffer_allocator;
58 std::shared_ptr<DisplayResourceFactory> const res_factory;59 std::shared_ptr<DisplayResourceFactory> const res_factory;
59 std::shared_ptr<DisplayReport> const display_report;60 std::shared_ptr<DisplayReport> const display_report;
61 std::shared_ptr<HWCVsyncCoordinator> const vsync_coordinator_;
6062
61 std::shared_ptr<FramebufferBundle> framebuffers;63 std::shared_ptr<FramebufferBundle> framebuffers;
62 bool force_backup_display;64 bool force_backup_display;
6365
=== modified file 'src/platform/graphics/android/platform.cpp'
--- src/platform/graphics/android/platform.cpp 2014-11-18 03:21:20 +0000
+++ src/platform/graphics/android/platform.cpp 2014-11-18 19:29:59 +0000
@@ -26,6 +26,7 @@
26#include "output_builder.h"26#include "output_builder.h"
27#include "buffer_writer.h"27#include "buffer_writer.h"
28#include "hwc_loggers.h"28#include "hwc_loggers.h"
29#include "hwc_vsync.h"
29#include "ipc_operations.h"30#include "ipc_operations.h"
30#include "mir/graphics/platform_ipc_package.h"31#include "mir/graphics/platform_ipc_package.h"
31#include "mir/graphics/buffer_ipc_message.h"32#include "mir/graphics/buffer_ipc_message.h"
@@ -160,6 +161,7 @@
160 auto logger = make_logger(*options);161 auto logger = make_logger(*options);
161 auto overlay_option = should_use_overlay_optimization(*options);162 auto overlay_option = should_use_overlay_optimization(*options);
162 logger->log_overlay_optimization(overlay_option);163 logger->log_overlay_optimization(overlay_option);
164
163 auto display_resource_factory = std::make_shared<mga::ResourceFactory>();165 auto display_resource_factory = std::make_shared<mga::ResourceFactory>();
164 auto fb_allocator = std::make_shared<mga::AndroidGraphicBufferAllocator>();166 auto fb_allocator = std::make_shared<mga::AndroidGraphicBufferAllocator>();
165 auto display_builder = std::make_shared<mga::OutputBuilder>(167 auto display_builder = std::make_shared<mga::OutputBuilder>(
@@ -172,7 +174,8 @@
172 std::shared_ptr<mg::NestedContext> const&)174 std::shared_ptr<mg::NestedContext> const&)
173{175{
174 //TODO: remove nullptr parameter once platform classes are sorted.176 //TODO: remove nullptr parameter once platform classes are sorted.
175 // mg::NativePlatform cannot create a display anyways, so it doesnt need a display builder177 // mg::NativePlatform cannot create a display anyways, so it doesnt need a display builder or
178 // a vsync provider.
176 return std::make_shared<mga::Platform>(nullptr, display_report);179 return std::make_shared<mga::Platform>(nullptr, display_report);
177}180}
178181
179182
=== modified file 'src/platform/graphics/android/platform.h'
--- src/platform/graphics/android/platform.h 2014-11-18 03:21:20 +0000
+++ src/platform/graphics/android/platform.h 2014-11-18 19:29:59 +0000
@@ -33,6 +33,7 @@
33class GraphicBufferAllocator;33class GraphicBufferAllocator;
34class FramebufferFactory;34class FramebufferFactory;
35class DisplayBuilder;35class DisplayBuilder;
36class HWCVsyncCoordinator;
3637
37class Platform : public graphics::Platform, public NativePlatform38class Platform : public graphics::Platform, public NativePlatform
38{39{
@@ -52,6 +53,7 @@
52 std::shared_ptr<PlatformIPCPackage> connection_ipc_package() override;53 std::shared_ptr<PlatformIPCPackage> connection_ipc_package() override;
53 std::shared_ptr<InternalClient> create_internal_client() override;54 std::shared_ptr<InternalClient> create_internal_client() override;
54 std::shared_ptr<graphics::BufferWriter> make_buffer_writer() override;55 std::shared_ptr<graphics::BufferWriter> make_buffer_writer() override;
56
55 void fill_buffer_package(57 void fill_buffer_package(
56 BufferIpcMessage* packer, graphics::Buffer const* buffer, BufferIpcMsgType msg_type) const override;58 BufferIpcMessage* packer, graphics::Buffer const* buffer, BufferIpcMsgType msg_type) const override;
57 EGLNativeDisplayType egl_native_display() const override;59 EGLNativeDisplayType egl_native_display() const override;
@@ -63,6 +65,7 @@
6365
64 std::shared_ptr<DisplayBuilder> const display_builder;66 std::shared_ptr<DisplayBuilder> const display_builder;
65 std::shared_ptr<DisplayReport> const display_report;67 std::shared_ptr<DisplayReport> const display_report;
68
66 std::shared_ptr<PlatformIpcOperations> const ipc_operations;69 std::shared_ptr<PlatformIpcOperations> const ipc_operations;
67 DeviceQuirks quirks{PropertiesOps{}};70 DeviceQuirks quirks{PropertiesOps{}};
68};71};
6972
=== modified file 'src/platform/graphics/android/resource_factory.cpp'
--- src/platform/graphics/android/resource_factory.cpp 2014-10-01 06:25:56 +0000
+++ src/platform/graphics/android/resource_factory.cpp 2014-11-18 19:29:59 +0000
@@ -39,6 +39,11 @@
39namespace mg = mir::graphics;39namespace mg = mir::graphics;
40namespace mga=mir::graphics::android;40namespace mga=mir::graphics::android;
4141
42mga::ResourceFactory::ResourceFactory()
43 : vsync_coordinator(std::make_shared<mga::HWCVsync>())
44{
45}
46
42std::shared_ptr<framebuffer_device_t> mga::ResourceFactory::create_fb_native_device() const47std::shared_ptr<framebuffer_device_t> mga::ResourceFactory::create_fb_native_device() const
43{48{
44 hw_module_t const* module;49 hw_module_t const* module;
@@ -92,15 +97,18 @@
92std::shared_ptr<mga::DisplayDevice> mga::ResourceFactory::create_hwc_device(97std::shared_ptr<mga::DisplayDevice> mga::ResourceFactory::create_hwc_device(
93 std::shared_ptr<HwcWrapper> const& wrapper) const98 std::shared_ptr<HwcWrapper> const& wrapper) const
94{99{
95 auto syncer = std::make_shared<mga::HWCVsync>();
96 auto file_ops = std::make_shared<mga::RealSyncFileOps>();100 auto file_ops = std::make_shared<mga::RealSyncFileOps>();
97 return std::make_shared<mga::HwcDevice>(wrapper, syncer, file_ops);101 return std::make_shared<mga::HwcDevice>(wrapper, vsync_coordinator, file_ops);
98}102}
99103
100std::shared_ptr<mga::DisplayDevice> mga::ResourceFactory::create_hwc_fb_device(104std::shared_ptr<mga::DisplayDevice> mga::ResourceFactory::create_hwc_fb_device(
101 std::shared_ptr<HwcWrapper> const& wrapper,105 std::shared_ptr<HwcWrapper> const& wrapper,
102 std::shared_ptr<framebuffer_device_t> const& fb_native_device) const106 std::shared_ptr<framebuffer_device_t> const& fb_native_device) const
103{107{
104 auto syncer = std::make_shared<mga::HWCVsync>();108 return std::make_shared<mga::HwcFbDevice>(wrapper, fb_native_device, vsync_coordinator);
105 return std::make_shared<mga::HwcFbDevice>(wrapper, fb_native_device, syncer);109}
110
111std::shared_ptr<mga::HWCVsyncCoordinator> mga::ResourceFactory::create_vsync_coordinator() const
112{
113 return vsync_coordinator;
106}114}
107115
=== modified file 'src/platform/graphics/android/resource_factory.h'
--- src/platform/graphics/android/resource_factory.h 2014-10-01 06:25:56 +0000
+++ src/platform/graphics/android/resource_factory.h 2014-11-18 19:29:59 +0000
@@ -27,10 +27,12 @@
27{27{
28namespace android28namespace android
29{29{
30class HWCVsyncCoordinator;
3031
31class ResourceFactory : public DisplayResourceFactory32class ResourceFactory : public DisplayResourceFactory
32{33{
33public:34public:
35 ResourceFactory();
34 //native allocations36 //native allocations
35 std::shared_ptr<hwc_composer_device_1> create_hwc_native_device() const;37 std::shared_ptr<hwc_composer_device_1> create_hwc_native_device() const;
36 std::shared_ptr<framebuffer_device_t> create_fb_native_device() const;38 std::shared_ptr<framebuffer_device_t> create_fb_native_device() const;
@@ -46,6 +48,11 @@
4648
47 std::shared_ptr<ANativeWindow> create_native_window(49 std::shared_ptr<ANativeWindow> create_native_window(
48 std::shared_ptr<FramebufferBundle> const& fb_bundle) const;50 std::shared_ptr<FramebufferBundle> const& fb_bundle) const;
51
52 std::shared_ptr<HWCVsyncCoordinator> create_vsync_coordinator() const;
53
54private:
55 std::shared_ptr<HWCVsyncCoordinator> const vsync_coordinator;
49};56};
5057
51}58}
5259
=== modified file 'src/platform/graphics/mesa/display.cpp'
--- src/platform/graphics/mesa/display.cpp 2014-10-01 06:25:56 +0000
+++ src/platform/graphics/mesa/display.cpp 2014-11-18 19:29:59 +0000
@@ -24,12 +24,15 @@
24#include "kms_output.h"24#include "kms_output.h"
25#include "kms_page_flipper.h"25#include "kms_page_flipper.h"
26#include "virtual_terminal.h"26#include "virtual_terminal.h"
27
27#include "mir/graphics/overlapping_output_grouping.h"28#include "mir/graphics/overlapping_output_grouping.h"
28#include "mir/graphics/event_handler_register.h"29#include "mir/graphics/event_handler_register.h"
29
30#include "mir/graphics/display_report.h"30#include "mir/graphics/display_report.h"
31#include "mir/graphics/gl_context.h"31#include "mir/graphics/gl_context.h"
32#include "mir/graphics/display_configuration_policy.h"32#include "mir/graphics/display_configuration_policy.h"
33
34#include "mir/frontend/vsync_provider.h"
35
33#include "mir/geometry/rectangle.h"36#include "mir/geometry/rectangle.h"
3437
35#include <boost/throw_exception.hpp>38#include <boost/throw_exception.hpp>
@@ -41,6 +44,7 @@
4144
42namespace mgm = mir::graphics::mesa;45namespace mgm = mir::graphics::mesa;
43namespace mg = mir::graphics;46namespace mg = mir::graphics;
47namespace mf = mir::frontend;
44namespace geom = mir::geometry;48namespace geom = mir::geometry;
4549
46namespace50namespace
@@ -360,3 +364,16 @@
360 }364 }
361 });365 });
362}366}
367
368// TODO: Implement for Mesa to enable touch resampling
369std::shared_ptr<mf::VsyncProvider> mgm::Display::vsync_provider()
370{
371 struct NullVsyncProvider : public mf::VsyncProvider
372 {
373 std::chrono::nanoseconds last_vsync_for(graphics::DisplayConfigurationOutputId) override
374 {
375 return std::chrono::nanoseconds::zero();
376 }
377 };
378 return std::make_shared<NullVsyncProvider>();
379}
363380
=== modified file 'src/platform/graphics/mesa/display.h'
--- src/platform/graphics/mesa/display.h 2014-11-03 06:51:26 +0000
+++ src/platform/graphics/mesa/display.h 2014-11-18 19:29:59 +0000
@@ -81,6 +81,8 @@
8181
82 std::shared_ptr<graphics::Cursor> create_hardware_cursor(std::shared_ptr<CursorImage> const& initial_image) override;82 std::shared_ptr<graphics::Cursor> create_hardware_cursor(std::shared_ptr<CursorImage> const& initial_image) override;
83 std::unique_ptr<GLContext> create_gl_context() override;83 std::unique_ptr<GLContext> create_gl_context() override;
84 std::shared_ptr<frontend::VsyncProvider> vsync_provider() override;
85
8486
85private:87private:
86 void clear_connected_unused_outputs();88 void clear_connected_unused_outputs();
8789
=== modified file 'src/protobuf/mir_protobuf.proto'
--- src/protobuf/mir_protobuf.proto 2014-10-27 22:31:16 +0000
+++ src/protobuf/mir_protobuf.proto 2014-11-18 19:29:59 +0000
@@ -39,6 +39,8 @@
39 optional uint32 flags = 6;39 optional uint32 flags = 6;
40 optional int32 width = 7;40 optional int32 width = 7;
41 optional int32 height = 8;41 optional int32 height = 8;
42
43 optional int64 vsync_time = 9;
4244
43 optional string error = 127;45 optional string error = 127;
44}46}
4547
=== modified file 'src/server/frontend/default_configuration.cpp'
--- src/server/frontend/default_configuration.cpp 2014-11-12 14:07:30 +0000
+++ src/server/frontend/default_configuration.cpp 2014-11-18 19:29:59 +0000
@@ -27,6 +27,7 @@
27#include "mir/graphics/platform.h"27#include "mir/graphics/platform.h"
28#include "mir/frontend/protobuf_connection_creator.h"28#include "mir/frontend/protobuf_connection_creator.h"
29#include "mir/frontend/session_authorizer.h"29#include "mir/frontend/session_authorizer.h"
30#include "mir/graphics/display.h"
30#include "mir/options/configuration.h"31#include "mir/options/configuration.h"
31#include "mir/options/option.h"32#include "mir/options/option.h"
3233
@@ -137,6 +138,16 @@
137 });138 });
138}139}
139140
141std::shared_ptr<mf::VsyncProvider>
142mir::DefaultServerConfiguration::the_vsync_provider()
143{
144 return vsync_provider(
145 [&]()
146 {
147 return the_display()->vsync_provider();
148 });
149}
150
140std::shared_ptr<mir::frontend::ProtobufIpcFactory>151std::shared_ptr<mir::frontend::ProtobufIpcFactory>
141mir::DefaultServerConfiguration::new_ipc_factory(152mir::DefaultServerConfiguration::new_ipc_factory(
142 std::shared_ptr<mf::SessionAuthorizer> const& session_authorizer)153 std::shared_ptr<mf::SessionAuthorizer> const& session_authorizer)
@@ -151,13 +162,14 @@
151 translator = std::make_shared<mf::UnsupportedCoordinateTranslator>();162 translator = std::make_shared<mf::UnsupportedCoordinateTranslator>();
152 }163 }
153 return std::make_shared<mf::DefaultIpcFactory>(164 return std::make_shared<mf::DefaultIpcFactory>(
154 the_frontend_shell(),165 the_frontend_shell(),
155 the_session_mediator_report(),166 the_session_mediator_report(),
156 the_graphics_platform()->make_ipc_operations(),167 the_graphics_platform()->make_ipc_operations(),
157 the_frontend_display_changer(),168 the_frontend_display_changer(),
158 the_buffer_allocator(),169 the_buffer_allocator(),
159 the_screencast(),170 the_screencast(),
160 session_authorizer,171 session_authorizer,
161 the_cursor_images(),172 the_cursor_images(),
162 translator);173 the_vsync_provider(),
174 translator);
163}175}
164176
=== modified file 'src/server/frontend/default_ipc_factory.cpp'
--- src/server/frontend/default_ipc_factory.cpp 2014-11-12 14:07:30 +0000
+++ src/server/frontend/default_ipc_factory.cpp 2014-11-18 19:29:59 +0000
@@ -39,6 +39,7 @@
39 std::shared_ptr<Screencast> const& screencast,39 std::shared_ptr<Screencast> const& screencast,
40 std::shared_ptr<SessionAuthorizer> const& session_authorizer,40 std::shared_ptr<SessionAuthorizer> const& session_authorizer,
41 std::shared_ptr<mi::CursorImages> const& cursor_images,41 std::shared_ptr<mi::CursorImages> const& cursor_images,
42 std::shared_ptr<mf::VsyncProvider> const& vsync_provider,
42 std::shared_ptr<scene::CoordinateTranslator> const& translator) :43 std::shared_ptr<scene::CoordinateTranslator> const& translator) :
43 shell(shell),44 shell(shell),
44 no_prompt_shell(std::make_shared<NoPromptShell>(shell)),45 no_prompt_shell(std::make_shared<NoPromptShell>(shell)),
@@ -50,6 +51,7 @@
50 screencast(screencast),51 screencast(screencast),
51 session_authorizer(session_authorizer),52 session_authorizer(session_authorizer),
52 cursor_images(cursor_images),53 cursor_images(cursor_images),
54 vsync_provider(vsync_provider),
53 translator{translator}55 translator{translator}
54{56{
55}57}
@@ -93,7 +95,7 @@
93 sm_report,95 sm_report,
94 sink,96 sink,
95 effective_screencast,97 effective_screencast,
96 connection_context, cursor_images);98 connection_context, cursor_images, vsync_provider);
97}99}
98100
99std::shared_ptr<mf::ResourceCache> mf::DefaultIpcFactory::resource_cache()101std::shared_ptr<mf::ResourceCache> mf::DefaultIpcFactory::resource_cache()
@@ -110,7 +112,8 @@
110 std::shared_ptr<EventSink> const& sink,112 std::shared_ptr<EventSink> const& sink,
111 std::shared_ptr<Screencast> const& effective_screencast,113 std::shared_ptr<Screencast> const& effective_screencast,
112 ConnectionContext const& connection_context,114 ConnectionContext const& connection_context,
113 std::shared_ptr<mi::CursorImages> const& cursor_images)115 std::shared_ptr<mi::CursorImages> const& cursor_images,
116 std::shared_ptr<mf::VsyncProvider> const& vsync_provider)
114{117{
115 return std::make_shared<SessionMediator>(118 return std::make_shared<SessionMediator>(
116 shell,119 shell,
@@ -123,5 +126,6 @@
123 effective_screencast,126 effective_screencast,
124 connection_context,127 connection_context,
125 cursor_images,128 cursor_images,
129 vsync_provider,
126 translator);130 translator);
127}131}
128132
=== modified file 'src/server/frontend/default_ipc_factory.h'
--- src/server/frontend/default_ipc_factory.h 2014-11-12 14:07:30 +0000
+++ src/server/frontend/default_ipc_factory.h 2014-11-18 19:29:59 +0000
@@ -45,6 +45,7 @@
45class DisplayChanger;45class DisplayChanger;
46class Screencast;46class Screencast;
47class SessionAuthorizer;47class SessionAuthorizer;
48class VsyncProvider;
4849
49class DefaultIpcFactory : public ProtobufIpcFactory50class DefaultIpcFactory : public ProtobufIpcFactory
50{51{
@@ -58,6 +59,7 @@
58 std::shared_ptr<Screencast> const& screencast,59 std::shared_ptr<Screencast> const& screencast,
59 std::shared_ptr<SessionAuthorizer> const& session_authorizer,60 std::shared_ptr<SessionAuthorizer> const& session_authorizer,
60 std::shared_ptr<input::CursorImages> const& cursor_images,61 std::shared_ptr<input::CursorImages> const& cursor_images,
62 std::shared_ptr<VsyncProvider> const& vsync_provider,
61 std::shared_ptr<scene::CoordinateTranslator> const& translator);63 std::shared_ptr<scene::CoordinateTranslator> const& translator);
6264
63 std::shared_ptr<detail::DisplayServer> make_ipc_server(65 std::shared_ptr<detail::DisplayServer> make_ipc_server(
@@ -76,7 +78,8 @@
76 std::shared_ptr<EventSink> const& sink,78 std::shared_ptr<EventSink> const& sink,
77 std::shared_ptr<Screencast> const& effective_screencast,79 std::shared_ptr<Screencast> const& effective_screencast,
78 ConnectionContext const& connection_context,80 ConnectionContext const& connection_context,
79 std::shared_ptr<input::CursorImages> const& cursor_images);81 std::shared_ptr<input::CursorImages> const& cursor_images,
82 std::shared_ptr<VsyncProvider> const& vsync_provider);
8083
81private:84private:
82 std::shared_ptr<Shell> const shell;85 std::shared_ptr<Shell> const shell;
@@ -89,6 +92,7 @@
89 std::shared_ptr<Screencast> const screencast;92 std::shared_ptr<Screencast> const screencast;
90 std::shared_ptr<SessionAuthorizer> const session_authorizer;93 std::shared_ptr<SessionAuthorizer> const session_authorizer;
91 std::shared_ptr<input::CursorImages> const cursor_images;94 std::shared_ptr<input::CursorImages> const cursor_images;
95 std::shared_ptr<frontend::VsyncProvider> const vsync_provider;
92 std::shared_ptr<scene::CoordinateTranslator> const translator;96 std::shared_ptr<scene::CoordinateTranslator> const translator;
93};97};
94}98}
9599
=== modified file 'src/server/frontend/session_mediator.cpp'
--- src/server/frontend/session_mediator.cpp 2014-11-18 03:21:20 +0000
+++ src/server/frontend/session_mediator.cpp 2014-11-18 19:29:59 +0000
@@ -41,6 +41,7 @@
41#include "mir/frontend/event_sink.h"41#include "mir/frontend/event_sink.h"
42#include "mir/frontend/screencast.h"42#include "mir/frontend/screencast.h"
43#include "mir/frontend/prompt_session.h"43#include "mir/frontend/prompt_session.h"
44#include "mir/frontend/vsync_provider.h"
44#include "mir/scene/prompt_session_creation_parameters.h"45#include "mir/scene/prompt_session_creation_parameters.h"
45#include "mir/fd.h"46#include "mir/fd.h"
4647
@@ -74,6 +75,7 @@
74 std::shared_ptr<Screencast> const& screencast,75 std::shared_ptr<Screencast> const& screencast,
75 ConnectionContext const& connection_context,76 ConnectionContext const& connection_context,
76 std::shared_ptr<mi::CursorImages> const& cursor_images,77 std::shared_ptr<mi::CursorImages> const& cursor_images,
78 std::shared_ptr<mf::VsyncProvider> const& vsync_provider,
77 std::shared_ptr<scene::CoordinateTranslator> const& translator) :79 std::shared_ptr<scene::CoordinateTranslator> const& translator) :
78 client_pid_(0),80 client_pid_(0),
79 shell(shell),81 shell(shell),
@@ -86,6 +88,7 @@
86 screencast(screencast),88 screencast(screencast),
87 connection_context(connection_context),89 connection_context(connection_context),
88 cursor_images(cursor_images),90 cursor_images(cursor_images),
91 vsync_provider(vsync_provider),
89 translator{translator},92 translator{translator},
90 surface_tracker{static_cast<size_t>(client_buffer_cache_size)}93 surface_tracker{static_cast<size_t>(client_buffer_cache_size)}
91{94{
@@ -671,6 +674,11 @@
671{674{
672 protobuf_buffer.set_buffer_id(graphics_buffer->id().as_value());675 protobuf_buffer.set_buffer_id(graphics_buffer->id().as_value());
673676
677 // TODO: ~racarr Enable MM touch resampling
678 auto vsync_time = vsync_provider->last_vsync_for(mg::DisplayConfigurationOutputId{0});
679 if (vsync_time != std::chrono::nanoseconds::zero())
680 protobuf_buffer.set_vsync_time(vsync_time.count());
681
674 mfd::ProtobufBufferPacker packer{&protobuf_buffer};682 mfd::ProtobufBufferPacker packer{&protobuf_buffer};
675 ipc_operations->pack_buffer(packer, *graphics_buffer, buffer_msg_type);683 ipc_operations->pack_buffer(packer, *graphics_buffer, buffer_msg_type);
676684
677685
=== modified file 'src/server/frontend/session_mediator.h'
--- src/server/frontend/session_mediator.h 2014-11-12 14:07:30 +0000
+++ src/server/frontend/session_mediator.h 2014-11-18 19:29:59 +0000
@@ -63,6 +63,7 @@
63class DisplayChanger;63class DisplayChanger;
64class Screencast;64class Screencast;
65class PromptSession;65class PromptSession;
66class VsyncProvider;
6667
67// SessionMediator relays requests from the client process into the server.68// SessionMediator relays requests from the client process into the server.
68class SessionMediator : public detail::DisplayServer, public mir::protobuf::Debug69class SessionMediator : public detail::DisplayServer, public mir::protobuf::Debug
@@ -80,6 +81,7 @@
80 std::shared_ptr<Screencast> const& screencast,81 std::shared_ptr<Screencast> const& screencast,
81 ConnectionContext const& connection_context,82 ConnectionContext const& connection_context,
82 std::shared_ptr<input::CursorImages> const& cursor_images,83 std::shared_ptr<input::CursorImages> const& cursor_images,
84 std::shared_ptr<VsyncProvider> const& vsync_provider,
83 std::shared_ptr<scene::CoordinateTranslator> const& translator);85 std::shared_ptr<scene::CoordinateTranslator> const& translator);
8486
85 ~SessionMediator() noexcept;87 ~SessionMediator() noexcept;
@@ -203,6 +205,7 @@
203 std::shared_ptr<Screencast> const screencast;205 std::shared_ptr<Screencast> const screencast;
204 ConnectionContext const connection_context;206 ConnectionContext const connection_context;
205 std::shared_ptr<input::CursorImages> const cursor_images;207 std::shared_ptr<input::CursorImages> const cursor_images;
208 std::shared_ptr<frontend::VsyncProvider> const vsync_provider;
206 std::shared_ptr<scene::CoordinateTranslator> const translator;209 std::shared_ptr<scene::CoordinateTranslator> const translator;
207210
208 SurfaceTracker surface_tracker;211 SurfaceTracker surface_tracker;
209212
=== modified file 'src/server/graphics/nested/CMakeLists.txt'
--- src/server/graphics/nested/CMakeLists.txt 2014-10-01 06:25:56 +0000
+++ src/server/graphics/nested/CMakeLists.txt 2014-11-18 19:29:59 +0000
@@ -9,6 +9,7 @@
9 nested_display_configuration.cpp9 nested_display_configuration.cpp
10 nested_output.cpp10 nested_output.cpp
11 nested_platform.cpp11 nested_platform.cpp
12 nested_vsync_provider.cpp
12 mir_client_host_connection.cpp13 mir_client_host_connection.cpp
13)14)
1415
1516
=== modified file 'src/server/graphics/nested/host_connection.h'
--- src/server/graphics/nested/host_connection.h 2014-04-24 08:42:12 +0000
+++ src/server/graphics/nested/host_connection.h 2014-11-18 19:29:59 +0000
@@ -24,6 +24,7 @@
24#include <memory>24#include <memory>
25#include <vector>25#include <vector>
26#include <functional>26#include <functional>
27#include <chrono>
2728
28#include <EGL/egl.h>29#include <EGL/egl.h>
2930
@@ -43,6 +44,8 @@
4344
44 virtual EGLNativeWindowType egl_native_window() = 0;45 virtual EGLNativeWindowType egl_native_window() = 0;
45 virtual void set_event_handler(MirEventDelegate const* handler) = 0;46 virtual void set_event_handler(MirEventDelegate const* handler) = 0;
47
48 virtual std::chrono::nanoseconds last_display_time() = 0;
4649
47protected:50protected:
48 HostSurface() = default;51 HostSurface() = default;
4952
=== modified file 'src/server/graphics/nested/mir_client_host_connection.cpp'
--- src/server/graphics/nested/mir_client_host_connection.cpp 2014-10-01 06:25:56 +0000
+++ src/server/graphics/nested/mir_client_host_connection.cpp 2014-11-18 19:29:59 +0000
@@ -77,6 +77,11 @@
77 {77 {
78 mir_surface_set_event_handler(mir_surface, handler);78 mir_surface_set_event_handler(mir_surface, handler);
79 }79 }
80
81 std::chrono::nanoseconds last_display_time() override
82 {
83 return std::chrono::nanoseconds(mir_surface_get_last_display_time(mir_surface));
84 }
8085
81private:86private:
82 MirSurface* const mir_surface;87 MirSurface* const mir_surface;
8388
=== modified file 'src/server/graphics/nested/nested_display.cpp'
--- src/server/graphics/nested/nested_display.cpp 2014-10-01 06:25:56 +0000
+++ src/server/graphics/nested/nested_display.cpp 2014-11-18 19:29:59 +0000
@@ -19,6 +19,7 @@
19#include "nested_display.h"19#include "nested_display.h"
20#include "nested_display_configuration.h"20#include "nested_display_configuration.h"
21#include "nested_output.h"21#include "nested_output.h"
22#include "nested_vsync_provider.h"
22#include "host_connection.h"23#include "host_connection.h"
2324
24#include "mir/geometry/rectangle.h"25#include "mir/geometry/rectangle.h"
@@ -34,6 +35,7 @@
3435
35namespace mg = mir::graphics;36namespace mg = mir::graphics;
36namespace mgn = mir::graphics::nested;37namespace mgn = mir::graphics::nested;
38namespace mf = mir::frontend;
37namespace geom = mir::geometry;39namespace geom = mir::geometry;
3840
39EGLint const mgn::detail::nested_egl_context_attribs[] =41EGLint const mgn::detail::nested_egl_context_attribs[] =
@@ -131,6 +133,7 @@
131 dispatcher{dispatcher},133 dispatcher{dispatcher},
132 display_report{display_report},134 display_report{display_report},
133 egl_display{connection->egl_native_display(), gl_config},135 egl_display{connection->egl_native_display(), gl_config},
136 vsync_provider_(std::make_shared<mgn::VsyncProvider>()),
134 outputs{}137 outputs{}
135{138{
136 std::shared_ptr<DisplayConfiguration> conf(configuration());139 std::shared_ptr<DisplayConfiguration> conf(configuration());
@@ -211,7 +214,7 @@
211 host_surface,214 host_surface,
212 area,215 area,
213 dispatcher,216 dispatcher,
214 output.current_format);217 output.current_format, vsync_provider_, output.id);
215 have_output_for_group = true;218 have_output_for_group = true;
216 }219 }
217 });220 });
@@ -267,3 +270,8 @@
267{270{
268 return std::unique_ptr<mg::GLContext>{new SurfacelessEGLContext(egl_display, EGL_NO_CONTEXT)};271 return std::unique_ptr<mg::GLContext>{new SurfacelessEGLContext(egl_display, EGL_NO_CONTEXT)};
269}272}
273
274std::shared_ptr<mf::VsyncProvider> mgn::NestedDisplay::vsync_provider()
275{
276 return vsync_provider_;
277}
270278
=== modified file 'src/server/graphics/nested/nested_display.h'
--- src/server/graphics/nested/nested_display.h 2014-10-01 06:25:56 +0000
+++ src/server/graphics/nested/nested_display.h 2014-11-18 19:29:59 +0000
@@ -48,6 +48,7 @@
4848
49namespace nested49namespace nested
50{50{
51class VsyncProvider;
51namespace detail52namespace detail
52{53{
5354
@@ -124,6 +125,8 @@
124125
125 std::shared_ptr<Cursor> create_hardware_cursor(std::shared_ptr<CursorImage> const& initial_image) override;126 std::shared_ptr<Cursor> create_hardware_cursor(std::shared_ptr<CursorImage> const& initial_image) override;
126 std::unique_ptr<graphics::GLContext> create_gl_context() override;127 std::unique_ptr<graphics::GLContext> create_gl_context() override;
128
129 std::shared_ptr<frontend::VsyncProvider> vsync_provider() override;
127130
128private:131private:
129 std::shared_ptr<Platform> const platform;132 std::shared_ptr<Platform> const platform;
@@ -131,6 +134,7 @@
131 std::shared_ptr<input::InputDispatcher> const dispatcher;134 std::shared_ptr<input::InputDispatcher> const dispatcher;
132 std::shared_ptr<DisplayReport> const display_report;135 std::shared_ptr<DisplayReport> const display_report;
133 detail::EGLDisplayHandle egl_display;136 detail::EGLDisplayHandle egl_display;
137 std::shared_ptr<VsyncProvider> const vsync_provider_;
134138
135 std::mutex outputs_mutex;139 std::mutex outputs_mutex;
136 std::unordered_map<DisplayConfigurationOutputId, std::shared_ptr<detail::NestedOutput>> outputs;140 std::unordered_map<DisplayConfigurationOutputId, std::shared_ptr<detail::NestedOutput>> outputs;
137141
=== modified file 'src/server/graphics/nested/nested_output.cpp'
--- src/server/graphics/nested/nested_output.cpp 2014-10-01 06:25:56 +0000
+++ src/server/graphics/nested/nested_output.cpp 2014-11-18 19:29:59 +0000
@@ -18,6 +18,8 @@
1818
19#include "nested_output.h"19#include "nested_output.h"
20#include "host_connection.h"20#include "host_connection.h"
21#include "nested_vsync_provider.h"
22
21#include "mir/input/input_dispatcher.h"23#include "mir/input/input_dispatcher.h"
22#include "mir/graphics/pixel_format_utils.h"24#include "mir/graphics/pixel_format_utils.h"
2325
@@ -33,7 +35,9 @@
33 std::shared_ptr<HostSurface> const& host_surface,35 std::shared_ptr<HostSurface> const& host_surface,
34 geometry::Rectangle const& area,36 geometry::Rectangle const& area,
35 std::shared_ptr<input::InputDispatcher> const& dispatcher,37 std::shared_ptr<input::InputDispatcher> const& dispatcher,
36 MirPixelFormat preferred_format) :38 MirPixelFormat preferred_format,
39 std::shared_ptr<mgn::VsyncProvider> const& vsync_provider,
40 mg::DisplayConfigurationOutputId id) :
37 uses_alpha_{mg::contains_alpha(preferred_format)},41 uses_alpha_{mg::contains_alpha(preferred_format)},
38 egl_display(egl_display),42 egl_display(egl_display),
39 host_surface{host_surface},43 host_surface{host_surface},
@@ -41,7 +45,9 @@
41 egl_context{egl_display, eglCreateContext(egl_display, egl_config, egl_display.egl_context(), nested_egl_context_attribs)},45 egl_context{egl_display, eglCreateContext(egl_display, egl_config, egl_display.egl_context(), nested_egl_context_attribs)},
42 area{area.top_left, area.size},46 area{area.top_left, area.size},
43 dispatcher{dispatcher},47 dispatcher{dispatcher},
44 egl_surface{egl_display, host_surface->egl_native_window(), egl_config}48 egl_surface{egl_display, host_surface->egl_native_window(), egl_config},
49 vsync_provider(vsync_provider),
50 id(id)
45{51{
46 MirEventDelegate ed = {event_thunk, this};52 MirEventDelegate ed = {event_thunk, this};
47 host_surface->set_event_handler(&ed);53 host_surface->set_event_handler(&ed);
@@ -66,6 +72,7 @@
66void mgn::detail::NestedOutput::post_update()72void mgn::detail::NestedOutput::post_update()
67{73{
68 eglSwapBuffers(egl_display, egl_surface);74 eglSwapBuffers(egl_display, egl_surface);
75 vsync_provider->notify_of_vsync(id, host_surface->last_display_time());
69}76}
7077
71bool mgn::detail::NestedOutput::post_renderables_if_optimizable(RenderableList const&)78bool mgn::detail::NestedOutput::post_renderables_if_optimizable(RenderableList const&)
7279
=== modified file 'src/server/graphics/nested/nested_output.h'
--- src/server/graphics/nested/nested_output.h 2014-11-03 06:51:26 +0000
+++ src/server/graphics/nested/nested_output.h 2014-11-18 19:29:59 +0000
@@ -21,6 +21,8 @@
2121
22#include "nested_display.h"22#include "nested_display.h"
2323
24#include "mir/graphics/display_configuration.h"
25
24namespace mir26namespace mir
25{27{
26namespace graphics28namespace graphics
@@ -28,6 +30,7 @@
28namespace nested30namespace nested
29{31{
30class HostSurface;32class HostSurface;
33class VsyncProvider;
3134
32namespace detail35namespace detail
33{36{
@@ -40,7 +43,9 @@
40 std::shared_ptr<HostSurface> const& host_surface,43 std::shared_ptr<HostSurface> const& host_surface,
41 geometry::Rectangle const& area,44 geometry::Rectangle const& area,
42 std::shared_ptr<input::InputDispatcher> const& input_dispatcher,45 std::shared_ptr<input::InputDispatcher> const& input_dispatcher,
43 MirPixelFormat preferred_format);46 MirPixelFormat preferred_format,
47 std::shared_ptr<VsyncProvider> const& vsync_provider,
48 DisplayConfigurationOutputId id);
4449
45 ~NestedOutput() noexcept;50 ~NestedOutput() noexcept;
4651
@@ -64,6 +69,9 @@
64 geometry::Rectangle const area;69 geometry::Rectangle const area;
65 std::shared_ptr<input::InputDispatcher> const dispatcher;70 std::shared_ptr<input::InputDispatcher> const dispatcher;
66 EGLSurfaceHandle const egl_surface;71 EGLSurfaceHandle const egl_surface;
72
73 std::shared_ptr<VsyncProvider> const vsync_provider;
74 DisplayConfigurationOutputId id;
6775
68 static void event_thunk(MirSurface* surface, MirEvent const* event, void* context);76 static void event_thunk(MirSurface* surface, MirEvent const* event, void* context);
69 void mir_event(MirEvent const& event);77 void mir_event(MirEvent const& event);
7078
=== modified file 'src/server/graphics/nested/nested_platform.cpp'
--- src/server/graphics/nested/nested_platform.cpp 2014-11-18 09:59:21 +0000
+++ src/server/graphics/nested/nested_platform.cpp 2014-11-18 19:29:59 +0000
@@ -17,6 +17,7 @@
17 */17 */
1818
19#include "nested_platform.h"19#include "nested_platform.h"
20#include "nested_vsync_provider.h"
20#include "host_connection.h"21#include "host_connection.h"
21#include "mir/graphics/nested_context.h"22#include "mir/graphics/nested_context.h"
2223
@@ -24,6 +25,7 @@
2425
25namespace mg = mir::graphics;26namespace mg = mir::graphics;
26namespace mgn = mir::graphics::nested;27namespace mgn = mir::graphics::nested;
28namespace mf = mir::frontend;
2729
28mgn::NestedPlatform::NestedPlatform(30mgn::NestedPlatform::NestedPlatform(
29 std::shared_ptr<HostConnection> const& connection,31 std::shared_ptr<HostConnection> const& connection,
3032
=== added file 'src/server/graphics/nested/nested_vsync_provider.cpp'
--- src/server/graphics/nested/nested_vsync_provider.cpp 1970-01-01 00:00:00 +0000
+++ src/server/graphics/nested/nested_vsync_provider.cpp 2014-11-18 19:29:59 +0000
@@ -0,0 +1,45 @@
1/*
2 * Copyright © 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Robert Carr <robert.carr@canonical.com>
17 */
18
19#include "nested_vsync_provider.h"
20
21#include <boost/throw_exception.hpp>
22#include <stdexcept>
23
24namespace mg = mir::graphics;
25namespace mgn = mg::nested;
26
27void mgn::VsyncProvider::notify_of_vsync(mg::DisplayConfigurationOutputId id, std::chrono::nanoseconds vsync_time)
28{
29 std::lock_guard<std::mutex> lg(last_vsync_guard);
30 last_vsync[id] = vsync_time;
31}
32
33std::chrono::nanoseconds mgn::VsyncProvider::last_vsync_for(mg::DisplayConfigurationOutputId id)
34{
35 std::lock_guard<std::mutex> lg(last_vsync_guard);
36
37 // In this structure we see two flaws of the DisplayConfigurationOutputId mechanism
38 // 1. Failure to find id is not an exception, we may have just not seen a vsync time yet
39 // how do we differentiate without complex integration with display notification changes?
40 // 2. Similarly, how do we know when we are done with an ID?
41 if (last_vsync.find(id) == last_vsync.end())
42 return std::chrono::nanoseconds::zero();
43
44 return last_vsync[id];
45}
046
=== added file 'src/server/graphics/nested/nested_vsync_provider.h'
--- src/server/graphics/nested/nested_vsync_provider.h 1970-01-01 00:00:00 +0000
+++ src/server/graphics/nested/nested_vsync_provider.h 2014-11-18 19:29:59 +0000
@@ -0,0 +1,49 @@
1/*
2 * Copyright © 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Robert Carr <robert.carr@canonical.com>
17 */
18
19#ifndef MIR_GRAPHICS_NESTED_VSYNC_PROVIDER_H_
20#define MIR_GRAPHICS_NESTED_VSYNC_PROVIDER_H_
21
22#include "mir/frontend/vsync_provider.h"
23
24#include <mutex>
25#include <map>
26
27namespace mir
28{
29namespace graphics
30{
31namespace nested
32{
33
34struct VsyncProvider : public frontend::VsyncProvider
35{
36public:
37 void notify_of_vsync(DisplayConfigurationOutputId id, std::chrono::nanoseconds vsync_time);
38 std::chrono::nanoseconds last_vsync_for(DisplayConfigurationOutputId id);
39
40private:
41 std::mutex last_vsync_guard;
42 std::map<DisplayConfigurationOutputId, std::chrono::nanoseconds> last_vsync;
43};
44
45}
46}
47}
48
49#endif // MIR_GRAPHICS_NESTED_VSYNC_PROVIDER_H_
050
=== modified file 'src/server/graphics/offscreen/display.cpp'
--- src/server/graphics/offscreen/display.cpp 2014-10-01 06:25:56 +0000
+++ src/server/graphics/offscreen/display.cpp 2014-11-18 19:29:59 +0000
@@ -20,12 +20,14 @@
20#include "display_buffer.h"20#include "display_buffer.h"
21#include "mir/graphics/basic_platform.h"21#include "mir/graphics/basic_platform.h"
22#include "mir/graphics/display_configuration_policy.h"22#include "mir/graphics/display_configuration_policy.h"
23#include "mir/frontend/vsync_provider.h"
23#include "mir/geometry/size.h"24#include "mir/geometry/size.h"
2425
25#include <boost/throw_exception.hpp>26#include <boost/throw_exception.hpp>
26#include <stdexcept>27#include <stdexcept>
2728
28namespace mg = mir::graphics;29namespace mg = mir::graphics;
30namespace mf = mir::frontend;
29namespace mgo = mg::offscreen;31namespace mgo = mg::offscreen;
30namespace geom = mir::geometry;32namespace geom = mir::geometry;
3133
@@ -173,3 +175,17 @@
173 return std::unique_ptr<GLContext>{175 return std::unique_ptr<GLContext>{
174 new SurfacelessEGLContext{egl_display, egl_context_shared}};176 new SurfacelessEGLContext{egl_display, egl_context_shared}};
175}177}
178
179// Not many examples of needing interactive touch resampling to offscreen outputs
180// so this may never have an implementation...perhaps leaving some code smell.
181std::shared_ptr<mf::VsyncProvider> mgo::Display::vsync_provider()
182{
183 struct NullVsyncProvider : public mf::VsyncProvider
184 {
185 std::chrono::nanoseconds last_vsync_for(graphics::DisplayConfigurationOutputId) override
186 {
187 return std::chrono::nanoseconds::zero();
188 }
189 };
190 return std::make_shared<NullVsyncProvider>();
191}
176192
=== modified file 'src/server/graphics/offscreen/display.h'
--- src/server/graphics/offscreen/display.h 2014-11-03 06:51:26 +0000
+++ src/server/graphics/offscreen/display.h 2014-11-18 19:29:59 +0000
@@ -88,6 +88,8 @@
8888
89 std::shared_ptr<Cursor> create_hardware_cursor(std::shared_ptr<CursorImage> const& initial_image) override;89 std::shared_ptr<Cursor> create_hardware_cursor(std::shared_ptr<CursorImage> const& initial_image) override;
90 std::unique_ptr<GLContext> create_gl_context() override;90 std::unique_ptr<GLContext> create_gl_context() override;
91 std::shared_ptr<frontend::VsyncProvider> vsync_provider() override;
92
9193
92private:94private:
93 std::shared_ptr<BasicPlatform> const basic_platform;95 std::shared_ptr<BasicPlatform> const basic_platform;
9496
=== modified file 'src/server/symbols.map'
--- src/server/symbols.map 2014-11-18 17:26:29 +0000
+++ src/server/symbols.map 2014-11-18 19:29:59 +0000
@@ -103,6 +103,7 @@
103 mir::DefaultServerConfiguration::the_scene*;103 mir::DefaultServerConfiguration::the_scene*;
104 mir::DefaultServerConfiguration::the_scene_report*;104 mir::DefaultServerConfiguration::the_scene_report*;
105 mir::DefaultServerConfiguration::the_screencast*;105 mir::DefaultServerConfiguration::the_screencast*;
106 mir::DefaultServerConfiguration::the_vsync_provider*;
106 mir::DefaultServerConfiguration::the_server_action_queue*;107 mir::DefaultServerConfiguration::the_server_action_queue*;
107 mir::DefaultServerConfiguration::the_server_status_listener*;108 mir::DefaultServerConfiguration::the_server_status_listener*;
108 mir::DefaultServerConfiguration::the_session_authorizer*;109 mir::DefaultServerConfiguration::the_session_authorizer*;
@@ -578,6 +579,7 @@
578 non-virtual?thunk?to?mir::DefaultServerConfiguration::the_scene*;579 non-virtual?thunk?to?mir::DefaultServerConfiguration::the_scene*;
579 non-virtual?thunk?to?mir::DefaultServerConfiguration::the_scene_report*;580 non-virtual?thunk?to?mir::DefaultServerConfiguration::the_scene_report*;
580 non-virtual?thunk?to?mir::DefaultServerConfiguration::the_screencast*;581 non-virtual?thunk?to?mir::DefaultServerConfiguration::the_screencast*;
582 non-virtual?thunk?to?mir::DefaultServerConfiguration::the_vsync_provider*;
581 non-virtual?thunk?to?mir::DefaultServerConfiguration::the_server_action_queue*;583 non-virtual?thunk?to?mir::DefaultServerConfiguration::the_server_action_queue*;
582 non-virtual?thunk?to?mir::DefaultServerConfiguration::the_server_status_listener*;584 non-virtual?thunk?to?mir::DefaultServerConfiguration::the_server_status_listener*;
583 non-virtual?thunk?to?mir::DefaultServerConfiguration::the_session_authorizer*;585 non-virtual?thunk?to?mir::DefaultServerConfiguration::the_session_authorizer*;
584586
=== modified file 'tests/acceptance-tests/test_client_library.cpp'
--- tests/acceptance-tests/test_client_library.cpp 2014-11-11 17:46:49 +0000
+++ tests/acceptance-tests/test_client_library.cpp 2014-11-18 19:29:59 +0000
@@ -146,11 +146,16 @@
146 }146 }
147 }147 }
148};148};
149
150struct ClientLibraryStubbedPlatform : public ClientLibrary
151{
152 mtf::UsingStubClientPlatform using_stub_client_platform;
153};
149}154}
150155
151using namespace testing;156using namespace testing;
152157
153TEST_F(ClientLibrary, client_library_connects_and_disconnects)158TEST_F(ClientLibraryStubbedPlatform, client_library_connects_and_disconnects)
154{159{
155 MirWaitHandle* wh = mir_connect(new_connection().c_str(), __PRETTY_FUNCTION__, connection_callback, this);160 MirWaitHandle* wh = mir_connect(new_connection().c_str(), __PRETTY_FUNCTION__, connection_callback, this);
156 EXPECT_THAT(wh, NotNull());161 EXPECT_THAT(wh, NotNull());
@@ -163,7 +168,7 @@
163 mir_connection_release(connection);168 mir_connection_release(connection);
164}169}
165170
166TEST_F(ClientLibrary, synchronous_connection)171TEST_F(ClientLibraryStubbedPlatform, synchronous_connection)
167{172{
168 connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);173 connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
169174
@@ -174,7 +179,7 @@
174 mir_connection_release(connection);179 mir_connection_release(connection);
175}180}
176181
177TEST_F(ClientLibrary, creates_surface)182TEST_F(ClientLibraryStubbedPlatform, creates_surface)
178{183{
179 mir_wait_for(mir_connect(new_connection().c_str(), __PRETTY_FUNCTION__, connection_callback, this));184 mir_wait_for(mir_connect(new_connection().c_str(), __PRETTY_FUNCTION__, connection_callback, this));
180185
@@ -220,7 +225,7 @@
220 mir_connection_release(connection);225 mir_connection_release(connection);
221}226}
222227
223TEST_F(ClientLibrary, can_set_surface_types)228TEST_F(ClientLibraryStubbedPlatform, can_set_surface_types)
224{229{
225 mir_wait_for(mir_connect(new_connection().c_str(), __PRETTY_FUNCTION__, connection_callback, this));230 mir_wait_for(mir_connect(new_connection().c_str(), __PRETTY_FUNCTION__, connection_callback, this));
226231
@@ -265,7 +270,7 @@
265 mir_connection_release(connection);270 mir_connection_release(connection);
266}271}
267272
268TEST_F(ClientLibrary, can_set_surface_state)273TEST_F(ClientLibraryStubbedPlatform, can_set_surface_state)
269{274{
270 connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);275 connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
271276
@@ -307,7 +312,7 @@
307 mir_connection_release(connection);312 mir_connection_release(connection);
308}313}
309314
310TEST_F(ClientLibrary, receives_surface_dpi_value)315TEST_F(ClientLibraryStubbedPlatform, receives_surface_dpi_value)
311{316{
312 connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);317 connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
313318
@@ -388,7 +393,7 @@
388393
389#ifdef ANDROID394#ifdef ANDROID
390// Mir's Android test infrastructure isn't quite ready for this yet.395// Mir's Android test infrastructure isn't quite ready for this yet.
391TEST_F(ClientLibrary, DISABLED_gets_buffer_dimensions)396TEST_F(ClientLibraryStubbedPlatform, DISABLED_gets_buffer_dimensions)
392#else397#else
393TEST_F(ClientLibrary, gets_buffer_dimensions)398TEST_F(ClientLibrary, gets_buffer_dimensions)
394#endif399#endif
@@ -436,7 +441,7 @@
436 mir_connection_release(connection);441 mir_connection_release(connection);
437}442}
438443
439TEST_F(ClientLibrary, creates_multiple_surfaces)444TEST_F(ClientLibraryStubbedPlatform, creates_multiple_surfaces)
440{445{
441 int const n_surfaces = 13;446 int const n_surfaces = 13;
442 size_t old_surface_count = 0;447 size_t old_surface_count = 0;
@@ -475,7 +480,7 @@
475 mir_connection_release(connection);480 mir_connection_release(connection);
476}481}
477482
478TEST_F(ClientLibrary, client_library_accesses_and_advances_buffers)483TEST_F(ClientLibraryStubbedPlatform, client_library_accesses_and_advances_buffers)
479{484{
480 mir_wait_for(mir_connect(new_connection().c_str(), __PRETTY_FUNCTION__, connection_callback, this));485 mir_wait_for(mir_connect(new_connection().c_str(), __PRETTY_FUNCTION__, connection_callback, this));
481486
@@ -501,7 +506,7 @@
501 mir_connection_release(connection);506 mir_connection_release(connection);
502}507}
503508
504TEST_F(ClientLibrary, fully_synchronous_client)509TEST_F(ClientLibraryStubbedPlatform, fully_synchronous_client)
505{510{
506 connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);511 connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
507512
@@ -527,7 +532,7 @@
527 mir_connection_release(connection);532 mir_connection_release(connection);
528}533}
529534
530TEST_F(ClientLibrary, highly_threaded_client)535TEST_F(ClientLibraryStubbedPlatform, highly_threaded_client)
531{536{
532 connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);537 connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
533538
@@ -560,7 +565,7 @@
560 mir_connection_release(connection);565 mir_connection_release(connection);
561}566}
562567
563TEST_F(ClientLibrary, accesses_platform_package)568TEST_F(ClientLibraryStubbedPlatform, accesses_platform_package)
564{569{
565 mir_wait_for(mir_connect(new_connection().c_str(), __PRETTY_FUNCTION__, connection_callback, this));570 mir_wait_for(mir_connect(new_connection().c_str(), __PRETTY_FUNCTION__, connection_callback, this));
566571
@@ -575,7 +580,7 @@
575 mir_connection_release(connection);580 mir_connection_release(connection);
576}581}
577582
578TEST_F(ClientLibrary, accesses_display_info)583TEST_F(ClientLibraryStubbedPlatform, accesses_display_info)
579{584{
580 mir_wait_for(mir_connect(new_connection().c_str(), __PRETTY_FUNCTION__, connection_callback, this));585 mir_wait_for(mir_connect(new_connection().c_str(), __PRETTY_FUNCTION__, connection_callback, this));
581586
582587
=== modified file 'tests/include/mir_test_doubles/mock_display.h'
--- tests/include/mir_test_doubles/mock_display.h 2014-10-01 06:25:56 +0000
+++ tests/include/mir_test_doubles/mock_display.h 2014-11-18 19:29:59 +0000
@@ -48,6 +48,7 @@
48 MOCK_METHOD0(resume, void());48 MOCK_METHOD0(resume, void());
49 MOCK_METHOD1(create_hardware_cursor, std::shared_ptr<graphics::Cursor>(std::shared_ptr<graphics::CursorImage> const&));49 MOCK_METHOD1(create_hardware_cursor, std::shared_ptr<graphics::Cursor>(std::shared_ptr<graphics::CursorImage> const&));
50 MOCK_METHOD0(create_gl_context, std::unique_ptr<graphics::GLContext>());50 MOCK_METHOD0(create_gl_context, std::unique_ptr<graphics::GLContext>());
51 MOCK_METHOD0(vsync_provider, std::shared_ptr<frontend::VsyncProvider>());
51};52};
5253
53}54}
5455
=== modified file 'tests/include/mir_test_doubles/mock_hwc_vsync_coordinator.h'
--- tests/include/mir_test_doubles/mock_hwc_vsync_coordinator.h 2014-03-06 06:05:17 +0000
+++ tests/include/mir_test_doubles/mock_hwc_vsync_coordinator.h 2014-11-18 19:29:59 +0000
@@ -34,7 +34,9 @@
34{34{
35 ~MockVsyncCoordinator() noexcept {}35 ~MockVsyncCoordinator() noexcept {}
36 MOCK_METHOD0(wait_for_vsync, void());36 MOCK_METHOD0(wait_for_vsync, void());
37 MOCK_METHOD0(notify_vsync, void());37 MOCK_METHOD1(notify_vsync, void(std::chrono::nanoseconds));
38
39 MOCK_METHOD1(last_vsync_for, std::chrono::nanoseconds(graphics::DisplayConfigurationOutputId));
38};40};
3941
4042
4143
=== modified file 'tests/include/mir_test_doubles/null_display.h'
--- tests/include/mir_test_doubles/null_display.h 2014-11-03 06:51:26 +0000
+++ tests/include/mir_test_doubles/null_display.h 2014-11-18 19:29:59 +0000
@@ -66,6 +66,11 @@
66 {66 {
67 return std::unique_ptr<NullGLContext>{new NullGLContext()};67 return std::unique_ptr<NullGLContext>{new NullGLContext()};
68 }68 }
69
70 std::shared_ptr<frontend::VsyncProvider> vsync_provider()
71 {
72 return nullptr;
73 }
69};74};
7075
71}76}
7277
=== modified file 'tests/include/mir_test_doubles/stub_display.h'
--- tests/include/mir_test_doubles/stub_display.h 2014-06-17 11:21:31 +0000
+++ tests/include/mir_test_doubles/stub_display.h 2014-11-18 19:29:59 +0000
@@ -22,6 +22,7 @@
22#include "null_display.h"22#include "null_display.h"
23#include "stub_display_buffer.h"23#include "stub_display_buffer.h"
24#include "stub_display_configuration.h"24#include "stub_display_configuration.h"
25#include "stub_vsync_provider.h"
2526
26#include "mir/geometry/rectangle.h"27#include "mir/geometry/rectangle.h"
2728
@@ -56,6 +57,11 @@
56 new StubDisplayConfig(output_rects)57 new StubDisplayConfig(output_rects)
57 );58 );
58 }59 }
60
61 std::shared_ptr<frontend::VsyncProvider> vsync_provider() override
62 {
63 return std::make_shared<StubVsyncProvider>();
64 }
5965
60private:66private:
61 std::vector<geometry::Rectangle> const output_rects;67 std::vector<geometry::Rectangle> const output_rects;
6268
=== modified file 'tests/include/mir_test_doubles/stub_display_builder.h'
--- tests/include/mir_test_doubles/stub_display_builder.h 2014-10-01 06:25:56 +0000
+++ tests/include/mir_test_doubles/stub_display_builder.h 2014-11-18 19:29:59 +0000
@@ -84,6 +84,11 @@
84 new StubConfigurableDisplayBuffer(geometry::Rectangle{{0,0},sz}));84 new StubConfigurableDisplayBuffer(geometry::Rectangle{{0,0},sz}));
85 }85 }
86 86
87 std::shared_ptr<graphics::android::HWCVsyncCoordinator> vsync_coordinator() const
88 {
89 return nullptr;
90 }
91
87 geometry::Size sz;92 geometry::Size sz;
88};93};
89}94}
9095
=== modified file 'tests/include/mir_test_doubles/stub_host_connection.h'
--- tests/include/mir_test_doubles/stub_host_connection.h 2014-04-23 14:19:34 +0000
+++ tests/include/mir_test_doubles/stub_host_connection.h 2014-11-18 19:29:59 +0000
@@ -55,6 +55,7 @@
55 public:55 public:
56 EGLNativeWindowType egl_native_window() override { return {}; }56 EGLNativeWindowType egl_native_window() override { return {}; }
57 void set_event_handler(MirEventDelegate const*) override {}57 void set_event_handler(MirEventDelegate const*) override {}
58 std::chrono::nanoseconds last_display_time() override { return std::chrono::nanoseconds::min(); }
58 };59 };
5960
60 return std::make_shared<NullHostSurface>();61 return std::make_shared<NullHostSurface>();
6162
=== added file 'tests/include/mir_test_doubles/stub_vsync_provider.h'
--- tests/include/mir_test_doubles/stub_vsync_provider.h 1970-01-01 00:00:00 +0000
+++ tests/include/mir_test_doubles/stub_vsync_provider.h 2014-11-18 19:29:59 +0000
@@ -0,0 +1,43 @@
1/*
2 * Copyright © 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Robert Carr <robert.carr@canonical.com>
17 */
18
19#ifndef MIR_TEST_DOUBLES_STUB_VSYNC_PROVIDER_H_
20#define MIR_TEST_DOUBLES_STUB_VSYNC_PROVIDER_H_
21
22#include "mir/frontend/vsync_provider.h"
23
24namespace mir
25{
26namespace test
27{
28namespace doubles
29{
30
31struct StubVsyncProvider : public frontend::VsyncProvider
32{
33 std::chrono::nanoseconds last_vsync_for(graphics::DisplayConfigurationOutputId) override
34 {
35 return std::chrono::nanoseconds::zero();
36 }
37};
38
39}
40}
41}
42
43#endif // MIR_TEST_DOUBLES_STUB_VSYNC_PROVIDER_H_
044
=== modified file 'tests/include/mir_test_framework/using_stub_client_platform.h'
--- tests/include/mir_test_framework/using_stub_client_platform.h 2014-11-11 15:50:11 +0000
+++ tests/include/mir_test_framework/using_stub_client_platform.h 2014-11-18 19:29:59 +0000
@@ -19,6 +19,8 @@
19#ifndef MIR_TEST_FRAMEWORK_USING_STUB_CLIENT_PLATFORM_H_19#ifndef MIR_TEST_FRAMEWORK_USING_STUB_CLIENT_PLATFORM_H_
20#define MIR_TEST_FRAMEWORK_USING_STUB_CLIENT_PLATFORM_H_20#define MIR_TEST_FRAMEWORK_USING_STUB_CLIENT_PLATFORM_H_
2121
22#include "src/client/connection_configuration.h"
23
22#include <memory>24#include <memory>
23#include <functional>25#include <functional>
2426
2527
=== modified file 'tests/integration-tests/CMakeLists.txt'
--- tests/integration-tests/CMakeLists.txt 2014-11-18 03:21:20 +0000
+++ tests/integration-tests/CMakeLists.txt 2014-11-18 19:29:59 +0000
@@ -33,6 +33,7 @@
33 test_server_shutdown.cpp33 test_server_shutdown.cpp
34 test_session_manager.cpp34 test_session_manager.cpp
35 test_session.cpp35 test_session.cpp
36 test_vsync_to_client.cpp
36 session_management.cpp37 session_management.cpp
37 surface_composition.cpp38 surface_composition.cpp
38 ${GENERATED_PROTOBUF_SRCS}39 ${GENERATED_PROTOBUF_SRCS}
3940
=== modified file 'tests/integration-tests/graphics/android/test_display_integration.cpp'
--- tests/integration-tests/graphics/android/test_display_integration.cpp 2014-10-21 16:21:14 +0000
+++ tests/integration-tests/graphics/android/test_display_integration.cpp 2014-11-18 19:29:59 +0000
@@ -22,6 +22,7 @@
22#include "src/platform/graphics/android/resource_factory.h"22#include "src/platform/graphics/android/resource_factory.h"
23#include "src/platform/graphics/android/android_graphic_buffer_allocator.h"23#include "src/platform/graphics/android/android_graphic_buffer_allocator.h"
24#include "src/platform/graphics/android/output_builder.h"24#include "src/platform/graphics/android/output_builder.h"
25#include "src/platform/graphics/android/hwc_vsync.h"
25#include "src/server/graphics/program_factory.h"26#include "src/server/graphics/program_factory.h"
26#include "src/server/report/null_report_factory.h"27#include "src/server/report/null_report_factory.h"
2728
2829
=== modified file 'tests/integration-tests/test_surfaceloop.cpp'
--- tests/integration-tests/test_surfaceloop.cpp 2014-10-21 16:21:14 +0000
+++ tests/integration-tests/test_surfaceloop.cpp 2014-11-18 19:29:59 +0000
@@ -23,6 +23,7 @@
23#include "mir_test_doubles/null_platform.h"23#include "mir_test_doubles/null_platform.h"
24#include "mir_test_doubles/null_display.h"24#include "mir_test_doubles/null_display.h"
25#include "mir_test_doubles/stub_display_buffer.h"25#include "mir_test_doubles/stub_display_buffer.h"
26#include "mir_test_doubles/stub_vsync_provider.h"
2627
27#include "mir_test_framework/stubbed_server_configuration.h"28#include "mir_test_framework/stubbed_server_configuration.h"
28#include "mir_test_framework/basic_client_server_fixture.h"29#include "mir_test_framework/basic_client_server_fixture.h"
@@ -85,6 +86,12 @@
85 f(display_buffer);86 f(display_buffer);
86 }87 }
8788
89 std::shared_ptr<mf::VsyncProvider> vsync_provider() override
90 {
91 return std::make_shared<mtd::StubVsyncProvider>();
92 }
93
94
88private:95private:
89 mtd::StubDisplayBuffer display_buffer;96 mtd::StubDisplayBuffer display_buffer;
90};97};
9198
=== added file 'tests/integration-tests/test_vsync_to_client.cpp'
--- tests/integration-tests/test_vsync_to_client.cpp 1970-01-01 00:00:00 +0000
+++ tests/integration-tests/test_vsync_to_client.cpp 2014-11-18 19:29:59 +0000
@@ -0,0 +1,225 @@
1/*
2 * Copyright © 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Robert Carr <robert.carr@canonical.com>
17 */
18
19#include "mir/frontend/vsync_provider.h"
20#include "mir/graphics/display_configuration.h"
21#include "mir/input/input_platform.h"
22#include "mir/input/input_receiver_thread.h"
23
24#include "mir_toolkit/mir_client_library.h"
25
26#include "mir_test/fake_shared.h"
27#include "mir_test_framework/in_process_server.h"
28#include "mir_test_framework/stubbed_server_configuration.h"
29#include "mir_test_framework/stub_client_connection_configuration.h"
30#include "mir_test_framework/using_stub_client_platform.h"
31
32namespace mg = mir::graphics;
33namespace mi = mir::input;
34namespace mf = mir::frontend;
35namespace mircv = mi::receiver;
36namespace mt = mir::test;
37namespace mtf = mir_test_framework;
38
39namespace
40{
41// Client mocks and configuration
42struct MockInputReceiverThread : public mircv::InputReceiverThread
43{
44 MOCK_METHOD1(notify_of_frame_time, void(std::chrono::nanoseconds));
45 // Stub of uninteresting methods
46 void start() override {}
47 void stop() override {}
48 void join() override {}
49};
50
51struct MockInputThreadInputPlatform : public mircv::InputPlatform
52{
53 MockInputThreadInputPlatform(std::shared_ptr<mircv::InputReceiverThread> const& receiver_thread)
54 : mock_receiver_thread(receiver_thread)
55 {
56 }
57 std::shared_ptr<mircv::InputReceiverThread> create_input_thread(int,
58 std::function<void(MirEvent *)> const&) override
59 {
60 return mock_receiver_thread;
61 }
62
63 std::shared_ptr<mircv::InputReceiverThread> const mock_receiver_thread;
64};
65
66struct InputMockInjectingClientConnectionConfiguration : public mtf::StubConnectionConfiguration
67{
68 InputMockInjectingClientConnectionConfiguration(std::string const& socket_file, std::shared_ptr<mircv::InputReceiverThread> const& receiver_thread)
69 : StubConnectionConfiguration(socket_file),
70 mock_input_platform(std::make_shared<MockInputThreadInputPlatform>(receiver_thread))
71 {
72 }
73
74 std::shared_ptr<mircv::InputPlatform> the_input_platform() override
75 {
76 return input_platform(
77 [this]
78 {
79 return mock_input_platform;
80 });
81 }
82 std::shared_ptr<MockInputThreadInputPlatform> const mock_input_platform;
83};
84
85// Server mocks and configuration
86struct StubVsyncProvider : public mf::VsyncProvider
87{
88 StubVsyncProvider()
89 : count(0)
90 {
91 }
92
93 std::chrono::nanoseconds last_vsync_for(mg::DisplayConfigurationOutputId) override
94 {
95 return std::chrono::nanoseconds(count++);
96 }
97 int count;
98};
99
100struct StubVsyncProviderServerConfiguration : mtf::StubbedServerConfiguration
101{
102 std::shared_ptr<mf::VsyncProvider>
103 the_vsync_provider() override
104 {
105 return vsync_provider([]()
106 {
107 return std::make_shared<StubVsyncProvider>();
108 });
109 }
110
111 std::shared_ptr<mi::InputManager> the_input_manager()
112 {
113 return DefaultServerConfiguration::the_input_manager();
114 }
115 std::shared_ptr<mi::InputSender> the_input_sender()
116 {
117 return DefaultServerConfiguration::the_input_sender();
118 }
119 std::shared_ptr<mi::InputDispatcher> the_input_dispatcher()
120 {
121 return DefaultServerConfiguration::the_input_dispatcher();
122 }
123};
124
125
126struct VsyncProviderTest : mtf::InProcessServer
127{
128 StubVsyncProviderServerConfiguration server_configuration;
129
130 mir::DefaultServerConfiguration& server_config() override { return server_configuration; }
131};
132
133}
134
135TEST_F(VsyncProviderTest, last_display_time)
136{
137 using namespace ::testing;
138
139 mtf::UsingStubClientPlatform using_stub_client_platform;
140
141 auto connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
142 MirSurfaceParameters const request_params =
143 {
144 __PRETTY_FUNCTION__,
145 640, 480,
146 mir_pixel_format_abgr_8888,
147 mir_buffer_usage_hardware,
148 mir_display_output_id_invalid
149 };
150 auto surface = mir_connection_create_surface_sync(connection, &request_params);
151 EXPECT_EQ(true, mir_surface_is_valid(surface));
152
153 // The fake vsync provider on server just increments an integer
154 // for each vsync request.
155 mir_surface_swap_buffers_sync(surface);
156 EXPECT_EQ(1, mir_surface_get_last_display_time(surface));
157 mir_surface_swap_buffers_sync(surface);
158 EXPECT_EQ(2, mir_surface_get_last_display_time(surface));
159 mir_surface_swap_buffers_sync(surface);
160 EXPECT_EQ(3, mir_surface_get_last_display_time(surface));
161
162 mir_surface_release_sync(surface);
163 mir_connection_release(connection);
164}
165
166namespace
167{
168void ignore_event(MirSurface*, MirEvent const*, void*)
169{
170}
171struct StubConfiguration : public InputMockInjectingClientConnectionConfiguration
172{
173 StubConfiguration(std::string const& socket_file)
174 : InputMockInjectingClientConnectionConfiguration(socket_file, mock_input_receiver_thread)
175 {
176 }
177 ~StubConfiguration()
178 {
179 mock_input_receiver_thread.reset();
180 }
181
182 static std::shared_ptr<MockInputReceiverThread> mock_input_receiver_thread;
183};
184
185std::shared_ptr<MockInputReceiverThread> StubConfiguration::mock_input_receiver_thread;
186}
187
188TEST_F(VsyncProviderTest, client_input_thread_receives_information_from_server_vsync_provider_on_buffer_swap)
189{
190 using namespace ::testing;
191
192 StubConfiguration::mock_input_receiver_thread = std::make_shared<MockInputReceiverThread>();
193
194 mtf::UsingClientPlatform<StubConfiguration> using_stub_client_platform;
195 MirEventDelegate delegate{ignore_event, NULL};
196
197 {
198 InSequence seq;
199 // The fake vsync provider just uses increments for each vsync request.
200 EXPECT_CALL(*StubConfiguration::mock_input_receiver_thread, notify_of_frame_time(std::chrono::nanoseconds(1)));
201 EXPECT_CALL(*StubConfiguration::mock_input_receiver_thread, notify_of_frame_time(std::chrono::nanoseconds(2)));
202 EXPECT_CALL(*StubConfiguration::mock_input_receiver_thread, notify_of_frame_time(std::chrono::nanoseconds(3)));
203 }
204
205 auto connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
206 MirSurfaceParameters const request_params =
207 {
208 __PRETTY_FUNCTION__,
209 640, 480,
210 mir_pixel_format_abgr_8888,
211 mir_buffer_usage_hardware,
212 mir_display_output_id_invalid
213 };
214 auto surface = mir_connection_create_surface_sync(connection, &request_params);
215
216 // Without a handler the client input thread will not be started.
217 mir_surface_set_event_handler(surface, &delegate);
218
219 mir_surface_swap_buffers_sync(surface);
220 mir_surface_swap_buffers_sync(surface);
221 mir_surface_swap_buffers_sync(surface);
222
223 mir_surface_release_sync(surface);
224 mir_connection_release(connection);
225}
0226
=== modified file 'tests/mir_test_framework/stubbed_graphics_platform.cpp'
--- tests/mir_test_framework/stubbed_graphics_platform.cpp 2014-11-13 16:41:26 +0000
+++ tests/mir_test_framework/stubbed_graphics_platform.cpp 2014-11-18 19:29:59 +0000
@@ -23,6 +23,7 @@
2323
24#include "mir_test_doubles/stub_buffer_allocator.h"24#include "mir_test_doubles/stub_buffer_allocator.h"
25#include "mir_test_doubles/stub_display.h"25#include "mir_test_doubles/stub_display.h"
26#include "mir_test_doubles/stub_vsync_provider.h"
2627
27#ifdef ANDROID28#ifdef ANDROID
28#include "mir_test_doubles/stub_android_native_buffer.h"29#include "mir_test_doubles/stub_android_native_buffer.h"
@@ -37,6 +38,7 @@
37#include <boost/throw_exception.hpp>38#include <boost/throw_exception.hpp>
3839
39namespace geom = mir::geometry;40namespace geom = mir::geometry;
41namespace mf = mir::frontend;
40namespace mg = mir::graphics;42namespace mg = mir::graphics;
41namespace mo = mir::options;43namespace mo = mir::options;
42namespace mtd = mir::test::doubles;44namespace mtd = mir::test::doubles;
4345
=== modified file 'tests/unit-tests/client/input/test_android_input_receiver.cpp'
--- tests/unit-tests/client/input/test_android_input_receiver.cpp 2014-10-21 16:21:14 +0000
+++ tests/unit-tests/client/input/test_android_input_receiver.cpp 2014-11-18 19:29:59 +0000
@@ -204,102 +204,6 @@
204 EXPECT_FALSE(receiver.next_event(std::chrono::milliseconds(1), ev)); // Minimal timeout needed for valgrind204 EXPECT_FALSE(receiver.next_event(std::chrono::milliseconds(1), ev)); // Minimal timeout needed for valgrind
205}205}
206206
207TEST_F(AndroidInputReceiverSetup, slow_raw_input_doesnt_cause_frameskipping)
208{ // Regression test for LP: #1372300
209 using namespace testing;
210 using namespace std::chrono;
211
212 nsecs_t t = 0;
213
214 mircva::InputReceiver receiver(
215 client_fd, std::make_shared<mircv::NullInputReceiverReport>(),
216 [&t](int) { return t; }
217 );
218 TestingInputProducer producer(server_fd);
219
220 nsecs_t const one_millisecond = 1000000ULL;
221 nsecs_t const one_second = 1000 * one_millisecond;
222 nsecs_t const one_frame = one_second / 60;
223
224 MirEvent ev;
225
226 producer.produce_a_motion_event(123, 456, t);
227 producer.produce_a_key_event();
228 flush_channels();
229
230 std::chrono::milliseconds const max_timeout(1000);
231
232 // Key events don't get resampled. Will be reported first.
233 ASSERT_TRUE(receiver.next_event(max_timeout, ev));
234 ASSERT_EQ(mir_event_type_key, ev.type);
235
236 // The motion is still too new. Won't be reported yet, but is batched.
237 auto start = high_resolution_clock::now();
238 ASSERT_FALSE(receiver.next_event(max_timeout, ev));
239 auto end = high_resolution_clock::now();
240 auto duration = end - start;
241
242 // Verify we timed out in under a frame (LP: #1372300)
243 // Sadly using real time as droidinput::Looper doesn't use a mocked clock.
244 ASSERT_LT(duration_cast<nanoseconds>(duration).count(), one_frame);
245
246 // Verify we don't use all the CPU by not sleeping (LP: #1373809)
247 EXPECT_GT(duration_cast<nanoseconds>(duration).count(), one_millisecond);
248
249 // But later in a frame or so, the motion will be reported:
250 t += 2 * one_frame; // Account for the new slower 55Hz event rate
251 ASSERT_TRUE(receiver.next_event(max_timeout, ev));
252 ASSERT_EQ(mir_event_type_motion, ev.type);
253}
254
255TEST_F(AndroidInputReceiverSetup, rendering_does_not_lag_behind_input)
256{
257 using namespace testing;
258
259 nsecs_t t = 0;
260
261 mircva::InputReceiver receiver(
262 client_fd, std::make_shared<mircv::NullInputReceiverReport>(),
263 [&t](int) { return t; }
264 );
265 TestingInputProducer producer(server_fd);
266
267 nsecs_t const one_millisecond = 1000000ULL;
268 nsecs_t const one_second = 1000 * one_millisecond;
269 nsecs_t const device_sample_interval = one_second / 250;
270 nsecs_t const frame_interval = one_second / 60;
271 nsecs_t const gesture_duration = 1 * one_second;
272
273 nsecs_t last_produced = 0;
274 int frames_triggered = 0;
275
276 for (t = 0; t < gesture_duration; t += one_millisecond)
277 {
278 if (!t || t >= (last_produced + device_sample_interval))
279 {
280 last_produced = t;
281 float a = t * M_PI / 1000000.0f;
282 float x = 500.0f * sinf(a);
283 float y = 1000.0f * cosf(a);
284 producer.produce_a_motion_event(x, y, t);
285 flush_channels();
286 }
287
288 MirEvent ev;
289 if (receiver.next_event(std::chrono::milliseconds(0), ev))
290 ++frames_triggered;
291 }
292
293 // If the rendering time resulting from the gesture is longer than the
294 // gesture itself then that's laggy...
295 nsecs_t render_duration = frame_interval * frames_triggered;
296 EXPECT_THAT(render_duration, Le(gesture_duration));
297
298 int average_lag_milliseconds = (render_duration - gesture_duration) /
299 (frames_triggered * one_millisecond);
300 EXPECT_THAT(average_lag_milliseconds, Le(1));
301}
302
303TEST_F(AndroidInputReceiverSetup, input_comes_in_phase_with_rendering)207TEST_F(AndroidInputReceiverSetup, input_comes_in_phase_with_rendering)
304{208{
305 using namespace testing;209 using namespace testing;
306210
=== modified file 'tests/unit-tests/client/test_client_mir_surface.cpp'
--- tests/unit-tests/client/test_client_mir_surface.cpp 2014-10-28 13:59:51 +0000
+++ tests/unit-tests/client/test_client_mir_surface.cpp 2014-11-18 19:29:59 +0000
@@ -289,6 +289,7 @@
289 MOCK_METHOD0(start, void());289 MOCK_METHOD0(start, void());
290 MOCK_METHOD0(stop, void());290 MOCK_METHOD0(stop, void());
291 MOCK_METHOD0(join, void());291 MOCK_METHOD0(join, void());
292 MOCK_METHOD1(notify_of_frame_time, void(std::chrono::nanoseconds));
292};293};
293294
294class TestConnectionConfiguration : public mcl::DefaultConnectionConfiguration295class TestConnectionConfiguration : public mcl::DefaultConnectionConfiguration
295296
=== modified file 'tests/unit-tests/frontend/test_session_mediator.cpp'
--- tests/unit-tests/frontend/test_session_mediator.cpp 2014-11-13 16:41:26 +0000
+++ tests/unit-tests/frontend/test_session_mediator.cpp 2014-11-18 19:29:59 +0000
@@ -42,6 +42,7 @@
42#include "mir_test_doubles/mock_buffer.h"42#include "mir_test_doubles/mock_buffer.h"
43#include "mir_test_doubles/stub_session.h"43#include "mir_test_doubles/stub_session.h"
44#include "mir_test_doubles/stub_display_configuration.h"44#include "mir_test_doubles/stub_display_configuration.h"
45#include "mir_test_doubles/stub_vsync_provider.h"
45#include "mir_test_doubles/stub_buffer_allocator.h"46#include "mir_test_doubles/stub_buffer_allocator.h"
46#include "mir_test_doubles/null_screencast.h"47#include "mir_test_doubles/null_screencast.h"
47#include "mir_test/display_config_matchers.h"48#include "mir_test/display_config_matchers.h"
@@ -205,6 +206,39 @@
205 MOCK_METHOD0(supported_pixel_formats, std::vector<MirPixelFormat>());206 MOCK_METHOD0(supported_pixel_formats, std::vector<MirPixelFormat>());
206};207};
207208
209
210class MockPlatform : public mg::Platform
211{
212 public:
213 MockPlatform(std::shared_ptr<mg::PlatformIpcOperations> const& ipc_ops)
214 {
215 using namespace testing;
216 ON_CALL(*this, create_buffer_allocator())
217 .WillByDefault(Return(std::shared_ptr<mg::GraphicBufferAllocator>()));
218 ON_CALL(*this, create_display(_,_,_))
219 .WillByDefault(Return(std::make_shared<mtd::NullDisplay>()));
220 ON_CALL(*this, make_vsync_provider())
221 .WillByDefault(Return(std::make_shared<mtd::StubVsyncProvider>()));
222 ON_CALL(*this, connection_ipc_package())
223 .WillByDefault(Return(std::make_shared<mg::PlatformIPCPackage>()));
224 ON_CALL(*this, make_ipc_operations())
225 .WillByDefault(Return(ipc_ops));
226 }
227
228 MOCK_METHOD0(create_buffer_allocator, std::shared_ptr<mg::GraphicBufferAllocator>());
229 MOCK_METHOD3(create_display,
230 std::shared_ptr<mg::Display>(
231 std::shared_ptr<mg::DisplayConfigurationPolicy> const&,
232 std::shared_ptr<mg::GLProgramFactory> const&,
233 std::shared_ptr<mg::GLConfig> const&));
234 MOCK_METHOD0(connection_ipc_package, std::shared_ptr<mg::PlatformIPCPackage>());
235 MOCK_METHOD0(create_internal_client, std::shared_ptr<mg::InternalClient>());
236 MOCK_CONST_METHOD0(make_ipc_operations, std::shared_ptr<mg::PlatformIpcOperations>());
237 MOCK_CONST_METHOD0(egl_native_display, EGLNativeDisplayType());
238 MOCK_METHOD0(make_buffer_writer, std::shared_ptr<mg::BufferWriter>());
239 MOCK_METHOD0(make_vsync_provider, std::shared_ptr<mf::VsyncProvider>());
240};
241
208struct StubScreencast : mtd::NullScreencast242struct StubScreencast : mtd::NullScreencast
209{243{
210 std::shared_ptr<mg::Buffer> capture(mf::ScreencastSessionId)244 std::shared_ptr<mg::Buffer> capture(mf::ScreencastSessionId)
@@ -230,7 +264,7 @@
230 shell, mt::fake_shared(mock_ipc_operations), graphics_changer,264 shell, mt::fake_shared(mock_ipc_operations), graphics_changer,
231 surface_pixel_formats, report,265 surface_pixel_formats, report,
232 std::make_shared<mtd::NullEventSink>(),266 std::make_shared<mtd::NullEventSink>(),
233 resource_cache, stub_screencast, &connector, nullptr, nullptr}267 resource_cache, stub_screencast, &connector, nullptr, std::make_shared<mtd::StubVsyncProvider>(), nullptr}
234 {268 {
235 using namespace ::testing;269 using namespace ::testing;
236270
@@ -286,7 +320,9 @@
286 shell, mt::fake_shared(mock_ipc_operations), graphics_changer,320 shell, mt::fake_shared(mock_ipc_operations), graphics_changer,
287 surface_pixel_formats, report,321 surface_pixel_formats, report,
288 std::make_shared<mtd::NullEventSink>(),322 std::make_shared<mtd::NullEventSink>(),
289 resource_cache, stub_screencast, context, nullptr, nullptr};323 resource_cache, stub_screencast, context, nullptr,
324 std::make_shared<mtd::StubVsyncProvider>(), nullptr
325 };
290326
291 EXPECT_THAT(connects_handled_count, Eq(0));327 EXPECT_THAT(connects_handled_count, Eq(0));
292328
@@ -391,7 +427,10 @@
391 surface_pixel_formats, report,427 surface_pixel_formats, report,
392 std::make_shared<mtd::NullEventSink>(),428 std::make_shared<mtd::NullEventSink>(),
393 resource_cache, std::make_shared<mtd::NullScreencast>(),429 resource_cache, std::make_shared<mtd::NullScreencast>(),
394 nullptr, nullptr, nullptr);430 nullptr, nullptr,
431 std::make_shared<mtd::StubVsyncProvider>(), nullptr
432 );
433
395 mediator.connect(nullptr, &connect_parameters, &connection, null_callback.get());434 mediator.connect(nullptr, &connect_parameters, &connection, null_callback.get());
396435
397 EXPECT_THAT(connection.display_configuration(), mt::DisplayConfigMatches(std::cref(config)));436 EXPECT_THAT(connection.display_configuration(), mt::DisplayConfigMatches(std::cref(config)));
@@ -593,7 +632,9 @@
593 surface_pixel_formats, report,632 surface_pixel_formats, report,
594 std::make_shared<mtd::NullEventSink>(), resource_cache,633 std::make_shared<mtd::NullEventSink>(), resource_cache,
595 std::make_shared<mtd::NullScreencast>(),634 std::make_shared<mtd::NullScreencast>(),
596 nullptr, nullptr, nullptr};635 nullptr, nullptr,
636 std::make_shared<mtd::StubVsyncProvider>(), nullptr
637 };
597638
598 mediator.connect(nullptr, &connect_parameters, &connection, null_callback.get());639 mediator.connect(nullptr, &connect_parameters, &connection, null_callback.get());
599640
@@ -846,7 +887,9 @@
846 shell, mt::fake_shared(mock_ipc_operations), graphics_changer,887 shell, mt::fake_shared(mock_ipc_operations), graphics_changer,
847 surface_pixel_formats, report,888 surface_pixel_formats, report,
848 std::make_shared<mtd::NullEventSink>(),889 std::make_shared<mtd::NullEventSink>(),
849 mt::fake_shared(mock_cache), stub_screencast, &connector, nullptr, nullptr};890 mt::fake_shared(mock_cache), stub_screencast, nullptr, nullptr,
891 std::make_shared<mtd::StubVsyncProvider>(), nullptr
892 };
850893
851 mediator.connect(nullptr, &connect_parameters, &connection, null_callback.get());894 mediator.connect(nullptr, &connect_parameters, &connection, null_callback.get());
852 mediator.create_surface(nullptr, &surface_parameters, &surface_response, null_callback.get());895 mediator.create_surface(nullptr, &surface_parameters, &surface_response, null_callback.get());
853896
=== modified file 'tests/unit-tests/graphics/android/CMakeLists.txt'
--- tests/unit-tests/graphics/android/CMakeLists.txt 2014-10-29 18:44:15 +0000
+++ tests/unit-tests/graphics/android/CMakeLists.txt 2014-11-18 19:29:59 +0000
@@ -29,6 +29,7 @@
29 ${CMAKE_CURRENT_SOURCE_DIR}/test_device_detection.cpp29 ${CMAKE_CURRENT_SOURCE_DIR}/test_device_detection.cpp
30 ${CMAKE_CURRENT_SOURCE_DIR}/test_hwc_wrapper.cpp30 ${CMAKE_CURRENT_SOURCE_DIR}/test_hwc_wrapper.cpp
31 ${CMAKE_CURRENT_SOURCE_DIR}/test_hwc_fallback_gl_renderer.cpp31 ${CMAKE_CURRENT_SOURCE_DIR}/test_hwc_fallback_gl_renderer.cpp
32 ${CMAKE_CURRENT_SOURCE_DIR}/test_hwc_vsync.cpp
32 $<TARGET_OBJECTS:mirplatformgraphicsandroidobjects>33 $<TARGET_OBJECTS:mirplatformgraphicsandroidobjects>
33)34)
3435
3536
=== modified file 'tests/unit-tests/graphics/android/test_hwc_common_device.cpp'
--- tests/unit-tests/graphics/android/test_hwc_common_device.cpp 2014-10-01 06:25:56 +0000
+++ tests/unit-tests/graphics/android/test_hwc_common_device.cpp 2014-11-18 19:29:59 +0000
@@ -195,14 +195,16 @@
195 .WillOnce(SaveArg<0>(&callbacks));195 .WillOnce(SaveArg<0>(&callbacks));
196196
197 auto device = make_hwc_device<TypeParam>(this->mock_device, this->mock_fbdev, this->mock_vsync);197 auto device = make_hwc_device<TypeParam>(this->mock_device, this->mock_fbdev, this->mock_vsync);
198
199 int64_t const fake_vsync_timestamp = 17;
198200
199 EXPECT_CALL(*this->mock_vsync, notify_vsync())201 EXPECT_CALL(*this->mock_vsync, notify_vsync(std::chrono::nanoseconds(fake_vsync_timestamp)))
200 .Times(1);202 .Times(1);
201 ASSERT_THAT(callbacks, Ne(nullptr));203 ASSERT_THAT(callbacks, Ne(nullptr));
202 callbacks->hooks.vsync(&callbacks->hooks, 0, 0);204 callbacks->hooks.vsync(&callbacks->hooks, 0, fake_vsync_timestamp);
203205
204 callbacks->self = nullptr;206 callbacks->self = nullptr;
205 callbacks->hooks.vsync(&callbacks->hooks, 0, 0);207 callbacks->hooks.vsync(&callbacks->hooks, 0, fake_vsync_timestamp);
206}208}
207209
208TYPED_TEST(HWCCommon, set_orientation)210TYPED_TEST(HWCCommon, set_orientation)
209211
=== added file 'tests/unit-tests/graphics/android/test_hwc_vsync.cpp'
--- tests/unit-tests/graphics/android/test_hwc_vsync.cpp 1970-01-01 00:00:00 +0000
+++ tests/unit-tests/graphics/android/test_hwc_vsync.cpp 2014-11-18 19:29:59 +0000
@@ -0,0 +1,68 @@
1/*
2 * Copyright © 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Robert Carr <robert.carr@canonical.com>
17 */
18
19#include "src/platform/graphics/android/hwc_vsync.h"
20
21#include "mir/graphics/display_configuration.h"
22
23#include <stdexcept>
24
25#include <gtest/gtest.h>
26#include <gmock/gmock.h>
27
28namespace mg = mir::graphics;
29namespace mga = mg::android;
30
31namespace
32{
33struct HWCVsyncTest : public testing::Test
34{
35 mga::HWCVsync syncer;
36
37 mg::DisplayConfigurationOutputId const output_id{0};
38 mg::DisplayConfigurationOutputId const invalid_output_id{1};
39};
40}
41
42TEST_F(HWCVsyncTest, initially_last_vsync_is_zero)
43{
44 EXPECT_EQ(std::chrono::nanoseconds::zero(), syncer.last_vsync_for(output_id));
45}
46
47// No multimonitor support on android drivers yet so non zero output ID is invalid.
48TEST_F(HWCVsyncTest, throws_exception_on_non_zero_output_id)
49{
50 EXPECT_THROW({
51 syncer.last_vsync_for(invalid_output_id);
52 }, std::runtime_error);
53}
54
55TEST_F(HWCVsyncTest, takes_time_from_last_vsync_notification)
56{
57 std::chrono::nanoseconds first_time{1}, second_time{2};
58
59 EXPECT_EQ(std::chrono::nanoseconds::zero(), syncer.last_vsync_for(output_id));
60
61 syncer.notify_vsync(first_time);
62 EXPECT_EQ(first_time, syncer.last_vsync_for(output_id));
63 EXPECT_EQ(first_time, syncer.last_vsync_for(output_id));
64
65 syncer.notify_vsync(second_time);
66 EXPECT_EQ(second_time, syncer.last_vsync_for(output_id));
67 EXPECT_EQ(second_time, syncer.last_vsync_for(output_id));
68}
069
=== modified file 'tests/unit-tests/graphics/android/test_output_builder.cpp'
--- tests/unit-tests/graphics/android/test_output_builder.cpp 2014-10-27 13:06:48 +0000
+++ tests/unit-tests/graphics/android/test_output_builder.cpp 2014-11-18 19:29:59 +0000
@@ -68,6 +68,7 @@
68 ON_CALL(*this, create_fb_device(_)).WillByDefault(Return(nullptr));68 ON_CALL(*this, create_fb_device(_)).WillByDefault(Return(nullptr));
69 ON_CALL(*this, create_hwc_device(_)).WillByDefault(Return(nullptr));69 ON_CALL(*this, create_hwc_device(_)).WillByDefault(Return(nullptr));
70 ON_CALL(*this, create_hwc_fb_device(_,_)).WillByDefault(Return(nullptr));70 ON_CALL(*this, create_hwc_fb_device(_,_)).WillByDefault(Return(nullptr));
71 ON_CALL(*this, create_vsync_coordinator()).WillByDefault(Return(nullptr));
71 }72 }
7273
73 MOCK_CONST_METHOD0(create_hwc_native_device, std::shared_ptr<hwc_composer_device_1>());74 MOCK_CONST_METHOD0(create_hwc_native_device, std::shared_ptr<hwc_composer_device_1>());
@@ -83,6 +84,7 @@
83 MOCK_CONST_METHOD2(create_hwc_fb_device,84 MOCK_CONST_METHOD2(create_hwc_fb_device,
84 std::shared_ptr<mga::DisplayDevice>(85 std::shared_ptr<mga::DisplayDevice>(
85 std::shared_ptr<mga::HwcWrapper> const&, std::shared_ptr<framebuffer_device_t> const&));86 std::shared_ptr<mga::HwcWrapper> const&, std::shared_ptr<framebuffer_device_t> const&));
87 MOCK_CONST_METHOD0(create_vsync_coordinator, std::shared_ptr<mga::HWCVsyncCoordinator>());
86};88};
8789
88class OutputBuilder : public ::testing::Test90class OutputBuilder : public ::testing::Test
8991
=== modified file 'tests/unit-tests/graphics/android/test_resource_factory.cpp'
--- tests/unit-tests/graphics/android/test_resource_factory.cpp 2014-10-01 06:25:56 +0000
+++ tests/unit-tests/graphics/android/test_resource_factory.cpp 2014-11-18 19:29:59 +0000
@@ -19,13 +19,16 @@
19#include "src/platform/graphics/android/resource_factory.h"19#include "src/platform/graphics/android/resource_factory.h"
20#include "mir_test_doubles/mock_android_hw.h"20#include "mir_test_doubles/mock_android_hw.h"
2121
22#include "mir_test/fake_shared.h"
23
22#include <stdexcept>24#include <stdexcept>
23#include <gmock/gmock.h>25#include <gmock/gmock.h>
24#include <gtest/gtest.h>26#include <gtest/gtest.h>
2527
26namespace mg=mir::graphics;28namespace mg = mir::graphics;
27namespace mga=mir::graphics::android;29namespace mga = mir::graphics::android;
28namespace mtd=mir::test::doubles;30namespace mt = mir::test;
31namespace mtd = mt::doubles;
2932
30struct ResourceFactoryTest : public ::testing::Test33struct ResourceFactoryTest : public ::testing::Test
31{34{
3235
=== modified file 'tests/unit-tests/graphics/nested/test_nested_display.cpp'
--- tests/unit-tests/graphics/nested/test_nested_display.cpp 2014-10-01 06:25:56 +0000
+++ tests/unit-tests/graphics/nested/test_nested_display.cpp 2014-11-18 19:29:59 +0000
@@ -18,6 +18,7 @@
1818
19#include "src/server/graphics/nested/nested_display.h"19#include "src/server/graphics/nested/nested_display.h"
20#include "src/server/graphics/nested/host_connection.h"20#include "src/server/graphics/nested/host_connection.h"
21#include "src/server/graphics/nested/nested_vsync_provider.h"
21#include "src/server/report/null/display_report.h"22#include "src/server/report/null/display_report.h"
22#include "src/server/graphics/default_display_configuration_policy.h"23#include "src/server/graphics/default_display_configuration_policy.h"
23#include "src/server/input/null_input_dispatcher.h"24#include "src/server/input/null_input_dispatcher.h"
2425
=== modified file 'tests/unit-tests/graphics/nested/test_nested_display_buffer.cpp'
--- tests/unit-tests/graphics/nested/test_nested_display_buffer.cpp 2014-06-04 22:09:06 +0000
+++ tests/unit-tests/graphics/nested/test_nested_display_buffer.cpp 2014-11-18 19:29:59 +0000
@@ -19,6 +19,7 @@
1919
20#include "src/server/graphics/nested/nested_output.h"20#include "src/server/graphics/nested/nested_output.h"
21#include "src/server/graphics/nested/host_connection.h"21#include "src/server/graphics/nested/host_connection.h"
22#include "src/server/graphics/nested/nested_vsync_provider.h"
22#include "src/server/input/null_input_dispatcher.h"23#include "src/server/input/null_input_dispatcher.h"
2324
24#include "mir_test_doubles/mock_egl.h"25#include "mir_test_doubles/mock_egl.h"
@@ -29,8 +30,9 @@
29#include <gmock/gmock.h>30#include <gmock/gmock.h>
3031
31namespace geom = mir::geometry;32namespace geom = mir::geometry;
32namespace mgn = mir::graphics::nested;33namespace mg = mir::graphics;
33namespace mgnd = mir::graphics::nested::detail;34namespace mgn = mg::nested;
35namespace mgnd = mgn::detail;
34namespace mi = mir::input;36namespace mi = mir::input;
35namespace mt = mir::test;37namespace mt = mir::test;
36namespace mtd = mir::test::doubles;38namespace mtd = mir::test::doubles;
@@ -40,6 +42,7 @@
40public:42public:
41 EGLNativeWindowType egl_native_window() override { return {}; }43 EGLNativeWindowType egl_native_window() override { return {}; }
42 void set_event_handler(MirEventDelegate const*) override {}44 void set_event_handler(MirEventDelegate const*) override {}
45 std::chrono::nanoseconds last_display_time() override { return std::chrono::nanoseconds::min(); }
43};46};
4447
45struct NestedDisplayBufferTest : testing::Test48struct NestedDisplayBufferTest : testing::Test
@@ -55,6 +58,8 @@
55 mi::NullInputDispatcher null_input_dispatcher;58 mi::NullInputDispatcher null_input_dispatcher;
56 mgnd::EGLDisplayHandle egl_disp_handle;59 mgnd::EGLDisplayHandle egl_disp_handle;
57 geom::Rectangle const default_rect;60 geom::Rectangle const default_rect;
61 mgn::VsyncProvider vsync_provider;
62 mg::DisplayConfigurationOutputId id;
58};63};
5964
60TEST_F(NestedDisplayBufferTest, alpha_enabled_pixel_format_enables_destination_alpha)65TEST_F(NestedDisplayBufferTest, alpha_enabled_pixel_format_enables_destination_alpha)
@@ -64,7 +69,9 @@
64 mt::fake_shared(null_host_surface),69 mt::fake_shared(null_host_surface),
65 default_rect,70 default_rect,
66 mt::fake_shared(null_input_dispatcher),71 mt::fake_shared(null_input_dispatcher),
67 mir_pixel_format_abgr_8888};72 mir_pixel_format_abgr_8888,
73 mt::fake_shared(vsync_provider),
74 id};
6875
69 EXPECT_TRUE(db.uses_alpha());76 EXPECT_TRUE(db.uses_alpha());
70}77}
@@ -76,7 +83,9 @@
76 mt::fake_shared(null_host_surface),83 mt::fake_shared(null_host_surface),
77 default_rect,84 default_rect,
78 mt::fake_shared(null_input_dispatcher),85 mt::fake_shared(null_input_dispatcher),
79 mir_pixel_format_xbgr_8888};86 mir_pixel_format_xbgr_8888,
87 mt::fake_shared(vsync_provider),
88 id};
8089
81 EXPECT_FALSE(db.uses_alpha());90 EXPECT_FALSE(db.uses_alpha());
82}91}

Subscribers

People subscribed via source and target branches