Merge lp:~kdub/mir/protobuf-exchange-buffer into lp:mir
- protobuf-exchange-buffer
- Merge into development-branch
Status: | Merged |
---|---|
Approved by: | Cemil Azizoglu |
Approved revision: | no longer in the source branch. |
Merged at revision: | 1910 |
Proposed branch: | lp:~kdub/mir/protobuf-exchange-buffer |
Merge into: | lp:mir |
Prerequisite: | lp:~kdub/mir/frontend-tracking |
Diff against target: |
273 lines (+175/-0) 5 files modified
src/common/protobuf/mir_protobuf.proto (+6/-0) src/common/symbols.map (+19/-0) src/server/frontend/session_mediator.cpp (+30/-0) src/server/frontend/session_mediator.h (+6/-0) tests/unit-tests/frontend/test_session_mediator.cpp (+114/-0) |
To merge this branch: | bzr merge lp:~kdub/mir/protobuf-exchange-buffer |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Cemil Azizoglu (community) | Approve | ||
Andreas Pokorny (community) | Approve | ||
PS Jenkins bot (community) | continuous-integration | Approve | |
Daniel van Vugt | Abstain | ||
Alexandros Frantzis (community) | Approve | ||
Review via email: mp+232728@code.launchpad.net |
Commit message
frontend: add the stubs for the exchange_buffer rpc call
note: this isn't hooked up fully on the server side yet, nor is it used by the client.
Description of the change
frontend: add the stubs for the exchange_buffer rpc call
note: this isn't hooked up fully on the server side yet, nor is it used by the client.
This is just an addition to the protocol, so version number not bumped. I do have to break in a backwards incompatible way for the android platform only in the near future though, will bump then.
PS Jenkins bot (ps-jenkins) wrote : | # |
Daniel van Vugt (vanvugt) wrote : | # |
As per last discussion, I think continuing with any "exchange" semantics is a bad idea. Because it fails to solve our existing performance/
Kevin DuBois (kdub) wrote : | # |
We discussed this a bit when I wanted to plan out this line of work on the mailing list (https:/
Different buffer sending mechanisms are interesting, but in the name of not rewriting the entire system, I'm going with an incremental improvement on what we already have. My goal here is just to send a file descriptor back with the buffer that the client is returning. I don't want to go too far into buffer sending experiments when my goal is only to implement the fencing improvements that are useful to android.
Alexandros Frantzis (afrantzis) wrote : | # |
Looks good.
Kevin DuBois (kdub) wrote : | # |
I blocked the base branch to deal with the lifetimes of the buffers (and their associated ids). Will move to WIP until that is solved
Kevin DuBois (kdub) wrote : | # |
prereq is in landing queue, moving back to the 'review-please' state
Cemil Azizoglu (cemil-azizoglu) wrote : | # |
Since we're messing with symbols map. Have you tested in a sanitary environment (e.g. build mir using sbuild, then build U8 using local debs for mir that you just built), and then installing the packages for testing. This is as opposed to cross-compiling and then "adb push"ing the libraries.
In the past, we've had problems which popped up during release time (big PITA) because we did the latter, but not the former.
Daniel van Vugt (vanvugt) wrote : | # |
(1) src/shared/
RAOF has pointed out to me today that function additions (which are not ABI breaking) need to be represented in new blocks in symbols.map. Because they do not form part of the current ABI, but are part of a future ABI. Confusingly, these new blocks can't be named according to the _next_ ABI either, for reasons RAOF just explained to me. So we need to come up with a naming scheme for new (temporary) symbols.map stanzas that exist until the next ABI break. On the next ABI break everything gets coalesced into a single block again.
Daniel van Vugt (vanvugt) wrote : | # |
(2) Text conflict in tests/unit-
1 conflicts encountered.
Chris Halse Rogers (raof) wrote : | # |
I should probably write up a “proper care and feeding for your versioned DSOs” guide in docs/ :)
It doesn't *break* anything to add symbols to an existing stanza, but you lose one of the benefits of versioning - namely, that you guarantee at load time, rather than symbol resolution time, that your library contains the expected symbols.
Daniel van Vugt (vanvugt) wrote : | # |
Oh, err, my concern is negated by doing a full ABI bump (which we are doing in Mir 0.8 anyway):
https:/
So once that lands, adding new entries into the main block of symbols.map is correct.
Kevin DuBois (kdub) wrote : | # |
So tested qtmir and usc (armhf build) with this change, and both could compile. platform api seems to be failing due to an unrelated header move.
Cemil Azizoglu (cemil-azizoglu) wrote : | # |
> So tested qtmir and usc (armhf build) with this change, and both could
> compile. platform api seems to be failing due to an unrelated header move.
Is it a Mir header move? Should we file a separate bug?
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1894
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Daniel van Vugt (vanvugt) wrote : | # |
I'm still not a fan myself. But we seem to have enough support for top approval...
Cemil Azizoglu (cemil-azizoglu) wrote : | # |
Let's not TA while there are still outstanding questions. Find issues during release is a much bigger pain.
Kevin DuBois (kdub) wrote : | # |
So the failure seen was on trunk because platform api had the mir/client/private headers moved out of an accessible location. This branch does not aggrevate or cause the issue. I can report a bug about the issue.
Cemil Azizoglu (cemil-azizoglu) wrote : | # |
> So the failure seen was on trunk because platform api had the
> mir/client/private headers moved out of an accessible location. This branch
> does not aggrevate or cause the issue. I can report a bug about the issue.
Ok that sounds good.
Preview Diff
1 | === modified file 'src/common/protobuf/mir_protobuf.proto' |
2 | --- src/common/protobuf/mir_protobuf.proto 2014-09-08 04:12:17 +0000 |
3 | +++ src/common/protobuf/mir_protobuf.proto 2014-09-09 20:45:42 +0000 |
4 | @@ -25,6 +25,11 @@ |
5 | required int32 value = 1; |
6 | }; |
7 | |
8 | +message BufferRequest { |
9 | + optional SurfaceId id = 1; |
10 | + optional Buffer buffer = 2; |
11 | +}; |
12 | + |
13 | message Buffer { |
14 | optional int32 buffer_id = 1; |
15 | repeated sint32 fd = 2; |
16 | @@ -221,4 +226,5 @@ |
17 | |
18 | rpc start_prompt_session(PromptSessionParameters) returns (Void); |
19 | rpc stop_prompt_session(Void) returns (Void); |
20 | + rpc exchange_buffer(BufferRequest) returns (Buffer); |
21 | } |
22 | |
23 | === modified file 'src/common/symbols.map' |
24 | --- src/common/symbols.map 2014-09-09 14:04:48 +0000 |
25 | +++ src/common/symbols.map 2014-09-09 20:45:42 +0000 |
26 | @@ -167,6 +167,23 @@ |
27 | mir::protobuf::Buffer::MergeFrom*; |
28 | mir::protobuf::Buffer::MergePartialFromCodedStream*; |
29 | mir::protobuf::Buffer::New*; |
30 | + mir::protobuf::BufferRequest::?BufferRequest*; |
31 | + mir::protobuf::BufferRequest::BufferRequest*; |
32 | + mir::protobuf::BufferRequest::ByteSize*; |
33 | + mir::protobuf::BufferRequest::Clear*; |
34 | + mir::protobuf::BufferRequest::CopyFrom*; |
35 | + mir::protobuf::BufferRequest::default_instance*; |
36 | + mir::protobuf::BufferRequest::descriptor*; |
37 | + mir::protobuf::BufferRequest::GetMetadata*; |
38 | + mir::protobuf::BufferRequest::IsInitialized*; |
39 | + mir::protobuf::BufferRequest::kBufferFieldNumber*; |
40 | + mir::protobuf::BufferRequest::kIdFieldNumber*; |
41 | + mir::protobuf::BufferRequest::MergeFrom*; |
42 | + mir::protobuf::BufferRequest::MergePartialFromCodedStream*; |
43 | + mir::protobuf::BufferRequest::New*; |
44 | + mir::protobuf::BufferRequest::SerializeWithCachedSizes*; |
45 | + mir::protobuf::BufferRequest::SerializeWithCachedSizesToArray*; |
46 | + mir::protobuf::BufferRequest::Swap*; |
47 | mir::protobuf::Buffer::SerializeWithCachedSizes*; |
48 | mir::protobuf::Buffer::SerializeWithCachedSizesToArray*; |
49 | mir::protobuf::Buffer::Swap*; |
50 | @@ -337,6 +354,7 @@ |
51 | mir::protobuf::DisplayServer::disconnect*; |
52 | mir::protobuf::DisplayServer::?DisplayServer*; |
53 | mir::protobuf::DisplayServer::drm_auth_magic*; |
54 | + mir::protobuf::DisplayServer::exchange_buffer*; |
55 | mir::protobuf::DisplayServer::GetDescriptor*; |
56 | mir::protobuf::DisplayServer::GetRequestPrototype*; |
57 | mir::protobuf::DisplayServer::GetResponsePrototype*; |
58 | @@ -357,6 +375,7 @@ |
59 | mir::protobuf::DisplayServer_Stub::?DisplayServer_Stub*; |
60 | mir::protobuf::DisplayServer_Stub::DisplayServer_Stub*; |
61 | mir::protobuf::DisplayServer_Stub::drm_auth_magic*; |
62 | + mir::protobuf::DisplayServer_Stub::exchange_buffer*; |
63 | mir::protobuf::DisplayServer_Stub::new_fds_for_prompt_providers*; |
64 | mir::protobuf::DisplayServer_Stub::next_buffer*; |
65 | mir::protobuf::DisplayServer_Stub::release_screencast*; |
66 | |
67 | === modified file 'src/server/frontend/session_mediator.cpp' |
68 | --- src/server/frontend/session_mediator.cpp 2014-09-08 04:12:17 +0000 |
69 | +++ src/server/frontend/session_mediator.cpp 2014-09-09 20:45:42 +0000 |
70 | @@ -248,6 +248,36 @@ |
71 | }); |
72 | } |
73 | |
74 | +void mf::SessionMediator::exchange_buffer( |
75 | + google::protobuf::RpcController*, |
76 | + mir::protobuf::BufferRequest const* request, |
77 | + mir::protobuf::Buffer* response, |
78 | + google::protobuf::Closure* done) |
79 | +{ |
80 | + mf::SurfaceId const surface_id{request->id().value()}; |
81 | + mg::BufferID const buffer_id{static_cast<uint32_t>(request->buffer().buffer_id())}; |
82 | + |
83 | + auto const lock = std::make_shared<std::unique_lock<std::mutex>>(session_mutex); |
84 | + auto const session = weak_session.lock(); |
85 | + if (!session) |
86 | + BOOST_THROW_EXCEPTION(std::logic_error("Invalid application session")); |
87 | + |
88 | + auto const& surface = session->get_surface(surface_id); |
89 | + surface->swap_buffers( |
90 | + surface_tracker.buffer_from(buffer_id), |
91 | + [this, surface_id, lock, response, done](mg::Buffer* new_buffer) |
92 | + { |
93 | + lock->unlock(); |
94 | + |
95 | + if (surface_tracker.track_buffer(surface_id, new_buffer)) |
96 | + pack_protobuf_buffer(*response, new_buffer, mg::BufferIpcMsgType::update_msg); |
97 | + else |
98 | + pack_protobuf_buffer(*response, new_buffer, mg::BufferIpcMsgType::full_msg); |
99 | + |
100 | + done->Run(); |
101 | + }); |
102 | +} |
103 | + |
104 | void mf::SessionMediator::release_surface( |
105 | google::protobuf::RpcController* /*controller*/, |
106 | const mir::protobuf::SurfaceId* request, |
107 | |
108 | === modified file 'src/server/frontend/session_mediator.h' |
109 | --- src/server/frontend/session_mediator.h 2014-09-08 04:12:17 +0000 |
110 | +++ src/server/frontend/session_mediator.h 2014-09-09 20:45:42 +0000 |
111 | @@ -98,6 +98,12 @@ |
112 | mir::protobuf::Buffer* response, |
113 | google::protobuf::Closure* done) override; |
114 | |
115 | + void exchange_buffer( |
116 | + google::protobuf::RpcController* controller, |
117 | + mir::protobuf::BufferRequest const* request, |
118 | + mir::protobuf::Buffer* response, |
119 | + google::protobuf::Closure* done) override; |
120 | + |
121 | void release_surface(google::protobuf::RpcController* controller, |
122 | const mir::protobuf::SurfaceId*, |
123 | mir::protobuf::Void*, |
124 | |
125 | === modified file 'tests/unit-tests/frontend/test_session_mediator.cpp' |
126 | --- tests/unit-tests/frontend/test_session_mediator.cpp 2014-09-08 04:12:17 +0000 |
127 | +++ tests/unit-tests/frontend/test_session_mediator.cpp 2014-09-09 20:45:42 +0000 |
128 | @@ -112,6 +112,8 @@ |
129 | |
130 | std::shared_ptr<mf::Surface> get_surface(mf::SurfaceId surface) const |
131 | { |
132 | + if (mock_surfaces.find(surface) == mock_surfaces.end()) |
133 | + BOOST_THROW_EXCEPTION(std::logic_error("Invalid SurfaceId")); |
134 | return mock_surfaces.at(surface); |
135 | } |
136 | |
137 | @@ -256,6 +258,7 @@ |
138 | mp::Buffer buffer_response; |
139 | mp::DRMMagic drm_request; |
140 | mp::DRMAuthMagicStatus drm_response; |
141 | + mp::BufferRequest buffer_request; |
142 | }; |
143 | } |
144 | |
145 | @@ -306,6 +309,10 @@ |
146 | }, std::logic_error); |
147 | |
148 | EXPECT_THROW({ |
149 | + mediator.exchange_buffer(nullptr, &buffer_request, &buffer_response, null_callback.get()); |
150 | + }, std::logic_error); |
151 | + |
152 | + EXPECT_THROW({ |
153 | mediator.release_surface(nullptr, &surface_id_request, nullptr, null_callback.get()); |
154 | }, std::logic_error); |
155 | |
156 | @@ -346,6 +353,10 @@ |
157 | }, std::logic_error); |
158 | |
159 | EXPECT_THROW({ |
160 | + mediator.exchange_buffer(nullptr, &buffer_request, &buffer_response, null_callback.get()); |
161 | + }, std::logic_error); |
162 | + |
163 | + EXPECT_THROW({ |
164 | mediator.release_surface(nullptr, &surface_id_request, nullptr, null_callback.get()); |
165 | }, std::logic_error); |
166 | |
167 | @@ -656,3 +667,106 @@ |
168 | |
169 | mediator.disconnect(nullptr, nullptr, nullptr, null_callback.get()); |
170 | } |
171 | + |
172 | +TEST_F(SessionMediator, exchange_buffer) |
173 | +{ |
174 | + using namespace testing; |
175 | + auto const& mock_surface = stubbed_session->mock_surface_at(mf::SurfaceId{0}); |
176 | + mp::Buffer exchanged_buffer; |
177 | + mtd::StubBuffer stub_buffer1; |
178 | + mtd::StubBuffer stub_buffer2; |
179 | + |
180 | + //create |
181 | + Sequence seq; |
182 | + EXPECT_CALL(*mock_surface, swap_buffers(_, _)) |
183 | + .InSequence(seq) |
184 | + .WillOnce(InvokeArgument<1>(&stub_buffer1)); |
185 | + //exchange |
186 | + EXPECT_CALL(*mock_surface, swap_buffers(&stub_buffer1,_)) |
187 | + .InSequence(seq) |
188 | + .WillOnce(InvokeArgument<1>(&stub_buffer2)); |
189 | + |
190 | + mediator.connect(nullptr, &connect_parameters, &connection, null_callback.get()); |
191 | + mediator.create_surface(nullptr, &surface_parameters, &surface_response, null_callback.get()); |
192 | + EXPECT_THAT(surface_response.buffer().buffer_id(), Eq(stub_buffer1.id().as_value())); |
193 | + |
194 | + *buffer_request.mutable_id() = surface_response.id(); |
195 | + buffer_request.mutable_buffer()->set_buffer_id(surface_response.buffer().buffer_id()); |
196 | + mediator.exchange_buffer(nullptr, &buffer_request, &exchanged_buffer, null_callback.get()); |
197 | + EXPECT_THAT(exchanged_buffer.buffer_id(), Eq(stub_buffer2.id().as_value())); |
198 | +} |
199 | + |
200 | +TEST_F(SessionMediator, session_exchange_buffer_sends_minimum_information) |
201 | +{ |
202 | + using namespace testing; |
203 | + mp::Buffer exchanged_buffer; |
204 | + mf::SurfaceId surf_id{0}; |
205 | + mtd::StubBuffer buffer1; |
206 | + mtd::StubBuffer buffer2; |
207 | + auto surface = stubbed_session->mock_surface_at(surf_id); |
208 | + ON_CALL(*surface, swap_buffers(nullptr,_)) |
209 | + .WillByDefault(InvokeArgument<1>(&buffer2)); |
210 | + ON_CALL(*surface, swap_buffers(&buffer1,_)) |
211 | + .WillByDefault(InvokeArgument<1>(&buffer2)); |
212 | + ON_CALL(*surface, swap_buffers(&buffer2,_)) |
213 | + .WillByDefault(InvokeArgument<1>(&buffer1)); |
214 | + |
215 | + //create |
216 | + Sequence seq; |
217 | + EXPECT_CALL(*graphics_platform, fill_buffer_package(_, &buffer2, mg::BufferIpcMsgType::full_msg)) |
218 | + .InSequence(seq); |
219 | + //swap1 |
220 | + EXPECT_CALL(*graphics_platform, fill_buffer_package(_, &buffer1, mg::BufferIpcMsgType::full_msg)) |
221 | + .InSequence(seq); |
222 | + //swap2 |
223 | + EXPECT_CALL(*graphics_platform, fill_buffer_package(_, &buffer2, mg::BufferIpcMsgType::update_msg)) |
224 | + .InSequence(seq); |
225 | + //swap3 |
226 | + EXPECT_CALL(*graphics_platform, fill_buffer_package(_, &buffer1, mg::BufferIpcMsgType::update_msg)) |
227 | + .InSequence(seq); |
228 | + |
229 | + mediator.connect(nullptr, &connect_parameters, &connection, null_callback.get()); |
230 | + |
231 | + mediator.create_surface(nullptr, &surface_parameters, &surface_response, null_callback.get()); |
232 | + *buffer_request.mutable_id() = surface_response.id(); |
233 | + buffer_request.mutable_buffer()->set_buffer_id(surface_response.buffer().buffer_id()); |
234 | + |
235 | + mediator.exchange_buffer(nullptr, &buffer_request, &exchanged_buffer, null_callback.get()); |
236 | + buffer_request.mutable_buffer()->set_buffer_id(exchanged_buffer.buffer_id()); |
237 | + |
238 | + mediator.exchange_buffer(nullptr, &buffer_request, &exchanged_buffer, null_callback.get()); |
239 | + buffer_request.mutable_buffer()->set_buffer_id(exchanged_buffer.buffer_id()); |
240 | + |
241 | + mediator.exchange_buffer(nullptr, &buffer_request, &exchanged_buffer, null_callback.get()); |
242 | + mediator.disconnect(nullptr, nullptr, nullptr, null_callback.get()); |
243 | +} |
244 | + |
245 | +TEST_F(SessionMediator, exchange_buffer_throws_if_client_submits_bad_request) |
246 | +{ |
247 | + using namespace testing; |
248 | + auto const& mock_surface = stubbed_session->mock_surface_at(mf::SurfaceId{0}); |
249 | + mp::Buffer exchanged_buffer; |
250 | + mtd::StubBuffer stub_buffer1; |
251 | + mtd::StubBuffer stub_buffer2; |
252 | + |
253 | + EXPECT_CALL(*mock_surface, swap_buffers(_, _)) |
254 | + .WillOnce(InvokeArgument<1>(&stub_buffer1)); |
255 | + |
256 | + mediator.connect(nullptr, &connect_parameters, &connection, null_callback.get()); |
257 | + mediator.create_surface(nullptr, &surface_parameters, &surface_response, null_callback.get()); |
258 | + EXPECT_THAT(surface_response.buffer().buffer_id(), Eq(stub_buffer1.id().as_value())); |
259 | + |
260 | + *buffer_request.mutable_id() = surface_response.id(); |
261 | + //client doesnt own stub_buffer2 |
262 | + buffer_request.mutable_buffer()->set_buffer_id(stub_buffer2.id().as_value()); |
263 | + EXPECT_THROW({ |
264 | + mediator.exchange_buffer(nullptr, &buffer_request, &exchanged_buffer, null_callback.get()); |
265 | + }, std::logic_error); |
266 | + |
267 | + //client made up its own surface id. |
268 | + buffer_request.mutable_id()->set_value(surface_response.id().value() + 2); |
269 | + buffer_request.mutable_buffer()->set_buffer_id(stub_buffer1.id().as_value()); |
270 | + EXPECT_THROW({ |
271 | + mediator.exchange_buffer(nullptr, &buffer_request, &exchanged_buffer, null_callback.get()); |
272 | + }, std::logic_error); |
273 | +} |
PASSED: Continuous integration, rev:1888 jenkins. qa.ubuntu. com/job/ mir-team- mir-development -branch- ci/2561/ jenkins. qa.ubuntu. com/job/ mir-android- utopic- i386-build/ 1541 jenkins. qa.ubuntu. com/job/ mir-clang- utopic- amd64-build/ 1547 jenkins. qa.ubuntu. com/job/ mir-mediumtests -utopic- touch/1523 jenkins. qa.ubuntu. com/job/ mir-team- mir-development -branch- utopic- amd64-ci/ 1083 jenkins. qa.ubuntu. com/job/ mir-team- mir-development -branch- utopic- amd64-ci/ 1083/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ mir-mediumtests -builder- utopic- armhf/460 jenkins. qa.ubuntu. com/job/ mir-mediumtests -builder- utopic- armhf/460/ artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ mir-mediumtests -runner- mako/2600 s-jenkins. ubuntu- ci:8080/ job/touch- flash-device/ 12387
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/mir- team-mir- development- branch- ci/2561/ rebuild
http://