Merge lp:~kdub/mir/fix-1664562 into lp:mir
- fix-1664562
- Merge into development-branch
Status: | Merged |
---|---|
Approved by: | Daniel van Vugt |
Approved revision: | no longer in the source branch. |
Merged at revision: | 4040 |
Proposed branch: | lp:~kdub/mir/fix-1664562 |
Merge into: | lp:mir |
Diff against target: |
900 lines (+535/-230) 10 files modified
src/server/graphics/nested/CMakeLists.txt (+1/-0) src/server/graphics/nested/host_buffer.cpp (+183/-0) src/server/graphics/nested/host_buffer.h (+73/-0) src/server/graphics/nested/mir_client_host_connection.cpp (+5/-174) tests/include/mir/test/doubles/mock_client_platform.h (+76/-0) tests/include/mir/test/doubles/stub_client_platform_factory.h (+50/-0) tests/include/mir/test/stub_server_tool.h (+14/-0) tests/unit-tests/client/test_mir_render_surface.cpp (+5/-56) tests/unit-tests/platforms/nested/CMakeLists.txt (+1/-0) tests/unit-tests/platforms/nested/test_host_buffer.cpp (+127/-0) |
To merge this branch: | bzr merge lp:~kdub/mir/fix-1664562 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Daniel van Vugt | Abstain | ||
Chris Halse Rogers | Approve | ||
Mir CI Bot | continuous-integration | Approve | |
Review via email: mp+317235@code.launchpad.net |
Commit message
nested: make sure not to close the FD given via the fenced_buffers extension. This was causing intermittent problems with mirscreencast on fenced platforms (android)
fixes: LP: #1664562
Description of the change
nested: make sure not to close the FD given via the fenced_buffers extension. This was causing intermittent problems with mirscreencast on fenced platforms (android)
fixes: LP: #1664562
one line of change... line 448 changed to line 194. The rest was extruding classes to their own files to come up with the test.
Mir CI Bot (mir-ci-bot) wrote : | # |
Chris Halse Rogers (raof) wrote : | # |
I'd kinda prefer this to be just the one-line change, rather than all the changes to make a test :).
That said, looks fine to me.
Daniel van Vugt (vanvugt) wrote : | # |
I agree with Chris, although it's also fine putting a larger cleanup on trunk. Only if you were backporting the fix to a stable branch like lp:mir/0.26 then you should choose the one-liner solution over this.
Preview Diff
1 | === modified file 'src/server/graphics/nested/CMakeLists.txt' |
2 | --- src/server/graphics/nested/CMakeLists.txt 2017-01-18 02:29:37 +0000 |
3 | +++ src/server/graphics/nested/CMakeLists.txt 2017-02-14 17:05:00 +0000 |
4 | @@ -15,4 +15,5 @@ |
5 | platform.cpp |
6 | buffer.cpp |
7 | ipc_operations.cpp |
8 | + host_buffer.cpp |
9 | ) |
10 | |
11 | === added file 'src/server/graphics/nested/host_buffer.cpp' |
12 | --- src/server/graphics/nested/host_buffer.cpp 1970-01-01 00:00:00 +0000 |
13 | +++ src/server/graphics/nested/host_buffer.cpp 2017-02-14 17:05:00 +0000 |
14 | @@ -0,0 +1,183 @@ |
15 | +/* |
16 | + * Copyright © 2017 Canonical Ltd. |
17 | + * |
18 | + * This program is free software: you can redistribute it and/or modify it |
19 | + * under the terms of the GNU General Public License version 3, |
20 | + * as published by the Free Software Foundation. |
21 | + * |
22 | + * This program is distributed in the hope that it will be useful, |
23 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
24 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
25 | + * GNU General Public License for more details. |
26 | + * |
27 | + * You should have received a copy of the GNU General Public License |
28 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
29 | + * |
30 | + * Authored by: Kevin DuBois <kevin.dubois@canonical.com> |
31 | + */ |
32 | + |
33 | +#include "host_buffer.h" |
34 | +#include "mir_toolkit/mir_buffer_private.h" |
35 | +#include <boost/throw_exception.hpp> |
36 | + |
37 | +namespace mg = mir::graphics; |
38 | +namespace mgn = mir::graphics::nested; |
39 | +namespace geom = mir::geometry; |
40 | + |
41 | +mgn::HostBuffer::HostBuffer(MirConnection* mir_connection, mg::BufferProperties const& properties) : |
42 | + fence_extensions(mir_extension_fenced_buffers_v1(mir_connection)) |
43 | +{ |
44 | + mir_connection_allocate_buffer( |
45 | + mir_connection, |
46 | + properties.size.width.as_int(), |
47 | + properties.size.height.as_int(), |
48 | + properties.format, |
49 | + buffer_available, this); |
50 | + std::unique_lock<std::mutex> lk(mut); |
51 | + cv.wait(lk, [&]{ return handle; }); |
52 | + if (!mir_buffer_is_valid(handle)) |
53 | + { |
54 | + mir_buffer_release(handle); |
55 | + BOOST_THROW_EXCEPTION(std::runtime_error("could not allocate MirBuffer")); |
56 | + } |
57 | +} |
58 | + |
59 | +mgn::HostBuffer::HostBuffer(MirConnection* mir_connection, geom::Size size, MirPixelFormat format) : |
60 | + fence_extensions(mir_extension_fenced_buffers_v1(mir_connection)) |
61 | +{ |
62 | + mir_connection_allocate_buffer( |
63 | + mir_connection, |
64 | + size.width.as_int(), |
65 | + size.height.as_int(), |
66 | + format, |
67 | + buffer_available, this); |
68 | + std::unique_lock<std::mutex> lk(mut); |
69 | + cv.wait(lk, [&]{ return handle; }); |
70 | + if (!mir_buffer_is_valid(handle)) |
71 | + { |
72 | + mir_buffer_release(handle); |
73 | + BOOST_THROW_EXCEPTION(std::runtime_error("could not allocate MirBuffer")); |
74 | + } |
75 | +} |
76 | + |
77 | +mgn::HostBuffer::HostBuffer(MirConnection* mir_connection, |
78 | + MirExtensionGbmBufferV1 const* ext, |
79 | + geom::Size size, unsigned int native_pf, unsigned int native_flags) : |
80 | + fence_extensions(mir_extension_fenced_buffers_v1(mir_connection)) |
81 | +{ |
82 | + ext->allocate_buffer_gbm( |
83 | + mir_connection, size.width.as_int(), size.height.as_int(), native_pf, native_flags, |
84 | + buffer_available, this); |
85 | + std::unique_lock<std::mutex> lk(mut); |
86 | + cv.wait(lk, [&]{ return handle; }); |
87 | + if (!mir_buffer_is_valid(handle)) |
88 | + { |
89 | + mir_buffer_release(handle); |
90 | + BOOST_THROW_EXCEPTION(std::runtime_error("could not allocate MirBuffer")); |
91 | + } |
92 | +} |
93 | + |
94 | +mgn::HostBuffer::HostBuffer(MirConnection* mir_connection, |
95 | + MirExtensionAndroidBufferV1 const* ext, |
96 | + geom::Size size, unsigned int native_pf, unsigned int native_flags) : |
97 | + fence_extensions(mir_extension_fenced_buffers_v1(mir_connection)) |
98 | +{ |
99 | + ext->allocate_buffer_android( |
100 | + mir_connection, size.width.as_int(), size.height.as_int(), native_pf, native_flags, |
101 | + buffer_available, this); |
102 | + std::unique_lock<std::mutex> lk(mut); |
103 | + cv.wait(lk, [&]{ return handle; }); |
104 | + if (!mir_buffer_is_valid(handle)) |
105 | + { |
106 | + mir_buffer_release(handle); |
107 | + BOOST_THROW_EXCEPTION(std::runtime_error("could not allocate MirBuffer")); |
108 | + } |
109 | +} |
110 | + |
111 | +mgn::HostBuffer::~HostBuffer() |
112 | +{ |
113 | + mir_buffer_release(handle); |
114 | +} |
115 | + |
116 | +void mgn::HostBuffer::sync(MirBufferAccess access, std::chrono::nanoseconds ns) |
117 | +{ |
118 | + if (fence_extensions && fence_extensions->wait_for_access) |
119 | + fence_extensions->wait_for_access(handle, access, ns.count()); |
120 | +} |
121 | + |
122 | +MirBuffer* mgn::HostBuffer::client_handle() const |
123 | +{ |
124 | + return handle; |
125 | +} |
126 | + |
127 | +std::unique_ptr<mgn::GraphicsRegion> mgn::HostBuffer::get_graphics_region() |
128 | +{ |
129 | + return std::make_unique<mgn::GraphicsRegion>(handle); |
130 | +} |
131 | + |
132 | +geom::Size mgn::HostBuffer::size() const |
133 | +{ |
134 | + return { mir_buffer_get_width(handle), mir_buffer_get_height(handle) }; |
135 | +} |
136 | + |
137 | +MirPixelFormat mgn::HostBuffer::format() const |
138 | +{ |
139 | + return mir_buffer_get_pixel_format(handle); |
140 | +} |
141 | + |
142 | +std::tuple<EGLenum, EGLClientBuffer, EGLint*> mgn::HostBuffer::egl_image_creation_hints() const |
143 | +{ |
144 | + EGLenum type; |
145 | + EGLClientBuffer client_buffer = nullptr;; |
146 | + EGLint* attrs = nullptr; |
147 | + // TODO: check return value |
148 | + mir_buffer_get_egl_image_parameters(handle, &type, &client_buffer, &attrs); |
149 | + |
150 | + return std::tuple<EGLenum, EGLClientBuffer, EGLint*>{type, client_buffer, attrs}; |
151 | +} |
152 | + |
153 | +void mgn::HostBuffer::buffer_available(MirBuffer* buffer, void* context) |
154 | +{ |
155 | + auto host_buffer = static_cast<HostBuffer*>(context); |
156 | + host_buffer->available(buffer); |
157 | +} |
158 | + |
159 | +void mgn::HostBuffer::available(MirBuffer* buffer) |
160 | +{ |
161 | + std::unique_lock<std::mutex> lk(mut); |
162 | + if (!handle) |
163 | + { |
164 | + handle = buffer; |
165 | + cv.notify_all(); |
166 | + } |
167 | + |
168 | + auto g = f; |
169 | + lk.unlock(); |
170 | + if (g) |
171 | + g(); |
172 | +} |
173 | + |
174 | +void mgn::HostBuffer::on_ownership_notification(std::function<void()> const& fn) |
175 | +{ |
176 | + std::unique_lock<std::mutex> lk(mut); |
177 | + f = fn; |
178 | +} |
179 | + |
180 | +MirBufferPackage* mgn::HostBuffer::package() const |
181 | +{ |
182 | + return mir_buffer_get_buffer_package(handle); |
183 | +} |
184 | + |
185 | +void mgn::HostBuffer::set_fence(mir::Fd fd) |
186 | +{ |
187 | + if (fence_extensions && fence_extensions->associate_fence) |
188 | + fence_extensions->associate_fence(handle, fd, mir_read_write); |
189 | +} |
190 | + |
191 | +mir::Fd mgn::HostBuffer::fence() const |
192 | +{ |
193 | + if (fence_extensions && fence_extensions->get_fence) |
194 | + return mir::Fd{mir::IntOwnedFd{fence_extensions->get_fence(handle)}}; |
195 | + else |
196 | + return mir::Fd{mir::Fd::invalid}; |
197 | +} |
198 | |
199 | === added file 'src/server/graphics/nested/host_buffer.h' |
200 | --- src/server/graphics/nested/host_buffer.h 1970-01-01 00:00:00 +0000 |
201 | +++ src/server/graphics/nested/host_buffer.h 2017-02-14 17:05:00 +0000 |
202 | @@ -0,0 +1,73 @@ |
203 | +/* |
204 | + * Copyright © 2017 Canonical Ltd. |
205 | + * |
206 | + * This program is free software: you can redistribute it and/or modify it |
207 | + * under the terms of the GNU General Public License version 3, |
208 | + * as published by the Free Software Foundation. |
209 | + * |
210 | + * This program is distributed in the hope that it will be useful, |
211 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
212 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
213 | + * GNU General Public License for more details. |
214 | + * |
215 | + * You should have received a copy of the GNU General Public License |
216 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
217 | + * |
218 | + * Authored by: Kevin DuBois <kevin.dubois@canonical.com> |
219 | + */ |
220 | + |
221 | +#ifndef MIR_GRAPHICS_NESTED_HOST_BUFFER_H_ |
222 | +#define MIR_GRAPHICS_NESTED_HOST_BUFFER_H_ |
223 | + |
224 | +#include "mir/graphics/buffer_properties.h" |
225 | +#include "mir_toolkit/mir_buffer.h" |
226 | +#include "mir_toolkit/extensions/gbm_buffer.h" |
227 | +#include "mir_toolkit/extensions/android_buffer.h" |
228 | +#include "native_buffer.h" |
229 | +#include <functional> |
230 | +#include <mutex> |
231 | +#include <condition_variable> |
232 | + |
233 | +namespace mir |
234 | +{ |
235 | +namespace graphics |
236 | +{ |
237 | +namespace nested |
238 | +{ |
239 | +class HostBuffer : public NativeBuffer |
240 | +{ |
241 | +public: |
242 | + HostBuffer(MirConnection* mir_connection, BufferProperties const& properties); |
243 | + HostBuffer(MirConnection* mir_connection, geometry::Size size, MirPixelFormat format); |
244 | + HostBuffer(MirConnection* mir_connection, |
245 | + MirExtensionGbmBufferV1 const* ext, |
246 | + geometry::Size size, unsigned int native_pf, unsigned int native_flags); |
247 | + HostBuffer(MirConnection* mir_connection, |
248 | + MirExtensionAndroidBufferV1 const* ext, |
249 | + geometry::Size size, unsigned int native_pf, unsigned int native_flags); |
250 | + ~HostBuffer(); |
251 | + |
252 | + void sync(MirBufferAccess access, std::chrono::nanoseconds ns) override; |
253 | + MirBuffer* client_handle() const override; |
254 | + std::unique_ptr<GraphicsRegion> get_graphics_region() override; |
255 | + geometry::Size size() const override; |
256 | + MirPixelFormat format() const override; |
257 | + std::tuple<EGLenum, EGLClientBuffer, EGLint*> egl_image_creation_hints() const override; |
258 | + static void buffer_available(MirBuffer* buffer, void* context); |
259 | + void available(MirBuffer* buffer) override; |
260 | + void on_ownership_notification(std::function<void()> const& fn) override; |
261 | + MirBufferPackage* package() const override; |
262 | + void set_fence(mir::Fd fd) override; |
263 | + mir::Fd fence() const override; |
264 | + |
265 | +private: |
266 | + MirExtensionFencedBuffersV1 const* fence_extensions = nullptr; |
267 | + std::function<void()> f; |
268 | + MirBuffer* handle = nullptr; |
269 | + std::mutex mut; |
270 | + std::condition_variable cv; |
271 | +}; |
272 | +} |
273 | +} |
274 | +} |
275 | +#endif /* MIR_GRAPHICS_NESTED_HOST_BUFFER_H_ */ |
276 | |
277 | === modified file 'src/server/graphics/nested/mir_client_host_connection.cpp' |
278 | --- src/server/graphics/nested/mir_client_host_connection.cpp 2017-02-14 07:05:13 +0000 |
279 | +++ src/server/graphics/nested/mir_client_host_connection.cpp 2017-02-14 17:05:00 +0000 |
280 | @@ -21,6 +21,7 @@ |
281 | #include "host_stream.h" |
282 | #include "host_chain.h" |
283 | #include "host_surface_spec.h" |
284 | +#include "host_buffer.h" |
285 | #include "native_buffer.h" |
286 | #include "mir_toolkit/mir_client_library.h" |
287 | #include "mir_toolkit/mir_extension_core.h" |
288 | @@ -610,176 +611,6 @@ |
289 | |
290 | namespace |
291 | { |
292 | -class HostBuffer : public mgn::NativeBuffer |
293 | -{ |
294 | -public: |
295 | - HostBuffer(MirConnection* mir_connection, mg::BufferProperties const& properties) : |
296 | - fence_extensions(mir_extension_fenced_buffers_v1(mir_connection)) |
297 | - { |
298 | - mir_connection_allocate_buffer( |
299 | - mir_connection, |
300 | - properties.size.width.as_int(), |
301 | - properties.size.height.as_int(), |
302 | - properties.format, |
303 | - buffer_available, this); |
304 | - std::unique_lock<std::mutex> lk(mut); |
305 | - cv.wait(lk, [&]{ return handle; }); |
306 | - if (!mir_buffer_is_valid(handle)) |
307 | - { |
308 | - mir_buffer_release(handle); |
309 | - BOOST_THROW_EXCEPTION(std::runtime_error("could not allocate MirBuffer")); |
310 | - } |
311 | - } |
312 | - |
313 | - HostBuffer(MirConnection* mir_connection, geom::Size size, MirPixelFormat format) : |
314 | - fence_extensions(mir_extension_fenced_buffers_v1(mir_connection)) |
315 | - { |
316 | - mir_connection_allocate_buffer( |
317 | - mir_connection, |
318 | - size.width.as_int(), |
319 | - size.height.as_int(), |
320 | - format, |
321 | - buffer_available, this); |
322 | - std::unique_lock<std::mutex> lk(mut); |
323 | - cv.wait(lk, [&]{ return handle; }); |
324 | - if (!mir_buffer_is_valid(handle)) |
325 | - { |
326 | - mir_buffer_release(handle); |
327 | - BOOST_THROW_EXCEPTION(std::runtime_error("could not allocate MirBuffer")); |
328 | - } |
329 | - } |
330 | - |
331 | - HostBuffer(MirConnection* mir_connection, |
332 | - MirExtensionGbmBufferV1 const* ext, |
333 | - geom::Size size, unsigned int native_pf, unsigned int native_flags) : |
334 | - fence_extensions(mir_extension_fenced_buffers_v1(mir_connection)) |
335 | - { |
336 | - ext->allocate_buffer_gbm( |
337 | - mir_connection, size.width.as_int(), size.height.as_int(), native_pf, native_flags, |
338 | - buffer_available, this); |
339 | - std::unique_lock<std::mutex> lk(mut); |
340 | - cv.wait(lk, [&]{ return handle; }); |
341 | - if (!mir_buffer_is_valid(handle)) |
342 | - { |
343 | - mir_buffer_release(handle); |
344 | - BOOST_THROW_EXCEPTION(std::runtime_error("could not allocate MirBuffer")); |
345 | - } |
346 | - } |
347 | - |
348 | - HostBuffer(MirConnection* mir_connection, |
349 | - MirExtensionAndroidBufferV1 const* ext, |
350 | - geom::Size size, unsigned int native_pf, unsigned int native_flags) : |
351 | - fence_extensions(mir_extension_fenced_buffers_v1(mir_connection)) |
352 | - { |
353 | - ext->allocate_buffer_android( |
354 | - mir_connection, size.width.as_int(), size.height.as_int(), native_pf, native_flags, |
355 | - buffer_available, this); |
356 | - std::unique_lock<std::mutex> lk(mut); |
357 | - cv.wait(lk, [&]{ return handle; }); |
358 | - if (!mir_buffer_is_valid(handle)) |
359 | - { |
360 | - mir_buffer_release(handle); |
361 | - BOOST_THROW_EXCEPTION(std::runtime_error("could not allocate MirBuffer")); |
362 | - } |
363 | - } |
364 | - |
365 | - ~HostBuffer() |
366 | - { |
367 | - mir_buffer_release(handle); |
368 | - } |
369 | - |
370 | - void sync(MirBufferAccess access, std::chrono::nanoseconds ns) override |
371 | - { |
372 | - if (fence_extensions && fence_extensions->wait_for_access) |
373 | - fence_extensions->wait_for_access(handle, access, ns.count()); |
374 | - } |
375 | - |
376 | - MirBuffer* client_handle() const override |
377 | - { |
378 | - return handle; |
379 | - } |
380 | - |
381 | - std::unique_ptr<mgn::GraphicsRegion> get_graphics_region() override |
382 | - { |
383 | - return std::make_unique<mgn::GraphicsRegion>(handle); |
384 | - } |
385 | - |
386 | - geom::Size size() const override |
387 | - { |
388 | - return { mir_buffer_get_width(handle), mir_buffer_get_height(handle) }; |
389 | - } |
390 | - |
391 | - MirPixelFormat format() const override |
392 | - { |
393 | - return mir_buffer_get_pixel_format(handle); |
394 | - } |
395 | - |
396 | - std::tuple<EGLenum, EGLClientBuffer, EGLint*> egl_image_creation_hints() const override |
397 | - { |
398 | - EGLenum type; |
399 | - EGLClientBuffer client_buffer = nullptr;; |
400 | - EGLint* attrs = nullptr; |
401 | - // TODO: check return value |
402 | - mir_buffer_get_egl_image_parameters(handle, &type, &client_buffer, &attrs); |
403 | - |
404 | - return std::tuple<EGLenum, EGLClientBuffer, EGLint*>{type, client_buffer, attrs}; |
405 | - } |
406 | - |
407 | - static void buffer_available(MirBuffer* buffer, void* context) |
408 | - { |
409 | - auto host_buffer = static_cast<HostBuffer*>(context); |
410 | - host_buffer->available(buffer); |
411 | - } |
412 | - |
413 | - void available(MirBuffer* buffer) override |
414 | - { |
415 | - std::unique_lock<std::mutex> lk(mut); |
416 | - if (!handle) |
417 | - { |
418 | - handle = buffer; |
419 | - cv.notify_all(); |
420 | - } |
421 | - |
422 | - auto g = f; |
423 | - lk.unlock(); |
424 | - if (g) |
425 | - g(); |
426 | - } |
427 | - |
428 | - void on_ownership_notification(std::function<void()> const& fn) override |
429 | - { |
430 | - std::unique_lock<std::mutex> lk(mut); |
431 | - f = fn; |
432 | - } |
433 | - |
434 | - MirBufferPackage* package() const override |
435 | - { |
436 | - return mir_buffer_get_buffer_package(handle); |
437 | - } |
438 | - |
439 | - void set_fence(mir::Fd fd) override |
440 | - { |
441 | - if (fence_extensions && fence_extensions->associate_fence) |
442 | - fence_extensions->associate_fence(handle, fd, mir_read_write); |
443 | - } |
444 | - |
445 | - mir::Fd fence() const override |
446 | - { |
447 | - if (fence_extensions && fence_extensions->get_fence) |
448 | - return mir::Fd{fence_extensions->get_fence(handle)}; |
449 | - else |
450 | - return mir::Fd{mir::Fd::invalid}; |
451 | - } |
452 | - |
453 | -private: |
454 | - MirExtensionFencedBuffersV1 const* fence_extensions = nullptr; |
455 | - |
456 | - std::function<void()> f; |
457 | - MirBuffer* handle = nullptr; |
458 | - std::mutex mut; |
459 | - std::condition_variable cv; |
460 | -}; |
461 | - |
462 | class SurfaceSpec : public mgn::HostSurfaceSpec |
463 | { |
464 | public: |
465 | @@ -824,13 +655,13 @@ |
466 | std::shared_ptr<mgn::NativeBuffer> mgn::MirClientHostConnection::create_buffer( |
467 | mg::BufferProperties const& properties) |
468 | { |
469 | - return std::make_shared<HostBuffer>(mir_connection, properties); |
470 | + return std::make_shared<mgn::HostBuffer>(mir_connection, properties); |
471 | } |
472 | |
473 | std::shared_ptr<mgn::NativeBuffer> mgn::MirClientHostConnection::create_buffer( |
474 | geom::Size size, MirPixelFormat format) |
475 | { |
476 | - return std::make_shared<HostBuffer>(mir_connection, size, format); |
477 | + return std::make_shared<mgn::HostBuffer>(mir_connection, size, format); |
478 | } |
479 | |
480 | std::shared_ptr<mgn::NativeBuffer> mgn::MirClientHostConnection::create_buffer( |
481 | @@ -838,12 +669,12 @@ |
482 | { |
483 | if (auto ext = mir_extension_gbm_buffer_v1(mir_connection)) |
484 | { |
485 | - return std::make_shared<HostBuffer>(mir_connection, ext, size, native_format, native_flags); |
486 | + return std::make_shared<mgn::HostBuffer>(mir_connection, ext, size, native_format, native_flags); |
487 | } |
488 | |
489 | if (auto ext = mir_extension_android_buffer_v1(mir_connection)) |
490 | { |
491 | - return std::make_shared<HostBuffer>(mir_connection, ext, size, native_format, native_flags); |
492 | + return std::make_shared<mgn::HostBuffer>(mir_connection, ext, size, native_format, native_flags); |
493 | } |
494 | |
495 | BOOST_THROW_EXCEPTION(std::runtime_error("could not create hardware buffer")); |
496 | |
497 | === added file 'tests/include/mir/test/doubles/mock_client_platform.h' |
498 | --- tests/include/mir/test/doubles/mock_client_platform.h 1970-01-01 00:00:00 +0000 |
499 | +++ tests/include/mir/test/doubles/mock_client_platform.h 2017-02-14 17:05:00 +0000 |
500 | @@ -0,0 +1,76 @@ |
501 | +/* |
502 | + * Copyright © 2017 Canonical Ltd. |
503 | + * |
504 | + * This program is free software: you can redistribute it and/or modify it |
505 | + * under the terms of the GNU General Public License version 3, |
506 | + * as published by the Free Software Foundation. |
507 | + * |
508 | + * This program is distributed in the hope that it will be useful, |
509 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
510 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
511 | + * GNU General Public License for more details. |
512 | + * |
513 | + * You should have received a copy of the GNU General Public License |
514 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
515 | + * |
516 | + * Authored by: Kevin DuBois <kevin.dubois@canonical.com> |
517 | + */ |
518 | + |
519 | +#ifndef MIR_TEST_DOUBLES_MOCK_CLIENT_PLATFOM_H_ |
520 | +#define MIR_TEST_DOUBLES_MOCK_CLIENT_PLATFOM_H_ |
521 | + |
522 | +#include "stub_client_buffer_factory.h" |
523 | +#include "mir/client_platform.h" |
524 | +#include "mir/client_platform_factory.h" |
525 | +#include <gmock/gmock.h> |
526 | + |
527 | +namespace mir |
528 | +{ |
529 | +namespace test |
530 | +{ |
531 | +namespace doubles |
532 | +{ |
533 | + |
534 | +struct MockClientPlatform : public client::ClientPlatform |
535 | +{ |
536 | + MockClientPlatform() |
537 | + { |
538 | + auto native_window = std::make_shared<EGLNativeWindowType>(); |
539 | + *native_window = reinterpret_cast<EGLNativeWindowType>(this); |
540 | + |
541 | + ON_CALL(*this, create_buffer_factory()) |
542 | + .WillByDefault(testing::Return(std::make_shared<StubClientBufferFactory>())); |
543 | + ON_CALL(*this, create_egl_native_window(testing::_)) |
544 | + .WillByDefault(testing::Return(native_window)); |
545 | + } |
546 | + |
547 | + void set_client_context(client::ClientContext* ctx) |
548 | + { |
549 | + client_context = ctx; |
550 | + } |
551 | + |
552 | + void populate(MirPlatformPackage& pkg) const override |
553 | + { |
554 | + client_context->populate_server_package(pkg); |
555 | + } |
556 | + |
557 | + MOCK_CONST_METHOD1(convert_native_buffer, MirNativeBuffer*(mir::graphics::NativeBuffer*)); |
558 | + MOCK_CONST_METHOD0(platform_type, MirPlatformType()); |
559 | + MOCK_METHOD1(platform_operation, MirPlatformMessage*(MirPlatformMessage const*)); |
560 | + MOCK_METHOD0(create_buffer_factory, std::shared_ptr<client::ClientBufferFactory>()); |
561 | + MOCK_METHOD2(use_egl_native_window, void(std::shared_ptr<void>, client::EGLNativeSurface*)); |
562 | + MOCK_METHOD1(create_egl_native_window, std::shared_ptr<void>(client::EGLNativeSurface*)); |
563 | + MOCK_METHOD0(create_egl_native_display, std::shared_ptr<EGLNativeDisplayType>()); |
564 | + MOCK_CONST_METHOD2(get_egl_pixel_format, MirPixelFormat(EGLDisplay, EGLConfig)); |
565 | + MOCK_METHOD2(request_interface, void*(char const*, int)); |
566 | + MOCK_CONST_METHOD1(native_format_for, uint32_t(MirPixelFormat)); |
567 | + MOCK_CONST_METHOD2(native_flags_for, uint32_t(MirBufferUsage, mir::geometry::Size)); |
568 | + |
569 | + client::ClientContext* client_context = nullptr; |
570 | +}; |
571 | + |
572 | +} |
573 | +} |
574 | +} |
575 | + |
576 | +#endif /* MIR_TEST_DOUBLES_MOCK_CLIENT_PLATFOM_H_ */ |
577 | |
578 | === added file 'tests/include/mir/test/doubles/stub_client_platform_factory.h' |
579 | --- tests/include/mir/test/doubles/stub_client_platform_factory.h 1970-01-01 00:00:00 +0000 |
580 | +++ tests/include/mir/test/doubles/stub_client_platform_factory.h 2017-02-14 17:05:00 +0000 |
581 | @@ -0,0 +1,50 @@ |
582 | +/* |
583 | + * Copyright © 2017 Canonical Ltd. |
584 | + * |
585 | + * This program is free software: you can redistribute it and/or modify it |
586 | + * under the terms of the GNU General Public License version 3, |
587 | + * as published by the Free Software Foundation. |
588 | + * |
589 | + * This program is distributed in the hope that it will be useful, |
590 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
591 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
592 | + * GNU General Public License for more details. |
593 | + * |
594 | + * You should have received a copy of the GNU General Public License |
595 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
596 | + * |
597 | + * Authored by: Kevin DuBois <kevin.dubois@canonical.com> |
598 | + */ |
599 | + |
600 | +#ifndef MIR_TEST_DOUBLES_STUB_CLIENT_PLATFORM_FACTORY_H_ |
601 | +#define MIR_TEST_DOUBLES_STUB_CLIENT_PLATFORM_FACTORY_H_ |
602 | + |
603 | +#include "mir/client_platform_factory.h" |
604 | + |
605 | +namespace mir |
606 | +{ |
607 | +namespace test |
608 | +{ |
609 | +namespace doubles |
610 | +{ |
611 | + |
612 | +struct StubClientPlatformFactory : public client::ClientPlatformFactory |
613 | +{ |
614 | + StubClientPlatformFactory(std::shared_ptr<client::ClientPlatform> const& platform) |
615 | + : platform{platform} |
616 | + { |
617 | + } |
618 | + |
619 | + std::shared_ptr<client::ClientPlatform> create_client_platform(client::ClientContext*) |
620 | + { |
621 | + return platform; |
622 | + } |
623 | + |
624 | + std::shared_ptr<client::ClientPlatform> platform; |
625 | +}; |
626 | + |
627 | +} |
628 | +} |
629 | +} |
630 | + |
631 | +#endif /* MIR_TEST_DOUBLES_STUB_CLIENT_PLATFORM_FACTORY_H_ */ |
632 | |
633 | === modified file 'tests/include/mir/test/stub_server_tool.h' |
634 | --- tests/include/mir/test/stub_server_tool.h 2017-02-14 07:05:13 +0000 |
635 | +++ tests/include/mir/test/stub_server_tool.h 2017-02-14 17:05:00 +0000 |
636 | @@ -123,6 +123,20 @@ |
637 | { |
638 | done->Run(); |
639 | } |
640 | + virtual void allocate_buffers( |
641 | + mir::protobuf::BufferAllocation const* /*request*/, |
642 | + mir::protobuf::Void* /*response*/, |
643 | + google::protobuf::Closure* done) |
644 | + { |
645 | + done->Run(); |
646 | + } |
647 | + void release_buffers( |
648 | + mir::protobuf::BufferRelease const* /*request*/, |
649 | + mir::protobuf::Void* /*response*/, |
650 | + google::protobuf::Closure* done) |
651 | + { |
652 | + done->Run(); |
653 | + } |
654 | |
655 | std::string application_name() const |
656 | { |
657 | |
658 | === modified file 'tests/unit-tests/client/test_mir_render_surface.cpp' |
659 | --- tests/unit-tests/client/test_mir_render_surface.cpp 2017-02-07 07:13:47 +0000 |
660 | +++ tests/unit-tests/client/test_mir_render_surface.cpp 2017-02-14 17:05:00 +0000 |
661 | @@ -28,6 +28,8 @@ |
662 | |
663 | #include "mir/test/fake_shared.h" |
664 | #include "mir/test/doubles/stub_client_buffer_factory.h" |
665 | +#include "mir/test/doubles/stub_client_platform_factory.h" |
666 | +#include "mir/test/doubles/mock_client_platform.h" |
667 | #include "mir_protobuf.pb.h" |
668 | |
669 | #include <sys/eventfd.h> |
670 | @@ -102,59 +104,6 @@ |
671 | mir::Fd pollable_fd; |
672 | }; |
673 | |
674 | -struct MockClientPlatform : public mcl::ClientPlatform |
675 | -{ |
676 | - MockClientPlatform() |
677 | - { |
678 | - auto native_window = std::make_shared<EGLNativeWindowType>(); |
679 | - *native_window = reinterpret_cast<EGLNativeWindowType>(this); |
680 | - |
681 | - ON_CALL(*this, create_buffer_factory()) |
682 | - .WillByDefault(Return(std::make_shared<mtd::StubClientBufferFactory>())); |
683 | - ON_CALL(*this, create_egl_native_window(_)) |
684 | - .WillByDefault(Return(native_window)); |
685 | - } |
686 | - |
687 | - void set_client_context(mcl::ClientContext* ctx) |
688 | - { |
689 | - client_context = ctx; |
690 | - } |
691 | - |
692 | - void populate(MirPlatformPackage& pkg) const override |
693 | - { |
694 | - client_context->populate_server_package(pkg); |
695 | - } |
696 | - |
697 | - MOCK_CONST_METHOD1(convert_native_buffer, MirNativeBuffer*(mir::graphics::NativeBuffer*)); |
698 | - MOCK_CONST_METHOD0(platform_type, MirPlatformType()); |
699 | - MOCK_METHOD1(platform_operation, MirPlatformMessage*(MirPlatformMessage const*)); |
700 | - MOCK_METHOD0(create_buffer_factory, std::shared_ptr<mcl::ClientBufferFactory>()); |
701 | - MOCK_METHOD2(use_egl_native_window, void(std::shared_ptr<void>, mcl::EGLNativeSurface*)); |
702 | - MOCK_METHOD1(create_egl_native_window, std::shared_ptr<void>(mcl::EGLNativeSurface*)); |
703 | - MOCK_METHOD0(create_egl_native_display, std::shared_ptr<EGLNativeDisplayType>()); |
704 | - MOCK_CONST_METHOD2(get_egl_pixel_format, MirPixelFormat(EGLDisplay, EGLConfig)); |
705 | - MOCK_METHOD2(request_interface, void*(char const*, int)); |
706 | - MOCK_CONST_METHOD1(native_format_for, uint32_t(MirPixelFormat)); |
707 | - MOCK_CONST_METHOD2(native_flags_for, uint32_t(MirBufferUsage, mir::geometry::Size)); |
708 | - |
709 | - mcl::ClientContext* client_context = nullptr; |
710 | -}; |
711 | - |
712 | -struct StubClientPlatformFactory : public mcl::ClientPlatformFactory |
713 | -{ |
714 | - StubClientPlatformFactory(std::shared_ptr<mcl::ClientPlatform> const& platform) |
715 | - : platform{platform} |
716 | - { |
717 | - } |
718 | - |
719 | - std::shared_ptr<mcl::ClientPlatform> create_client_platform(mcl::ClientContext*) |
720 | - { |
721 | - return platform; |
722 | - } |
723 | - |
724 | - std::shared_ptr<mcl::ClientPlatform> platform; |
725 | -}; |
726 | - |
727 | void connected_callback(MirConnection* /*connection*/, void* /*client_context*/) |
728 | { |
729 | } |
730 | @@ -178,7 +127,7 @@ |
731 | |
732 | std::shared_ptr<mcl::ClientPlatformFactory> the_client_platform_factory() override |
733 | { |
734 | - return std::make_shared<StubClientPlatformFactory>(platform); |
735 | + return std::make_shared<mtd::StubClientPlatformFactory>(platform); |
736 | } |
737 | |
738 | private: |
739 | @@ -190,7 +139,7 @@ |
740 | struct MirRenderSurfaceTest : public testing::Test |
741 | { |
742 | MirRenderSurfaceTest() |
743 | - : mock_platform{std::make_shared<testing::NiceMock<MockClientPlatform>>()}, |
744 | + : mock_platform{std::make_shared<testing::NiceMock<mtd::MockClientPlatform>>()}, |
745 | mock_channel{std::make_shared<testing::NiceMock<MockRpcChannel>>()}, |
746 | conf{mock_platform, mock_channel}, |
747 | connection{std::make_shared<MirConnection>(conf)} |
748 | @@ -198,7 +147,7 @@ |
749 | mock_platform->set_client_context(connection.get()); |
750 | } |
751 | |
752 | - std::shared_ptr<testing::NiceMock<MockClientPlatform>> const mock_platform; |
753 | + std::shared_ptr<testing::NiceMock<mtd::MockClientPlatform>> const mock_platform; |
754 | std::shared_ptr<testing::NiceMock<MockRpcChannel>> const mock_channel; |
755 | TestConnectionConfiguration conf; |
756 | std::shared_ptr<MirConnection> const connection; |
757 | |
758 | === modified file 'tests/unit-tests/platforms/nested/CMakeLists.txt' |
759 | --- tests/unit-tests/platforms/nested/CMakeLists.txt 2017-01-30 08:13:20 +0000 |
760 | +++ tests/unit-tests/platforms/nested/CMakeLists.txt 2017-02-14 17:05:00 +0000 |
761 | @@ -6,6 +6,7 @@ |
762 | ${CMAKE_CURRENT_SOURCE_DIR}/test_buffer.cpp |
763 | ${CMAKE_CURRENT_SOURCE_DIR}/test_nested_display_buffer.cpp |
764 | ${CMAKE_CURRENT_SOURCE_DIR}/test_ipc_operations.cpp |
765 | + ${CMAKE_CURRENT_SOURCE_DIR}/test_host_buffer.cpp |
766 | $<TARGET_OBJECTS:mir-test-doubles-udev> |
767 | ${MIR_PLATFORM_OBJECTS} |
768 | ${MIR_SERVER_OBJECTS} |
769 | |
770 | === added file 'tests/unit-tests/platforms/nested/test_host_buffer.cpp' |
771 | --- tests/unit-tests/platforms/nested/test_host_buffer.cpp 1970-01-01 00:00:00 +0000 |
772 | +++ tests/unit-tests/platforms/nested/test_host_buffer.cpp 2017-02-14 17:05:00 +0000 |
773 | @@ -0,0 +1,127 @@ |
774 | +/* |
775 | + * Copyright © 2017 Canonical Ltd. |
776 | + * |
777 | + * This program is free software: you can redistribute it and/or modify |
778 | + * it under the terms of the GNU General Public License version 3 as |
779 | + * published by the Free Software Foundation. |
780 | + * |
781 | + * This program is distributed in the hope that it will be useful, |
782 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
783 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
784 | + * GNU General Public License for more details. |
785 | + * |
786 | + * You should have received a copy of the GNU General Public License |
787 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
788 | + * |
789 | + * Authored by: Kevin DuBois <kevin.dubois@canonical.com> |
790 | + */ |
791 | + |
792 | +#include "src/server/graphics/nested/host_buffer.h" |
793 | +#include "src/client/default_connection_configuration.h" |
794 | +#include "src/client/mir_connection.h" |
795 | +#include "src/client/buffer_factory.h" |
796 | +#include "src/client/buffer.h" |
797 | +#include "mir/test/stub_server_tool.h" |
798 | +#include "mir/test/test_protobuf_server.h" |
799 | +#include "mir/test/doubles/stub_client_platform_factory.h" |
800 | +#include "mir/test/doubles/mock_client_platform.h" |
801 | +#include "mir/frontend/connector.h" |
802 | +#include <gtest/gtest.h> |
803 | +#include <gmock/gmock.h> |
804 | +#include <fcntl.h> |
805 | + |
806 | +using namespace testing; |
807 | +namespace mgn = mir::graphics::nested; |
808 | +namespace mt = mir::test; |
809 | +namespace mcl = mir::client; |
810 | +namespace mtd = mir::test::doubles; |
811 | + |
812 | +std::unique_ptr<mir::Fd> fd = nullptr; |
813 | +int get_fence(MirBuffer*) |
814 | +{ |
815 | + if (fd) |
816 | + return *fd; |
817 | + return -1; |
818 | +} |
819 | + |
820 | +struct TestConnectionConfiguration : mir::client::DefaultConnectionConfiguration |
821 | +{ |
822 | +public: |
823 | + |
824 | + TestConnectionConfiguration(std::string const& socket) |
825 | + : DefaultConnectionConfiguration(socket) |
826 | + { |
827 | + } |
828 | + |
829 | + std::shared_ptr<mcl::ClientPlatformFactory> the_client_platform_factory() override |
830 | + { |
831 | + auto platform = std::make_shared<mtd::MockClientPlatform>(); |
832 | + ON_CALL(*platform, request_interface(StrEq("mir_extension_fenced_buffers"), 1)) |
833 | + .WillByDefault(Return(&fence_ext)); |
834 | + return std::make_shared<mtd::StubClientPlatformFactory>(platform); |
835 | + } |
836 | + |
837 | + MirExtensionFencedBuffersV1 fence_ext{get_fence, nullptr, nullptr}; |
838 | + |
839 | + std::shared_ptr<mir::client::AsyncBufferFactory> the_buffer_factory() override |
840 | + { |
841 | + struct StubBufferFactory : mcl::AsyncBufferFactory |
842 | + { |
843 | + std::shared_ptr<mcl::Buffer> buffer; |
844 | + std::unique_ptr<mcl::MirBuffer> generate_buffer(mir::protobuf::Buffer const&) override |
845 | + { |
846 | + return nullptr; |
847 | + } |
848 | + void expect_buffer( |
849 | + std::shared_ptr<mcl::ClientBufferFactory> const&, |
850 | + MirConnection* conn, mir::geometry::Size, |
851 | + MirPixelFormat, MirBufferUsage usage, MirBufferCallback cb, void* ctx) override |
852 | + { |
853 | + if (!buffer) |
854 | + buffer = std::make_shared<mcl::Buffer>(cb, ctx, 1, nullptr, conn, usage); |
855 | + cb(reinterpret_cast<MirBuffer*>(buffer.get()), ctx); |
856 | + } |
857 | + void expect_buffer( |
858 | + std::shared_ptr<mcl::ClientBufferFactory> const&, |
859 | + MirConnection*, mir::geometry::Size, uint32_t, uint32_t, |
860 | + MirBufferCallback, void*) override |
861 | + { |
862 | + } |
863 | + void cancel_requests_with_context(void*) {} |
864 | + }; |
865 | + return std::make_shared<StubBufferFactory>(); |
866 | + } |
867 | +}; |
868 | + |
869 | +struct HostBuffer : Test |
870 | +{ |
871 | + HostBuffer() |
872 | + { |
873 | + //MirConnection is hard to stub |
874 | + std::remove(socket.c_str()); |
875 | + test_server = std::make_shared<mt::TestProtobufServer>(socket, server_tool); |
876 | + test_server->comm->start(); |
877 | + config = std::make_shared<TestConnectionConfiguration>(socket); |
878 | + } |
879 | + |
880 | + std::string const socket { "./test_sock" }; |
881 | + std::shared_ptr<mt::StubServerTool> const server_tool = std::make_shared<mt::StubServerTool>(); |
882 | + std::shared_ptr<mt::TestProtobufServer> test_server; |
883 | + std::shared_ptr<TestConnectionConfiguration> config; |
884 | +}; |
885 | + |
886 | +//LP: #1664562 |
887 | +TEST_F(HostBuffer, does_not_own_fd_when_accessing_fence) |
888 | +{ |
889 | + fd = std::make_unique<mir::Fd>( fileno(tmpfile()) ); |
890 | + |
891 | + MirConnection connection{*config}; |
892 | + connection.connect("", [](auto*, auto*){}, nullptr)->wait_for_all(); |
893 | + mgn::HostBuffer buffer(&connection, mir::geometry::Size{1,1}, mir_pixel_format_abgr_8888); |
894 | + { |
895 | + auto fence = buffer.fence(); |
896 | + EXPECT_THAT(fence, Eq(*fd)); |
897 | + } |
898 | + EXPECT_THAT(fcntl(*fd, F_GETFD), Eq(0)); |
899 | + fd.reset(); |
900 | +} |
PASSED: Continuous integration, rev:4029 /mir-jenkins. ubuntu. com/job/ mir-ci/ 2995/ /mir-jenkins. ubuntu. com/job/ build-mir/ 3990 /mir-jenkins. ubuntu. com/job/ build-0- fetch/4076 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= vivid+overlay/ 4066 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= xenial+ overlay/ 4066 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= zesty/4066 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= clang,platform= mesa,release= zesty/4017 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= clang,platform= mesa,release= zesty/4017/ artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= xenial+ overlay/ 4017 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= xenial+ overlay/ 4017/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= zesty/4017 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= zesty/4017/ artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= android, release= vivid+overlay/ 4017 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= android, release= vivid+overlay/ 4017/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= android, release= vivid+overlay/ 4017 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= android, release= vivid+overlay/ 4017/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= mesa,release= xenial+ overlay/ 4017 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= mesa,release= xenial+ overlay/ 4017/artifact/ output/ *zip*/output. zip
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild: /mir-jenkins. ubuntu. com/job/ mir-ci/ 2995/rebuild
https:/