Mir

Merge lp:~kdub/mir/protobuf-exchange-buffer into lp:mir

Proposed by Kevin DuBois
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
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.

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

As per last discussion, I think continuing with any "exchange" semantics is a bad idea. Because it fails to solve our existing performance/parallelism issues (bug 1253868). And to solve those problems requires the elimination of exchange semantics.

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

We discussed this a bit when I wanted to plan out this line of work on the mailing list (https://lists.ubuntu.com/archives/mir-devel/2014-July/000773.html).

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.

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

Looks good.

review: Approve
Revision history for this message
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

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

prereq is in landing queue, moving back to the 'review-please' state

Revision history for this message
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.

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

(1) src/shared/symbols.map additions:
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.

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

(2) Text conflict in tests/unit-tests/frontend/test_session_mediator.cpp
1 conflicts encountered.

Revision history for this message
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.

Revision history for this message
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://code.launchpad.net/~vanvugt/mir/mircommon2/+merge/233310

So once that lands, adding new entries into the main block of symbols.map is correct.

review: Abstain
Revision history for this message
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.

Revision history for this message
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?

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

lgtm

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

I'm still not a fan myself. But we seem to have enough support for top approval...

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

Let's not TA while there are still outstanding questions. Find issues during release is a much bigger pain.

Revision history for this message
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.

Revision history for this message
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.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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+}

Subscribers

People subscribed via source and target branches