Merge lp:~kdub/mir/receive-buffers-at-startup into lp:mir
- receive-buffers-at-startup
- Merge into development-branch
Proposed by
Kevin DuBois
Status: | Work in progress |
---|---|
Proposed branch: | lp:~kdub/mir/receive-buffers-at-startup |
Merge into: | lp:mir |
Diff against target: |
726 lines (+253/-55) 22 files modified
include/server/mir/frontend/buffer_stream.h (+4/-1) src/client/buffer_stream.cpp (+44/-8) src/client/buffer_stream.h (+8/-3) src/client/client_buffer_stream_factory.h (+3/-3) src/client/default_client_buffer_stream_factory.cpp (+4/-4) src/client/default_client_buffer_stream_factory.h (+2/-2) src/client/mir_connection.cpp (+2/-2) src/client/mir_connection.h (+2/-1) src/client/mir_screencast.cpp (+1/-1) src/client/mir_surface.cpp (+2/-1) src/protobuf/mir_protobuf.proto (+1/-0) src/server/compositor/buffer_stream_surfaces.cpp (+11/-0) src/server/compositor/buffer_stream_surfaces.h (+2/-0) src/server/frontend/session_mediator.cpp (+41/-12) tests/include/mir/test/doubles/mock_buffer_stream.h (+2/-0) tests/include/mir/test/doubles/mock_client_buffer_stream_factory.h (+6/-6) tests/include/mir/test/doubles/stub_buffer_stream.h (+2/-0) tests/include/mir/test/doubles/stub_client_buffer_stream_factory.h (+4/-2) tests/unit-tests/client/test_client_buffer_stream.cpp (+30/-8) tests/unit-tests/client/test_mir_screencast.cpp (+1/-1) tests/unit-tests/compositor/test_buffer_stream.cpp (+12/-0) tests/unit-tests/frontend/test_session_mediator.cpp (+69/-0) |
To merge this branch: | bzr merge lp:~kdub/mir/receive-buffers-at-startup |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mir development team | Pending | ||
Review via email: mp+265724@code.launchpad.net |
Commit message
client: if not given a mp::Buffer at startup, use the allocate_buffer rpc call to generate buffers.
Description of the change
client: if not given a mp::Buffer at startup, use the allocate_buffer rpc call to generate buffers.
note: imo, mcl::BufferStream needs to be split up and refactored, as its servicing both the exchange/next buffer method and the submit method, as well as a "producer" and "consumer" mode...
To post a comment you must log in.
Unmerged revisions
- 2785. By Kevin DuBois
-
reduce diff
- 2784. By Kevin DuBois
-
round of cleanups
- 2783. By Kevin DuBois
-
tests to pass
- 2782. By Kevin DuBois
-
merge in mir
- 2781. By Kevin DuBois
-
replumb sizes
- 2780. By Kevin DuBois
-
rethink size communication a bit in test
- 2779. By Kevin DuBois
-
add session mediator test to handle a nullptr return
- 2778. By Kevin DuBois
-
round of cleanups
- 2777. By Kevin DuBois
-
another test
- 2776. By Kevin DuBois
-
merge in mir
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'include/server/mir/frontend/buffer_stream.h' |
2 | --- include/server/mir/frontend/buffer_stream.h 2015-06-18 02:46:16 +0000 |
3 | +++ include/server/mir/frontend/buffer_stream.h 2015-07-23 19:11:05 +0000 |
4 | @@ -20,7 +20,7 @@ |
5 | #define MIR_FRONTEND_BUFFER_STREAM_H_ |
6 | |
7 | #include <mir_toolkit/common.h> |
8 | - |
9 | +#include "mir/graphics/buffer_id.h" |
10 | #include <functional> |
11 | #include <memory> |
12 | |
13 | @@ -29,6 +29,7 @@ |
14 | namespace graphics |
15 | { |
16 | class Buffer; |
17 | +class BufferProperties; |
18 | } |
19 | namespace scene |
20 | { |
21 | @@ -53,6 +54,8 @@ |
22 | |
23 | virtual MirPixelFormat pixel_format() const = 0; |
24 | |
25 | + virtual void allocate_buffer(graphics::BufferProperties const&) = 0; |
26 | + virtual void remove_buffer(graphics::BufferID) = 0; |
27 | protected: |
28 | BufferStream() = default; |
29 | BufferStream(BufferStream const&) = delete; |
30 | |
31 | === modified file 'src/client/buffer_stream.cpp' |
32 | --- src/client/buffer_stream.cpp 2015-07-16 07:03:19 +0000 |
33 | +++ src/client/buffer_stream.cpp 2015-07-23 19:11:05 +0000 |
34 | @@ -93,7 +93,8 @@ |
35 | std::shared_ptr<mcl::ClientPlatform> const& client_platform, |
36 | mp::BufferStream const& protobuf_bs, |
37 | std::shared_ptr<mcl::PerfReport> const& perf_report, |
38 | - std::string const& surface_name) |
39 | + std::string const& surface_name, |
40 | + geom::Size ideal_size) |
41 | : connection(connection), |
42 | display_server(server), |
43 | mode(mode), |
44 | @@ -102,7 +103,8 @@ |
45 | buffer_depository{client_platform->create_buffer_factory(), mir::frontend::client_buffer_cache_size}, |
46 | swap_interval_(1), |
47 | perf_report(perf_report), |
48 | - protobuf_void{mcl::make_protobuf_object<mir::protobuf::Void>()} |
49 | + protobuf_void{mcl::make_protobuf_object<mir::protobuf::Void>()}, |
50 | + ideal_buffer_size{ideal_size} |
51 | { |
52 | created(nullptr, nullptr); |
53 | perf_report->name_surface(surface_name.c_str()); |
54 | @@ -124,7 +126,8 @@ |
55 | buffer_depository{client_platform->create_buffer_factory(), mir::frontend::client_buffer_cache_size}, |
56 | swap_interval_(1), |
57 | perf_report(perf_report), |
58 | - protobuf_void{mcl::make_protobuf_object<mir::protobuf::Void>()} |
59 | + protobuf_void{mcl::make_protobuf_object<mir::protobuf::Void>()}, |
60 | + ideal_buffer_size{parameters.width(), parameters.height()} |
61 | { |
62 | perf_report->name_surface(std::to_string(reinterpret_cast<long int>(this)).c_str()); |
63 | |
64 | @@ -146,10 +149,22 @@ |
65 | { |
66 | if (!protobuf_bs->has_id() || protobuf_bs->has_error()) |
67 | BOOST_THROW_EXCEPTION(std::runtime_error("Can not create buffer stream: " + std::string(protobuf_bs->error()))); |
68 | - if (!protobuf_bs->has_buffer()) |
69 | - BOOST_THROW_EXCEPTION(std::runtime_error("Buffer stream did not come with a buffer")); |
70 | - |
71 | - process_buffer(protobuf_bs->buffer()); |
72 | + |
73 | + if (protobuf_bs->has_buffer()) |
74 | + { |
75 | + process_buffer(protobuf_bs->buffer()); |
76 | + finalize_initialization(callback, context); |
77 | + } |
78 | + else |
79 | + { |
80 | + alloc_buffers(); |
81 | + deferred_callback = callback; |
82 | + deferred_context = context; |
83 | + } |
84 | +} |
85 | + |
86 | +void mcl::BufferStream::finalize_initialization(mir_buffer_stream_callback callback, void *context) |
87 | +{ |
88 | egl_native_window_ = client_platform->create_egl_native_window(this); |
89 | |
90 | if (connection) |
91 | @@ -158,10 +173,24 @@ |
92 | if (callback) |
93 | callback(reinterpret_cast<MirBufferStream*>(this), context); |
94 | create_wait_handle.result_received(); |
95 | + was_created = true; |
96 | } |
97 | |
98 | -mcl::BufferStream::~BufferStream() |
99 | +void mcl::BufferStream::alloc_buffers() |
100 | { |
101 | + auto initial_nbuffers = 3u; |
102 | + auto request = mcl::make_protobuf_object<mp::BufferAllocation>(); |
103 | + *request->mutable_id() = protobuf_bs->id(); |
104 | + for(auto i = 0u; i < initial_nbuffers; i++) |
105 | + { |
106 | + auto buf_params = request->add_buffer_requests(); |
107 | + buf_params->set_width(protobuf_bs->buffer().width()); |
108 | + buf_params->set_height(protobuf_bs->buffer().height()); |
109 | + buf_params->set_pixel_format(protobuf_bs->pixel_format()); |
110 | + buf_params->set_buffer_usage(protobuf_bs->buffer_usage()); |
111 | + } |
112 | + display_server.allocate_buffers(nullptr, request.get(), protobuf_void.get(), |
113 | + google::protobuf::NewCallback(google::protobuf::DoNothing)); |
114 | } |
115 | |
116 | void mcl::BufferStream::process_buffer(mp::Buffer const& buffer) |
117 | @@ -421,6 +450,13 @@ |
118 | { |
119 | std::unique_lock<decltype(mutex)> lock(mutex); |
120 | |
121 | + if (!was_created) |
122 | + { |
123 | + process_buffer(buffer, lock); |
124 | + finalize_initialization(deferred_callback, deferred_context); |
125 | + return; |
126 | + } |
127 | + |
128 | if (on_incoming_buffer) |
129 | { |
130 | process_buffer(buffer, lock); |
131 | |
132 | === modified file 'src/client/buffer_stream.h' |
133 | --- src/client/buffer_stream.h 2015-07-16 07:03:19 +0000 |
134 | +++ src/client/buffer_stream.h 2015-07-23 19:11:05 +0000 |
135 | @@ -65,7 +65,8 @@ |
136 | std::shared_ptr<ClientPlatform> const& native_window_factory, |
137 | mir::protobuf::BufferStream const& protobuf_bs, |
138 | std::shared_ptr<PerfReport> const& perf_report, |
139 | - std::string const& surface_name); |
140 | + std::string const& surface_name, |
141 | + geometry::Size ideal_size); |
142 | // For surfaceless buffer streams |
143 | BufferStream( |
144 | MirConnection* connection, |
145 | @@ -76,8 +77,6 @@ |
146 | mir_buffer_stream_callback callback, |
147 | void *context); |
148 | |
149 | - virtual ~BufferStream(); |
150 | - |
151 | MirWaitHandle *get_create_wait_handle() override; |
152 | MirWaitHandle *release(mir_buffer_stream_callback callback, void* context) override; |
153 | |
154 | @@ -114,6 +113,7 @@ |
155 | BufferStream& operator=(BufferStream const&) = delete; |
156 | |
157 | private: |
158 | + void alloc_buffers(); |
159 | void created(mir_buffer_stream_callback callback, void* context); |
160 | void process_buffer(protobuf::Buffer const& buffer); |
161 | void process_buffer(protobuf::Buffer const& buffer, std::unique_lock<std::mutex> const&); |
162 | @@ -122,6 +122,7 @@ |
163 | void on_configured(); |
164 | void release_cpu_region(); |
165 | MirWaitHandle* submit(std::function<void()> const& done, std::unique_lock<std::mutex> lk); |
166 | + void finalize_initialization(mir_buffer_stream_callback callback, void *context); |
167 | |
168 | mutable std::mutex mutex; // Protects all members of *this |
169 | |
170 | @@ -153,6 +154,10 @@ |
171 | std::shared_ptr<MemoryRegion> secured_region; |
172 | |
173 | geometry::Size cached_buffer_size; |
174 | + geometry::Size ideal_buffer_size; |
175 | + bool was_created = false; |
176 | + mir_buffer_stream_callback deferred_callback; |
177 | + void *deferred_context; |
178 | }; |
179 | |
180 | } |
181 | |
182 | === modified file 'src/client/client_buffer_stream_factory.h' |
183 | --- src/client/client_buffer_stream_factory.h 2015-06-18 02:46:16 +0000 |
184 | +++ src/client/client_buffer_stream_factory.h 2015-07-23 19:11:05 +0000 |
185 | @@ -22,7 +22,7 @@ |
186 | #include "mir_protobuf.pb.h" |
187 | |
188 | #include "mir_toolkit/client_types.h" |
189 | - |
190 | +#include "mir/geometry/size.h" |
191 | #include <memory> |
192 | |
193 | class MirConnection; |
194 | @@ -37,10 +37,10 @@ |
195 | public: |
196 | virtual std::shared_ptr<ClientBufferStream> make_consumer_stream( |
197 | MirConnection*, protobuf::DisplayServer& server, |
198 | - protobuf::BufferStream const& protobuf_bs, std::string const& surface_name) = 0; |
199 | + protobuf::BufferStream const& protobuf_bs, std::string const& surface_name, geometry::Size) = 0; |
200 | virtual std::shared_ptr<ClientBufferStream> make_producer_stream( |
201 | MirConnection*, protobuf::DisplayServer& server, |
202 | - protobuf::BufferStream const& protobuf_bs, std::string const& surface_name) = 0; |
203 | + protobuf::BufferStream const& protobuf_bs, std::string const& surface_name, geometry::Size) = 0; |
204 | |
205 | // For creating buffer stream owned by client. |
206 | virtual ClientBufferStream* make_producer_stream( |
207 | |
208 | === modified file 'src/client/default_client_buffer_stream_factory.cpp' |
209 | --- src/client/default_client_buffer_stream_factory.cpp 2015-06-18 02:46:16 +0000 |
210 | +++ src/client/default_client_buffer_stream_factory.cpp 2015-07-23 19:11:05 +0000 |
211 | @@ -59,20 +59,20 @@ |
212 | |
213 | std::shared_ptr<mcl::ClientBufferStream> mcl::DefaultClientBufferStreamFactory::make_consumer_stream( |
214 | MirConnection* connection, mp::DisplayServer& server, |
215 | - mp::BufferStream const& protobuf_bs, std::string const& surface_name) |
216 | + mp::BufferStream const& protobuf_bs, std::string const& surface_name, geometry::Size size) |
217 | { |
218 | return std::make_shared<mcl::BufferStream>( |
219 | connection, server, mcl::BufferStreamMode::Consumer, client_platform, |
220 | - protobuf_bs, make_perf_report(logger), surface_name); |
221 | + protobuf_bs, make_perf_report(logger), surface_name, size); |
222 | } |
223 | |
224 | std::shared_ptr<mcl::ClientBufferStream> mcl::DefaultClientBufferStreamFactory::make_producer_stream( |
225 | MirConnection* connection, mp::DisplayServer& server, |
226 | - mp::BufferStream const& protobuf_bs, std::string const& surface_name) |
227 | + mp::BufferStream const& protobuf_bs, std::string const& surface_name, geometry::Size size) |
228 | { |
229 | return std::make_shared<mcl::BufferStream>( |
230 | connection, server, mcl::BufferStreamMode::Producer, client_platform, |
231 | - protobuf_bs, make_perf_report(logger), surface_name); |
232 | + protobuf_bs, make_perf_report(logger), surface_name, size); |
233 | } |
234 | |
235 | |
236 | |
237 | === modified file 'src/client/default_client_buffer_stream_factory.h' |
238 | --- src/client/default_client_buffer_stream_factory.h 2015-06-18 02:46:16 +0000 |
239 | +++ src/client/default_client_buffer_stream_factory.h 2015-07-23 19:11:05 +0000 |
240 | @@ -42,10 +42,10 @@ |
241 | |
242 | std::shared_ptr<ClientBufferStream> make_consumer_stream( |
243 | MirConnection*, protobuf::DisplayServer& server, |
244 | - protobuf::BufferStream const& protobuf_bs, std::string const& surface_name) override; |
245 | + protobuf::BufferStream const& protobuf_bs, std::string const& surface_name, geometry::Size) override; |
246 | std::shared_ptr<ClientBufferStream> make_producer_stream( |
247 | MirConnection*, protobuf::DisplayServer& server, |
248 | - protobuf::BufferStream const& protobuf_bs, std::string const& surface_name) override; |
249 | + protobuf::BufferStream const& protobuf_bs, std::string const& surface_name, geometry::Size) override; |
250 | |
251 | ClientBufferStream* make_producer_stream( |
252 | MirConnection*, |
253 | |
254 | === modified file 'src/client/mir_connection.cpp' |
255 | --- src/client/mir_connection.cpp 2015-07-14 08:16:46 +0000 |
256 | +++ src/client/mir_connection.cpp 2015-07-23 19:11:05 +0000 |
257 | @@ -505,9 +505,9 @@ |
258 | } |
259 | |
260 | std::shared_ptr<mir::client::ClientBufferStream> MirConnection::make_consumer_stream( |
261 | - mir::protobuf::BufferStream const& protobuf_bs, std::string const& surface_name) |
262 | + mir::protobuf::BufferStream const& protobuf_bs, std::string const& surface_name, mir::geometry::Size size) |
263 | { |
264 | - return buffer_stream_factory->make_consumer_stream(this, server, protobuf_bs, surface_name); |
265 | + return buffer_stream_factory->make_consumer_stream(this, server, protobuf_bs, surface_name, size); |
266 | } |
267 | |
268 | EGLNativeDisplayType MirConnection::egl_native_display() |
269 | |
270 | === modified file 'src/client/mir_connection.h' |
271 | --- src/client/mir_connection.h 2015-07-14 08:16:46 +0000 |
272 | +++ src/client/mir_connection.h 2015-07-23 19:11:05 +0000 |
273 | @@ -30,6 +30,7 @@ |
274 | |
275 | #include "mir_toolkit/mir_client_library.h" |
276 | |
277 | +#include "mir/geometry/size.h" |
278 | #include "mir/client_platform.h" |
279 | #include "mir/client_context.h" |
280 | |
281 | @@ -125,7 +126,7 @@ |
282 | std::shared_ptr<mir::client::ClientPlatform> get_client_platform(); |
283 | |
284 | std::shared_ptr<mir::client::ClientBufferStream> make_consumer_stream( |
285 | - mir::protobuf::BufferStream const& protobuf_bs, std::string const& surface_name); |
286 | + mir::protobuf::BufferStream const& protobuf_bs, std::string const& surface_name, mir::geometry::Size); |
287 | |
288 | mir::client::ClientBufferStream* create_client_buffer_stream( |
289 | int width, int height, |
290 | |
291 | === modified file 'src/client/mir_screencast.cpp' |
292 | --- src/client/mir_screencast.cpp 2015-06-18 02:46:16 +0000 |
293 | +++ src/client/mir_screencast.cpp 2015-07-23 19:11:05 +0000 |
294 | @@ -110,7 +110,7 @@ |
295 | if (!protobuf_screencast->has_error() && connection) |
296 | { |
297 | buffer_stream = connection->make_consumer_stream( |
298 | - protobuf_screencast->buffer_stream(), "MirScreencast"); |
299 | + protobuf_screencast->buffer_stream(), "MirScreencast", output_size); |
300 | } |
301 | |
302 | callback(this, context); |
303 | |
304 | === modified file 'src/client/mir_surface.cpp' |
305 | --- src/client/mir_surface.cpp 2015-07-23 02:39:20 +0000 |
306 | +++ src/client/mir_surface.cpp 2015-07-23 19:11:05 +0000 |
307 | @@ -324,8 +324,9 @@ |
308 | { |
309 | std::lock_guard<decltype(mutex)> lock(mutex); |
310 | |
311 | + geom::Size size{surface->width(), surface->height()}; |
312 | buffer_stream = buffer_stream_factory-> |
313 | - make_producer_stream(connection, *server, surface->buffer_stream(), name); |
314 | + make_producer_stream(connection, *server, surface->buffer_stream(), name, size); |
315 | |
316 | for(int i = 0; i < surface->attributes_size(); i++) |
317 | { |
318 | |
319 | === modified file 'src/protobuf/mir_protobuf.proto' |
320 | --- src/protobuf/mir_protobuf.proto 2015-07-23 02:39:20 +0000 |
321 | +++ src/protobuf/mir_protobuf.proto 2015-07-23 19:11:05 +0000 |
322 | @@ -117,6 +117,7 @@ |
323 | |
324 | message BufferRelease { |
325 | repeated Buffer buffers = 1; |
326 | + optional BufferStreamId id = 2; |
327 | }; |
328 | |
329 | message BufferRequest { |
330 | |
331 | === modified file 'src/server/compositor/buffer_stream_surfaces.cpp' |
332 | --- src/server/compositor/buffer_stream_surfaces.cpp 2015-06-18 14:33:10 +0000 |
333 | +++ src/server/compositor/buffer_stream_surfaces.cpp 2015-07-23 19:11:05 +0000 |
334 | @@ -22,6 +22,7 @@ |
335 | #include "mir/graphics/buffer_properties.h" |
336 | |
337 | #include "temporary_buffers.h" |
338 | +#include <boost/throw_exception.hpp> |
339 | |
340 | namespace mc = mir::compositor; |
341 | namespace mg = mir::graphics; |
342 | @@ -135,3 +136,13 @@ |
343 | if (auto o = observer.lock()) |
344 | observers.remove(o); |
345 | } |
346 | + |
347 | +void mc::BufferStreamSurfaces::allocate_buffer(graphics::BufferProperties const&) |
348 | +{ |
349 | + BOOST_THROW_EXCEPTION(std::runtime_error("not_supported")); |
350 | +} |
351 | + |
352 | +void mc::BufferStreamSurfaces::remove_buffer(graphics::BufferID) |
353 | +{ |
354 | + BOOST_THROW_EXCEPTION(std::runtime_error("not_supported")); |
355 | +} |
356 | |
357 | === modified file 'src/server/compositor/buffer_stream_surfaces.h' |
358 | --- src/server/compositor/buffer_stream_surfaces.h 2015-06-17 05:20:42 +0000 |
359 | +++ src/server/compositor/buffer_stream_surfaces.h 2015-07-23 19:11:05 +0000 |
360 | @@ -47,6 +47,8 @@ |
361 | MirPixelFormat pixel_format() const override; |
362 | void add_observer(std::shared_ptr<scene::SurfaceObserver> const& observer) override; |
363 | void remove_observer(std::weak_ptr<scene::SurfaceObserver> const& observer) override; |
364 | + void allocate_buffer(graphics::BufferProperties const&) override; |
365 | + void remove_buffer(graphics::BufferID) override; |
366 | |
367 | //from mc::BufferStream |
368 | void acquire_client_buffer(std::function<void(graphics::Buffer* buffer)> complete); |
369 | |
370 | === modified file 'src/server/frontend/session_mediator.cpp' |
371 | --- src/server/frontend/session_mediator.cpp 2015-07-23 02:39:20 +0000 |
372 | +++ src/server/frontend/session_mediator.cpp 2015-07-23 19:11:05 +0000 |
373 | @@ -160,6 +160,7 @@ |
374 | old_buffer, |
375 | [this, stream_id, complete](mg::Buffer* new_buffer) |
376 | { |
377 | + if (!new_buffer) return; |
378 | if (buffer_stream_tracker.track_buffer(stream_id, new_buffer)) |
379 | complete(new_buffer, mg::BufferIpcMsgType::update_msg); |
380 | else |
381 | @@ -298,10 +299,12 @@ |
382 | { |
383 | response->mutable_buffer_stream()->mutable_id()->set_value( |
384 | surf_id.as_value()); |
385 | - pack_protobuf_buffer(*response->mutable_buffer_stream()->mutable_buffer(), |
386 | - client_buffer, |
387 | - msg_type); |
388 | |
389 | + if (client_buffer) |
390 | + { |
391 | + pack_protobuf_buffer( |
392 | + *response->mutable_buffer_stream()->mutable_buffer(), client_buffer, msg_type); |
393 | + } |
394 | done->Run(); |
395 | }); |
396 | } |
397 | @@ -384,6 +387,7 @@ |
398 | stream->swap_buffers(old_buffer, |
399 | [this, stream_id, done](mg::Buffer* new_buffer) |
400 | { |
401 | + if (!new_buffer) return; |
402 | if (buffer_stream_tracker.track_buffer(stream_id, new_buffer)) |
403 | event_sink->send_buffer(stream_id, *new_buffer, mg::BufferIpcMsgType::update_msg); |
404 | else |
405 | @@ -395,20 +399,43 @@ |
406 | |
407 | void mf::SessionMediator::allocate_buffers( |
408 | google::protobuf::RpcController*, |
409 | - mir::protobuf::BufferAllocation const*, |
410 | + mir::protobuf::BufferAllocation const* request, |
411 | mir::protobuf::Void*, |
412 | - google::protobuf::Closure*) |
413 | + google::protobuf::Closure* done) |
414 | { |
415 | - BOOST_THROW_EXCEPTION(std::runtime_error("not supported yet")); |
416 | + auto session = weak_session.lock(); |
417 | + if (!session) |
418 | + BOOST_THROW_EXCEPTION(std::logic_error("Invalid application session")); |
419 | + |
420 | + mf::BufferStreamId stream_id{request->id().value()}; |
421 | + auto stream = session->get_buffer_stream(stream_id); |
422 | + for (auto i = 0; i < request->buffer_requests().size(); i++) |
423 | + { |
424 | + auto const& req = request->buffer_requests(i); |
425 | + mg::BufferProperties properties( |
426 | + geom::Size{req.width(), req.height()}, |
427 | + static_cast<MirPixelFormat>(req.pixel_format()), |
428 | + static_cast<mg::BufferUsage>(req.buffer_usage())); |
429 | + stream->allocate_buffer(properties); |
430 | + } |
431 | + done->Run(); |
432 | } |
433 | |
434 | void mf::SessionMediator::release_buffers( |
435 | google::protobuf::RpcController*, |
436 | - mir::protobuf::BufferRelease const*, |
437 | + mir::protobuf::BufferRelease const* request, |
438 | mir::protobuf::Void*, |
439 | - google::protobuf::Closure*) |
440 | + google::protobuf::Closure* done) |
441 | { |
442 | - BOOST_THROW_EXCEPTION(std::runtime_error("not supported yet")); |
443 | + auto session = weak_session.lock(); |
444 | + if (!session) |
445 | + BOOST_THROW_EXCEPTION(std::logic_error("Invalid application session")); |
446 | + |
447 | + mf::BufferStreamId stream_id{request->id().value()}; |
448 | + auto stream = session->get_buffer_stream(stream_id); |
449 | + for (auto i = 0; i < request->buffers().size(); i++) |
450 | + stream->remove_buffer(mg::BufferID{static_cast<uint32_t>(request->buffers(i).buffer_id())}); |
451 | + done->Run(); |
452 | } |
453 | |
454 | void mf::SessionMediator::release_surface( |
455 | @@ -700,9 +727,11 @@ |
456 | [this, response, done, session] |
457 | (graphics::Buffer* client_buffer, graphics::BufferIpcMsgType msg_type) |
458 | { |
459 | - auto buffer = response->mutable_buffer(); |
460 | - pack_protobuf_buffer(*buffer, client_buffer, msg_type); |
461 | - |
462 | + if (client_buffer) |
463 | + { |
464 | + auto buffer = response->mutable_buffer(); |
465 | + pack_protobuf_buffer(*buffer, client_buffer, msg_type); |
466 | + } |
467 | done->Run(); |
468 | }); |
469 | } |
470 | |
471 | === modified file 'tests/include/mir/test/doubles/mock_buffer_stream.h' |
472 | --- tests/include/mir/test/doubles/mock_buffer_stream.h 2015-06-18 02:46:16 +0000 |
473 | +++ tests/include/mir/test/doubles/mock_buffer_stream.h 2015-07-23 19:11:05 +0000 |
474 | @@ -75,6 +75,8 @@ |
475 | MOCK_METHOD1(with_most_recent_buffer_do, void(std::function<void(graphics::Buffer&)> const&)); |
476 | MOCK_CONST_METHOD0(pixel_format, MirPixelFormat()); |
477 | MOCK_CONST_METHOD0(has_submitted_buffer, bool()); |
478 | + MOCK_METHOD1(allocate_buffer, void(graphics::BufferProperties const&)); |
479 | + MOCK_METHOD1(remove_buffer, void(graphics::BufferID)); |
480 | }; |
481 | } |
482 | } |
483 | |
484 | === modified file 'tests/include/mir/test/doubles/mock_client_buffer_stream_factory.h' |
485 | --- tests/include/mir/test/doubles/mock_client_buffer_stream_factory.h 2015-06-18 02:46:16 +0000 |
486 | +++ tests/include/mir/test/doubles/mock_client_buffer_stream_factory.h 2015-07-23 19:11:05 +0000 |
487 | @@ -34,12 +34,12 @@ |
488 | |
489 | struct MockClientBufferStreamFactory : public client::ClientBufferStreamFactory |
490 | { |
491 | - MOCK_METHOD4(make_consumer_stream, std::shared_ptr<client::ClientBufferStream>( |
492 | - MirConnection*, protobuf::DisplayServer&, |
493 | - protobuf::BufferStream const&, std::string const&)); |
494 | - MOCK_METHOD4(make_producer_stream, std::shared_ptr<client::ClientBufferStream>( |
495 | - MirConnection*, protobuf::DisplayServer&, |
496 | - protobuf::BufferStream const&, std::string const&)); |
497 | + MOCK_METHOD5(make_consumer_stream, std::shared_ptr<client::ClientBufferStream>( |
498 | + MirConnection*, protobuf::DisplayServer&, |
499 | + protobuf::BufferStream const&, std::string const&, geometry::Size)); |
500 | + MOCK_METHOD5(make_producer_stream, std::shared_ptr<client::ClientBufferStream>( |
501 | + MirConnection*, protobuf::DisplayServer&, |
502 | + protobuf::BufferStream const&, std::string const&, geometry::Size)); |
503 | MOCK_METHOD5(make_producer_stream, client::ClientBufferStream*( |
504 | MirConnection*, protobuf::DisplayServer&, |
505 | protobuf::BufferStreamParameters const&, mir_buffer_stream_callback callback, void* context)); |
506 | |
507 | === modified file 'tests/include/mir/test/doubles/stub_buffer_stream.h' |
508 | --- tests/include/mir/test/doubles/stub_buffer_stream.h 2015-06-25 03:00:08 +0000 |
509 | +++ tests/include/mir/test/doubles/stub_buffer_stream.h 2015-07-23 19:11:05 +0000 |
510 | @@ -79,6 +79,8 @@ |
511 | void add_observer(std::shared_ptr<scene::SurfaceObserver> const&) {} |
512 | void remove_observer(std::weak_ptr<scene::SurfaceObserver> const&) {} |
513 | bool has_submitted_buffer() const { return true; } |
514 | + void allocate_buffer(graphics::BufferProperties const&) {} |
515 | + void remove_buffer(graphics::BufferID) {} |
516 | |
517 | StubBuffer stub_client_buffer; |
518 | std::shared_ptr<graphics::Buffer> stub_compositor_buffer; |
519 | |
520 | === modified file 'tests/include/mir/test/doubles/stub_client_buffer_stream_factory.h' |
521 | --- tests/include/mir/test/doubles/stub_client_buffer_stream_factory.h 2015-06-18 02:46:16 +0000 |
522 | +++ tests/include/mir/test/doubles/stub_client_buffer_stream_factory.h 2015-07-23 19:11:05 +0000 |
523 | @@ -35,7 +35,8 @@ |
524 | MirConnection*, |
525 | protobuf::DisplayServer& /* server */, |
526 | protobuf::BufferStream const& /* protobuf_bs */, |
527 | - std::string const& /* surface_name */) override |
528 | + std::string const& /* surface_name */, |
529 | + geometry::Size) override |
530 | { |
531 | return nullptr; |
532 | } |
533 | @@ -44,7 +45,8 @@ |
534 | MirConnection*, |
535 | protobuf::DisplayServer& /* server */, |
536 | protobuf::BufferStream const& /* protobuf_bs */, |
537 | - std::string const& /* surface_name */) override |
538 | + std::string const& /* surface_name */, |
539 | + geometry::Size) override |
540 | { |
541 | return nullptr; |
542 | } |
543 | |
544 | === modified file 'tests/unit-tests/client/test_client_buffer_stream.cpp' |
545 | --- tests/unit-tests/client/test_client_buffer_stream.cpp 2015-07-16 08:13:28 +0000 |
546 | +++ tests/unit-tests/client/test_client_buffer_stream.cpp 2015-07-23 19:11:05 +0000 |
547 | @@ -61,6 +61,11 @@ |
548 | mp::BufferRequest const* /*request*/, |
549 | mp::Buffer* /*response*/, |
550 | google::protobuf::Closure* /*done*/)); |
551 | + MOCK_METHOD4(allocate_buffers, |
552 | + void(google::protobuf::RpcController* /*controller*/, |
553 | + mp::BufferAllocation const* /*request*/, |
554 | + mp::Void* /*response*/, |
555 | + google::protobuf::Closure* /*done*/)); |
556 | }; |
557 | |
558 | // TODO: Deduplicate this class |
559 | @@ -144,7 +149,7 @@ |
560 | mcl::BufferStreamMode mode=mcl::BufferStreamMode::Producer) |
561 | { |
562 | return std::make_shared<mcl::BufferStream>(nullptr, mock_protobuf_server, mode, |
563 | - std::make_shared<StubClientPlatform>(mt::fake_shared(buffer_factory)), protobuf_bs, perf_report, ""); |
564 | + std::make_shared<StubClientPlatform>(mt::fake_shared(buffer_factory)), protobuf_bs, perf_report, "", geom::Size{}); |
565 | } |
566 | }; |
567 | |
568 | @@ -257,12 +262,6 @@ |
569 | make_buffer_stream(no_id_bs); |
570 | }, std::runtime_error); |
571 | |
572 | - |
573 | - auto no_buffer_bs = valid_bs; |
574 | - no_buffer_bs.clear_buffer(); |
575 | - EXPECT_THROW({ |
576 | - make_buffer_stream(no_buffer_bs); |
577 | - }, std::runtime_error); |
578 | } |
579 | |
580 | TEST_F(ClientBufferStreamTest, uses_buffer_message_from_server) |
581 | @@ -465,7 +464,7 @@ |
582 | auto bs = std::make_shared<mcl::BufferStream>( |
583 | nullptr, mock_protobuf_server, mcl::BufferStreamMode::Producer, |
584 | std::make_shared<StubClientPlatform>(mt::fake_shared(stub_client_buffer_factory)), |
585 | - protobuf_bs, mt::fake_shared(mock_perf_report), name); |
586 | + protobuf_bs, mt::fake_shared(mock_perf_report), name, geom::Size{}); |
587 | } |
588 | |
589 | TEST_F(ClientBufferStreamTest, receives_unsolicited_buffer) |
590 | @@ -530,3 +529,26 @@ |
591 | bs->request_and_wait_for_next_buffer(); |
592 | }, std::runtime_error); |
593 | } |
594 | + |
595 | +TEST_F(ClientBufferStreamTest, requests_buffers_if_not_given_buffers_at_startup) |
596 | +{ |
597 | + using namespace ::testing; |
598 | + MockClientBuffer mock_client_buffer; |
599 | + ON_CALL(mock_client_buffer_factory, create_buffer(_,_,_)) |
600 | + .WillByDefault(Return(mt::fake_shared(mock_client_buffer))); |
601 | + |
602 | + EXPECT_CALL(mock_protobuf_server, allocate_buffers(_,_,_,_)) |
603 | + .WillOnce(RunProtobufClosure()); |
604 | + |
605 | + mp::BufferStream protobuf_bs; |
606 | + mp::BufferStreamId bs_id; |
607 | + bs_id.set_value(1); |
608 | + *protobuf_bs.mutable_id() = bs_id; |
609 | + auto bs = make_buffer_stream(protobuf_bs, mock_client_buffer_factory); |
610 | + |
611 | + mp::Buffer buffer; |
612 | + MirBufferPackage buffer_package = a_buffer_package(); |
613 | + fill_protobuf_buffer_from_package(&buffer, buffer_package); |
614 | + bs->buffer_available(buffer); |
615 | + EXPECT_THAT(bs->get_current_buffer(), NotNull()); |
616 | +} |
617 | |
618 | === modified file 'tests/unit-tests/client/test_mir_screencast.cpp' |
619 | --- tests/unit-tests/client/test_mir_screencast.cpp 2015-06-26 08:00:59 +0000 |
620 | +++ tests/unit-tests/client/test_mir_screencast.cpp 2015-07-23 19:11:05 +0000 |
621 | @@ -166,7 +166,7 @@ |
622 | using namespace ::testing; |
623 | |
624 | ON_CALL(*mock_buffer_stream_factory, |
625 | - make_consumer_stream(_,_,_,_)).WillByDefault( |
626 | + make_consumer_stream(_,_,_,_,_)).WillByDefault( |
627 | Return(mt::fake_shared(mock_bs))); |
628 | } |
629 | |
630 | |
631 | === modified file 'tests/unit-tests/compositor/test_buffer_stream.cpp' |
632 | --- tests/unit-tests/compositor/test_buffer_stream.cpp 2015-06-25 03:00:08 +0000 |
633 | +++ tests/unit-tests/compositor/test_buffer_stream.cpp 2015-07-23 19:11:05 +0000 |
634 | @@ -236,3 +236,15 @@ |
635 | buffer_stream.swap_buffers(buffer, complete); |
636 | buffer_stream.swap_buffers(buffer, complete); |
637 | } |
638 | + |
639 | +TEST_F(BufferStreamTest, allocate_and_release_not_supported) |
640 | +{ |
641 | + mg::BufferProperties properties; |
642 | + mc::BufferStreamSurfaces buffer_stream(mock_bundle); |
643 | + EXPECT_THROW({ |
644 | + buffer_stream.allocate_buffer(properties); |
645 | + }, std::runtime_error); |
646 | + EXPECT_THROW({ |
647 | + buffer_stream.remove_buffer(mg::BufferID{3}); |
648 | + }, std::runtime_error); |
649 | +} |
650 | |
651 | === modified file 'tests/unit-tests/frontend/test_session_mediator.cpp' |
652 | --- tests/unit-tests/frontend/test_session_mediator.cpp 2015-06-25 19:29:44 +0000 |
653 | +++ tests/unit-tests/frontend/test_session_mediator.cpp 2015-07-23 19:11:05 +0000 |
654 | @@ -1007,3 +1007,72 @@ |
655 | |
656 | mediator.submit_buffer(nullptr, &request, &null, null_callback.get()); |
657 | } |
658 | + |
659 | +TEST_F(SessionMediator, allocates_from_the_correct_stream) |
660 | +{ |
661 | + using namespace testing; |
662 | + auto num_requests = 3u; |
663 | + mp::Void null; |
664 | + mp::BufferStreamId id; |
665 | + id.set_value(0); |
666 | + mp::BufferAllocation request; |
667 | + *request.mutable_id() = id; |
668 | + mg::BufferProperties properties(geom::Size{34, 84}, mir_pixel_format_abgr_8888, mg::BufferUsage::hardware); |
669 | + for(auto i = 0u; i < num_requests; i++) |
670 | + { |
671 | + auto buffer_request = request.add_buffer_requests(); |
672 | + buffer_request->set_width(properties.size.width.as_int()); |
673 | + buffer_request->set_height(properties.size.height.as_int()); |
674 | + buffer_request->set_pixel_format(properties.format); |
675 | + buffer_request->set_buffer_usage((int)properties.usage); |
676 | + } |
677 | + |
678 | + mediator.connect(nullptr, &connect_parameters, &connection, null_callback.get()); |
679 | + mediator.create_surface(nullptr, &surface_parameters, &surface_response, null_callback.get()); |
680 | + |
681 | + auto mock_stream = stubbed_session->mock_primary_stream_at(mf::SurfaceId{0}); |
682 | + EXPECT_CALL(*mock_stream, allocate_buffer(properties)) |
683 | + .Times(num_requests); |
684 | + |
685 | + mediator.allocate_buffers(nullptr, &request, &null, null_callback.get()); |
686 | +} |
687 | + |
688 | +TEST_F(SessionMediator, removes_buffer_from_the_correct_stream) |
689 | +{ |
690 | + using namespace testing; |
691 | + auto num_requests = 3u; |
692 | + mp::Void null; |
693 | + mp::BufferStreamId id; |
694 | + id.set_value(0); |
695 | + mp::BufferRelease request; |
696 | + *request.mutable_id() = id; |
697 | + auto buffer_id = 442u; |
698 | + for(auto i = 0u; i < num_requests; i++) |
699 | + { |
700 | + auto buffer_request = request.add_buffers(); |
701 | + buffer_request->set_buffer_id(buffer_id); |
702 | + } |
703 | + |
704 | + mediator.connect(nullptr, &connect_parameters, &connection, null_callback.get()); |
705 | + mediator.create_surface(nullptr, &surface_parameters, &surface_response, null_callback.get()); |
706 | + |
707 | + auto mock_stream = stubbed_session->mock_primary_stream_at(mf::SurfaceId{0}); |
708 | + EXPECT_CALL(*mock_stream, remove_buffer(mg::BufferID{buffer_id})) |
709 | + .Times(num_requests); |
710 | + |
711 | + mediator.release_buffers(nullptr, &request, &null, null_callback.get()); |
712 | +} |
713 | + |
714 | +TEST_F(SessionMediator, can_handle_if_swapbuffers_returns_nullptr) |
715 | +{ |
716 | + using namespace testing; |
717 | + mf::SurfaceId surf_id{0}; |
718 | + auto stream = stubbed_session->mock_primary_stream_at(surf_id); |
719 | + EXPECT_CALL(*stream, swap_buffers(_,_)) |
720 | + .WillOnce(InvokeArgument<1>(nullptr)); |
721 | + |
722 | + mediator.connect(nullptr, &connect_parameters, &connection, null_callback.get()); |
723 | + mediator.create_surface(nullptr, &surface_parameters, &surface_response, null_callback.get()); |
724 | + EXPECT_FALSE(surface_response.has_buffer()); |
725 | + EXPECT_TRUE(surface_response.has_id()); |
726 | +} |