Merge lp:~kdub/mir/interval0-signal into lp:~mir-team/mir/trunk
- interval0-signal
- Merge into trunk
Status: | Superseded | ||||
---|---|---|---|---|---|
Proposed branch: | lp:~kdub/mir/interval0-signal | ||||
Merge into: | lp:~mir-team/mir/trunk | ||||
Diff against target: |
1401 lines (+687/-108) 43 files modified
include/client/mir_toolkit/mir_client_library.h (+18/-0) include/server/mir/compositor/buffer_allocation_strategy.h (+1/-1) include/server/mir/compositor/buffer_stream_surfaces.h (+1/-0) include/server/mir/compositor/swapper_factory.h (+6/-2) include/server/mir/graphics/gl_renderer.h (+0/-1) include/server/mir/graphics/renderer.h (+0/-1) include/server/mir/shell/surface.h (+1/-0) include/server/mir/surfaces/buffer_stream.h (+1/-0) include/server/mir/surfaces/surface.h (+2/-0) include/shared/mir/graphics/android/mir_native_buffer.h (+59/-0) include/shared/mir_toolkit/common.h (+7/-0) include/test/mir_test_doubles/mock_buffer_stream.h (+2/-0) include/test/mir_test_doubles/mock_surface_renderer.h (+1/-2) include/test/mir_test_doubles/mock_swapper_factory.h (+2/-2) include/test/mir_test_doubles/null_buffer_stream.h (+4/-0) src/client/android/android_client_buffer.cpp (+29/-11) src/client/mir_client_library.cpp (+32/-0) src/client/mir_surface.cpp (+2/-0) src/server/compositor/buffer_stream_surfaces.cpp (+4/-0) src/server/compositor/rendering_operator.cpp (+0/-1) src/server/compositor/swapper_factory.cpp (+35/-9) src/server/compositor/switching_bundle.cpp (+2/-2) src/server/graphics/android/android_alloc_adaptor.cpp (+8/-19) src/server/graphics/gl_renderer.cpp (+0/-8) src/server/shell/surface.cpp (+14/-1) src/server/surfaces/surface.cpp (+5/-0) src/shared/graphics/android/CMakeLists.txt (+1/-0) src/shared/graphics/android/mir_native_buffer.cpp (+73/-0) tests/acceptance-tests/test_server_shutdown.cpp (+0/-3) tests/integration-tests/CMakeLists.txt (+1/-0) tests/integration-tests/test_surface_first_frame_sync.cpp (+0/-2) tests/integration-tests/test_swapinterval.cpp (+226/-0) tests/mir_test_framework/testing_server_options.cpp (+0/-4) tests/unit-tests/client/android/test_client_android_buffer.cpp (+2/-2) tests/unit-tests/compositor/test_buffer_stream.cpp (+9/-0) tests/unit-tests/compositor/test_rendering_operator.cpp (+0/-12) tests/unit-tests/compositor/test_swapper_factory.cpp (+50/-2) tests/unit-tests/compositor/test_switching_bundle.cpp (+3/-3) tests/unit-tests/graphics/android/CMakeLists.txt (+1/-0) tests/unit-tests/graphics/android/test_android_alloc_adaptor.cpp (+3/-10) tests/unit-tests/graphics/android/test_external_refcount.cpp (+70/-0) tests/unit-tests/graphics/test_gl_renderer.cpp (+0/-10) tests/unit-tests/surfaces/test_surface.cpp (+12/-0) |
||||
To merge this branch: | bzr merge lp:~kdub/mir/interval0-signal | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Approve | |
Mir development team | Pending | ||
Review via email: mp+169941@code.launchpad.net |
This proposal has been superseded by a proposal from 2013-06-19.
Commit message
Activate sending a "swapinterval" signal over IPC. Add client api for software clients to request different swapintervals. (eglSwapInterval is not glued together just yet). Currently only swapinterval of 0 or 1 is supported.
Description of the change
Activate sending a "swapinterval" signal over IPC. Add client api for software clients to request different swapintervals. (eglSwapInterval is not glued together just yet)
Currently only swapinterval of 0 or 1 is supported.
note that the actual path taken over ipc is via the surface parameters, there is no new protobuf message introduced to support the message.
tests/integrati
still in pre-review, dependent on anativewindow-
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:758
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
UNSTABLE: http://
Click here to trigger a rebuild:
http://
Preview Diff
1 | === modified file 'include/client/mir_toolkit/mir_client_library.h' |
2 | --- include/client/mir_toolkit/mir_client_library.h 2013-06-06 08:36:17 +0000 |
3 | +++ include/client/mir_toolkit/mir_client_library.h 2013-06-19 18:36:29 +0000 |
4 | @@ -293,6 +293,24 @@ |
5 | */ |
6 | MirSurfaceState mir_surface_get_state(MirSurface *surface); |
7 | |
8 | +/** |
9 | + * Set the swapinterval for mir_surface_swap_buffers. EGL users should use |
10 | + * eglSwapInterval directly. |
11 | + * \param [in] surface The surface to operate on |
12 | + * \param [in] interval The number of vblank signals that |
13 | + * mir_surface_swap_buffers will wait for |
14 | + * \return A wait handle that can be passed to mir_wait_for |
15 | + */ |
16 | +MirWaitHandle* mir_surface_set_swapinterval(MirSurface* surface, int interval); |
17 | + |
18 | +/** |
19 | + * Query the swapinterval that the surface is operating with. |
20 | + * The default interval is 1. |
21 | + * \param [in] surface The surface to operate on |
22 | + * \return The swapinterval value that the client is operating with |
23 | + */ |
24 | +int mir_surface_get_swapinterval(MirSurface* surface); |
25 | + |
26 | #ifdef __cplusplus |
27 | } |
28 | /**@}*/ |
29 | |
30 | === modified file 'include/server/mir/compositor/buffer_allocation_strategy.h' |
31 | --- include/server/mir/compositor/buffer_allocation_strategy.h 2013-06-11 14:27:33 +0000 |
32 | +++ include/server/mir/compositor/buffer_allocation_strategy.h 2013-06-19 18:36:29 +0000 |
33 | @@ -45,7 +45,7 @@ |
34 | class BufferAllocationStrategy |
35 | { |
36 | public: |
37 | - virtual std::shared_ptr<BufferSwapper> create_swapper_reuse_buffers( |
38 | + virtual std::shared_ptr<BufferSwapper> create_swapper_reuse_buffers(BufferProperties const&, |
39 | std::vector<std::shared_ptr<Buffer>>&, size_t, SwapperType) const = 0; |
40 | virtual std::shared_ptr<BufferSwapper> create_swapper_new_buffers( |
41 | BufferProperties& actual_properties, BufferProperties const& requested_properties, SwapperType) const = 0; |
42 | |
43 | === modified file 'include/server/mir/compositor/buffer_stream_surfaces.h' |
44 | --- include/server/mir/compositor/buffer_stream_surfaces.h 2013-06-18 09:44:11 +0000 |
45 | +++ include/server/mir/compositor/buffer_stream_surfaces.h 2013-06-19 18:36:29 +0000 |
46 | @@ -47,6 +47,7 @@ |
47 | |
48 | geometry::PixelFormat get_stream_pixel_format(); |
49 | geometry::Size stream_size(); |
50 | + void allow_framedropping(bool); |
51 | void force_requests_to_complete(); |
52 | |
53 | protected: |
54 | |
55 | === modified file 'include/server/mir/compositor/swapper_factory.h' |
56 | --- include/server/mir/compositor/swapper_factory.h 2013-06-11 15:05:27 +0000 |
57 | +++ include/server/mir/compositor/swapper_factory.h 2013-06-19 18:36:29 +0000 |
58 | @@ -38,14 +38,18 @@ |
59 | std::shared_ptr<GraphicBufferAllocator> const& gr_alloc, |
60 | int number_of_buffers); |
61 | |
62 | - std::shared_ptr<BufferSwapper> create_swapper_reuse_buffers( |
63 | + std::shared_ptr<BufferSwapper> create_swapper_reuse_buffers(BufferProperties const&, |
64 | std::vector<std::shared_ptr<Buffer>>&, size_t, SwapperType) const; |
65 | std::shared_ptr<BufferSwapper> create_swapper_new_buffers( |
66 | BufferProperties& actual_properties, BufferProperties const& requested_properties, SwapperType) const; |
67 | |
68 | private: |
69 | + void change_swapper_size( |
70 | + std::vector<std::shared_ptr<Buffer>>&, size_t const, size_t, BufferProperties const&) const; |
71 | + |
72 | std::shared_ptr<GraphicBufferAllocator> const gr_allocator; |
73 | - int const number_of_buffers; |
74 | + unsigned int const synchronous_number_of_buffers; |
75 | + unsigned int const spin_number_of_buffers; |
76 | }; |
77 | } |
78 | } |
79 | |
80 | === modified file 'include/server/mir/graphics/gl_renderer.h' |
81 | --- include/server/mir/graphics/gl_renderer.h 2013-05-21 15:11:41 +0000 |
82 | +++ include/server/mir/graphics/gl_renderer.h 2013-06-19 18:36:29 +0000 |
83 | @@ -37,7 +37,6 @@ |
84 | |
85 | /* From renderer */ |
86 | void render(std::function<void(std::shared_ptr<void> const&)> save_resource, Renderable& renderable); |
87 | - void ensure_no_live_buffers_bound(); |
88 | void clear(); |
89 | |
90 | ~GLRenderer() noexcept {} |
91 | |
92 | === modified file 'include/server/mir/graphics/renderer.h' |
93 | --- include/server/mir/graphics/renderer.h 2013-05-21 15:11:41 +0000 |
94 | +++ include/server/mir/graphics/renderer.h 2013-06-19 18:36:29 +0000 |
95 | @@ -36,7 +36,6 @@ |
96 | |
97 | virtual void clear() = 0; |
98 | virtual void render(std::function<void(std::shared_ptr<void> const&)> save_resource, Renderable& renderable) = 0; |
99 | - virtual void ensure_no_live_buffers_bound() = 0; |
100 | |
101 | protected: |
102 | Renderer() = default; |
103 | |
104 | === modified file 'include/server/mir/shell/surface.h' |
105 | --- include/server/mir/shell/surface.h 2013-06-17 19:47:07 +0000 |
106 | +++ include/server/mir/shell/surface.h 2013-06-19 18:36:29 +0000 |
107 | @@ -87,6 +87,7 @@ |
108 | |
109 | virtual void take_input_focus(std::shared_ptr<InputTargeter> const& targeter); |
110 | |
111 | + virtual void allow_framedropping(bool); |
112 | private: |
113 | bool set_type(MirSurfaceType t); // Use configure() to make public changes |
114 | bool set_state(MirSurfaceState s); |
115 | |
116 | === modified file 'include/server/mir/surfaces/buffer_stream.h' |
117 | --- include/server/mir/surfaces/buffer_stream.h 2013-06-13 10:40:42 +0000 |
118 | +++ include/server/mir/surfaces/buffer_stream.h 2013-06-19 18:36:29 +0000 |
119 | @@ -44,6 +44,7 @@ |
120 | virtual std::shared_ptr<surfaces::GraphicRegion> lock_back_buffer() = 0; |
121 | virtual geometry::PixelFormat get_stream_pixel_format() = 0; |
122 | virtual geometry::Size stream_size() = 0; |
123 | + virtual void allow_framedropping(bool) = 0; |
124 | virtual void force_requests_to_complete() = 0; |
125 | }; |
126 | |
127 | |
128 | === modified file 'include/server/mir/surfaces/surface.h' |
129 | --- include/server/mir/surfaces/surface.h 2013-06-12 15:36:31 +0000 |
130 | +++ include/server/mir/surfaces/surface.h 2013-06-19 18:36:29 +0000 |
131 | @@ -83,6 +83,8 @@ |
132 | bool supports_input() const; |
133 | int client_input_fd() const; |
134 | int server_input_fd() const; |
135 | + |
136 | + void allow_framedropping(bool); |
137 | private: |
138 | std::string surface_name; |
139 | geometry::Point top_left_point; |
140 | |
141 | === added file 'include/shared/mir/graphics/android/mir_native_buffer.h' |
142 | --- include/shared/mir/graphics/android/mir_native_buffer.h 1970-01-01 00:00:00 +0000 |
143 | +++ include/shared/mir/graphics/android/mir_native_buffer.h 2013-06-19 18:36:29 +0000 |
144 | @@ -0,0 +1,59 @@ |
145 | +/* |
146 | + * Copyright © 2013 Canonical Ltd. |
147 | + * |
148 | + * This program is free software: you can redistribute it and/or modify it |
149 | + * under the terms of the GNU Lesser General Public License version 3, |
150 | + * as published by the Free Software Foundation. |
151 | + * |
152 | + * This program is distributed in the hope that it will be useful, |
153 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
154 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
155 | + * GNU Lesser General Public License for more details. |
156 | + * |
157 | + * You should have received a copy of the GNU Lesser General Public License |
158 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
159 | + * |
160 | + * Authored by: Kevin DuBois <kevin.dubois@canonical.com> |
161 | + */ |
162 | + |
163 | +#ifndef MIR_GRAPHICS_ANDROID_MIR_NATIVE_BUFFER_H_ |
164 | +#define MIR_GRAPHICS_ANDROID_MIR_NATIVE_BUFFER_H_ |
165 | + |
166 | +#include <system/window.h> |
167 | +#include <functional> |
168 | +#include <atomic> |
169 | + |
170 | +namespace mir |
171 | +{ |
172 | +namespace graphics |
173 | +{ |
174 | +namespace android |
175 | +{ |
176 | +struct MirNativeBuffer : public ANativeWindowBuffer |
177 | +{ |
178 | + MirNativeBuffer(std::function<void(MirNativeBuffer*)> free); |
179 | + void driver_reference(); |
180 | + void driver_dereference(); |
181 | + void mir_dereference(); |
182 | + |
183 | +private: |
184 | + ~MirNativeBuffer(); |
185 | + |
186 | + std::function<void(MirNativeBuffer*)> free_fn; |
187 | + std::atomic<bool> mir_reference; |
188 | + std::atomic<int> driver_references; |
189 | + |
190 | +}; |
191 | + |
192 | +struct MirNativeBufferDeleter |
193 | +{ |
194 | + void operator()(MirNativeBuffer* a) |
195 | + { |
196 | + a->mir_dereference(); |
197 | + } |
198 | +}; |
199 | +} |
200 | +} |
201 | +} |
202 | + |
203 | +#endif /* MIR_GRAPHICS_ANDROID_MIR_NATIVE_BUFFER_H_ */ |
204 | |
205 | === modified file 'include/shared/mir_toolkit/common.h' |
206 | --- include/shared/mir_toolkit/common.h 2013-05-03 22:53:42 +0000 |
207 | +++ include/shared/mir_toolkit/common.h 2013-06-19 18:36:29 +0000 |
208 | @@ -35,6 +35,7 @@ |
209 | { |
210 | mir_surface_attrib_type, |
211 | mir_surface_attrib_state, |
212 | + mir_surface_attrib_performance_hint, |
213 | mir_surface_attrib_arraysize_ |
214 | } MirSurfaceAttrib; |
215 | |
216 | @@ -63,6 +64,12 @@ |
217 | mir_surface_state_arraysize_ |
218 | } MirSurfaceState; |
219 | |
220 | +typedef enum MirSurfacePerformanceHint |
221 | +{ |
222 | + mir_surface_hint_synchronous, |
223 | + mir_surface_hint_drop_frames, |
224 | + mir_surface_hint_arraysize_ |
225 | +} MirSurfacePerformanceHint; |
226 | /**@}*/ |
227 | |
228 | #endif |
229 | |
230 | === modified file 'include/test/mir_test_doubles/mock_buffer_stream.h' |
231 | --- include/test/mir_test_doubles/mock_buffer_stream.h 2013-06-13 10:40:42 +0000 |
232 | +++ include/test/mir_test_doubles/mock_buffer_stream.h 2013-06-19 18:36:29 +0000 |
233 | @@ -36,6 +36,8 @@ |
234 | |
235 | MOCK_METHOD0(get_stream_pixel_format, geometry::PixelFormat()); |
236 | MOCK_METHOD0(stream_size, geometry::Size()); |
237 | + MOCK_METHOD0(force_client_completion, void()); |
238 | + MOCK_METHOD1(allow_framedropping, void(bool)); |
239 | MOCK_METHOD0(force_requests_to_complete, void()); |
240 | }; |
241 | } |
242 | |
243 | === modified file 'include/test/mir_test_doubles/mock_surface_renderer.h' |
244 | --- include/test/mir_test_doubles/mock_surface_renderer.h 2013-05-21 15:11:41 +0000 |
245 | +++ include/test/mir_test_doubles/mock_surface_renderer.h 2013-06-19 18:36:29 +0000 |
246 | @@ -32,8 +32,7 @@ |
247 | struct MockSurfaceRenderer : public graphics::Renderer |
248 | { |
249 | MOCK_METHOD2(render, void(std::function<void(std::shared_ptr<void> const&)>, graphics::Renderable&)); |
250 | - MOCK_METHOD0(ensure_no_live_buffers_bound, void()); |
251 | - MOCK_METHOD0(clear, void ()); |
252 | + MOCK_METHOD0(clear, void()); |
253 | |
254 | ~MockSurfaceRenderer() noexcept {} |
255 | }; |
256 | |
257 | === modified file 'include/test/mir_test_doubles/mock_swapper_factory.h' |
258 | --- include/test/mir_test_doubles/mock_swapper_factory.h 2013-06-11 14:27:33 +0000 |
259 | +++ include/test/mir_test_doubles/mock_swapper_factory.h 2013-06-19 18:36:29 +0000 |
260 | @@ -33,8 +33,8 @@ |
261 | public: |
262 | ~MockSwapperFactory() noexcept {} |
263 | |
264 | - MOCK_CONST_METHOD3(create_swapper_reuse_buffers, |
265 | - std::shared_ptr<compositor::BufferSwapper>( |
266 | + MOCK_CONST_METHOD4(create_swapper_reuse_buffers, |
267 | + std::shared_ptr<compositor::BufferSwapper>(compositor::BufferProperties const&, |
268 | std::vector<std::shared_ptr<compositor::Buffer>>&, size_t, compositor::SwapperType)); |
269 | MOCK_CONST_METHOD3(create_swapper_new_buffers, |
270 | std::shared_ptr<compositor::BufferSwapper>( |
271 | |
272 | === modified file 'include/test/mir_test_doubles/null_buffer_stream.h' |
273 | --- include/test/mir_test_doubles/null_buffer_stream.h 2013-06-13 10:40:42 +0000 |
274 | +++ include/test/mir_test_doubles/null_buffer_stream.h 2013-06-19 18:36:29 +0000 |
275 | @@ -60,6 +60,10 @@ |
276 | { |
277 | } |
278 | |
279 | + void allow_framedropping(bool) |
280 | + { |
281 | + } |
282 | + |
283 | std::shared_ptr<compositor::Buffer> stub_buffer; |
284 | }; |
285 | |
286 | |
287 | === modified file 'src/client/android/android_client_buffer.cpp' |
288 | --- src/client/android/android_client_buffer.cpp 2013-06-12 09:36:20 +0000 |
289 | +++ src/client/android/android_client_buffer.cpp 2013-06-19 18:36:29 +0000 |
290 | @@ -16,6 +16,7 @@ |
291 | * Authored by: Kevin DuBois<kevin.dubois@canonical.com> |
292 | */ |
293 | |
294 | +#include "mir/graphics/android/mir_native_buffer.h" |
295 | #include "mir_toolkit/mir_client_library.h" |
296 | #include "android_client_buffer.h" |
297 | |
298 | @@ -23,6 +24,23 @@ |
299 | namespace mcl=mir::client; |
300 | namespace mcla=mir::client::android; |
301 | namespace geom=mir::geometry; |
302 | +namespace mga=mir::graphics::android; |
303 | +namespace |
304 | +{ |
305 | +struct AndroidBufferHandleDeleter |
306 | +{ |
307 | + AndroidBufferHandleDeleter(std::shared_ptr<mcla::AndroidRegistrar> const& alloc_dev) |
308 | + : buffer_registrar(alloc_dev) |
309 | + {} |
310 | + |
311 | + void operator()(mga::MirNativeBuffer* t) |
312 | + { |
313 | + buffer_registrar->unregister_buffer(t->handle); |
314 | + } |
315 | +private: |
316 | + std::shared_ptr<mcla::AndroidRegistrar> const buffer_registrar; |
317 | +}; |
318 | +} |
319 | |
320 | mcla::AndroidClientBuffer::AndroidClientBuffer(std::shared_ptr<AndroidRegistrar> const& registrar, |
321 | std::shared_ptr<MirBufferPackage> const& package, |
322 | @@ -30,20 +48,24 @@ |
323 | : creation_package(package), |
324 | buffer_registrar(registrar), |
325 | rect({{geom::X(0),geom::Y(0)}, size}), |
326 | - buffer_pf(pf), |
327 | - native_window_buffer(std::make_shared<ANativeWindowBuffer>()) |
328 | + buffer_pf(pf) |
329 | { |
330 | - creation_package = std::move(package); |
331 | + AndroidBufferHandleDeleter del1(registrar); |
332 | + auto tmp = new mga::MirNativeBuffer(del1); |
333 | + mga::MirNativeBufferDeleter del; |
334 | + native_window_buffer = std::shared_ptr<mga::MirNativeBuffer>(tmp, del); |
335 | native_handle = std::shared_ptr<const native_handle_t> (convert_to_native_handle(creation_package)); |
336 | |
337 | - buffer_registrar->register_buffer(native_handle.get()); |
338 | + try{ |
339 | + buffer_registrar->register_buffer(native_handle.get()); |
340 | + } catch (...) |
341 | + { |
342 | + //TODO: log failure |
343 | + } |
344 | |
345 | pack_native_window_buffer(); |
346 | } |
347 | |
348 | -static void incRef(android_native_base_t*) |
349 | -{ |
350 | -} |
351 | void mcla::AndroidClientBuffer::pack_native_window_buffer() |
352 | { |
353 | native_window_buffer->height = static_cast<int32_t>(rect.size.height.as_uint32_t()); |
354 | @@ -51,15 +73,11 @@ |
355 | native_window_buffer->stride = creation_package->stride / |
356 | geom::bytes_per_pixel(buffer_pf); |
357 | native_window_buffer->usage = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_RENDER; |
358 | - |
359 | native_window_buffer->handle = native_handle.get(); |
360 | - native_window_buffer->common.incRef = &incRef; |
361 | - native_window_buffer->common.decRef = &incRef; |
362 | } |
363 | |
364 | mcla::AndroidClientBuffer::~AndroidClientBuffer() noexcept |
365 | { |
366 | - buffer_registrar->unregister_buffer(native_handle.get()); |
367 | } |
368 | |
369 | const native_handle_t* mcla::AndroidClientBuffer::convert_to_native_handle(const std::shared_ptr<MirBufferPackage>& package) |
370 | |
371 | === modified file 'src/client/mir_client_library.cpp' |
372 | --- src/client/mir_client_library.cpp 2013-06-06 08:36:17 +0000 |
373 | +++ src/client/mir_client_library.cpp 2013-06-19 18:36:29 +0000 |
374 | @@ -316,3 +316,35 @@ |
375 | |
376 | return state; |
377 | } |
378 | + |
379 | +MirWaitHandle* mir_surface_set_swapinterval(MirSurface* surf, int interval) |
380 | +{ |
381 | + int hint = mir_surface_hint_synchronous; |
382 | + switch (interval) |
383 | + { |
384 | + case 0: |
385 | + hint = mir_surface_hint_drop_frames; |
386 | + break; |
387 | + case 1: |
388 | + hint = mir_surface_hint_synchronous; |
389 | + break; |
390 | + default: |
391 | + return NULL; |
392 | + } |
393 | + |
394 | + return surf ? surf->configure(mir_surface_attrib_performance_hint, hint) : NULL; |
395 | +} |
396 | + |
397 | +int mir_surface_get_swapinterval(MirSurface* surf) |
398 | +{ |
399 | + if (!surf) |
400 | + return -1; |
401 | + |
402 | + int s = surf->attrib(mir_surface_attrib_performance_hint); |
403 | + if (s == mir_surface_hint_synchronous) |
404 | + return 1; |
405 | + if (s == mir_surface_hint_drop_frames) |
406 | + return 0; |
407 | + |
408 | + return -1; |
409 | +} |
410 | |
411 | === modified file 'src/client/mir_surface.cpp' |
412 | --- src/client/mir_surface.cpp 2013-06-07 10:38:34 +0000 |
413 | +++ src/client/mir_surface.cpp 2013-06-19 18:36:29 +0000 |
414 | @@ -58,6 +58,7 @@ |
415 | attrib_cache[i] = -1; |
416 | attrib_cache[mir_surface_attrib_type] = mir_surface_type_normal; |
417 | attrib_cache[mir_surface_attrib_state] = mir_surface_state_unknown; |
418 | + attrib_cache[mir_surface_attrib_performance_hint] = mir_surface_hint_synchronous; |
419 | } |
420 | |
421 | MirSurface::~MirSurface() |
422 | @@ -269,6 +270,7 @@ |
423 | { |
424 | case mir_surface_attrib_type: |
425 | case mir_surface_attrib_state: |
426 | + case mir_surface_attrib_performance_hint: |
427 | if (configure_result.has_ivalue()) |
428 | attrib_cache[a] = configure_result.ivalue(); |
429 | else |
430 | |
431 | === modified file 'src/server/compositor/buffer_stream_surfaces.cpp' |
432 | --- src/server/compositor/buffer_stream_surfaces.cpp 2013-06-18 09:44:11 +0000 |
433 | +++ src/server/compositor/buffer_stream_surfaces.cpp 2013-06-19 18:36:29 +0000 |
434 | @@ -64,3 +64,7 @@ |
435 | buffer_bundle->force_requests_to_complete(); |
436 | } |
437 | |
438 | +void mc::BufferStreamSurfaces::allow_framedropping(bool allow) |
439 | +{ |
440 | + buffer_bundle->allow_framedropping(allow); |
441 | +} |
442 | |
443 | === modified file 'src/server/compositor/rendering_operator.cpp' |
444 | --- src/server/compositor/rendering_operator.cpp 2013-05-22 09:56:40 +0000 |
445 | +++ src/server/compositor/rendering_operator.cpp 2013-06-19 18:36:29 +0000 |
446 | @@ -30,7 +30,6 @@ |
447 | |
448 | mc::RenderingOperator::~RenderingOperator() |
449 | { |
450 | - renderer.ensure_no_live_buffers_bound(); |
451 | } |
452 | |
453 | void mc::RenderingOperator::operator()(graphics::Renderable& renderable) |
454 | |
455 | === modified file 'src/server/compositor/swapper_factory.cpp' |
456 | --- src/server/compositor/swapper_factory.cpp 2013-06-11 19:55:10 +0000 |
457 | +++ src/server/compositor/swapper_factory.cpp 2013-06-19 18:36:29 +0000 |
458 | @@ -36,7 +36,8 @@ |
459 | std::shared_ptr<GraphicBufferAllocator> const& gr_alloc, |
460 | int number_of_buffers) |
461 | : gr_allocator(gr_alloc), |
462 | - number_of_buffers(number_of_buffers) |
463 | + synchronous_number_of_buffers(number_of_buffers), |
464 | + spin_number_of_buffers(3) //spin algorithm always takes 3 buffers |
465 | { |
466 | } |
467 | |
468 | @@ -46,16 +47,42 @@ |
469 | { |
470 | } |
471 | |
472 | +void mc::SwapperFactory::change_swapper_size( |
473 | + std::vector<std::shared_ptr<mc::Buffer>>& list, |
474 | + size_t const desired_size, size_t current_size, BufferProperties const& buffer_properties) const |
475 | +{ |
476 | + while (current_size < desired_size) |
477 | + { |
478 | + list.push_back(gr_allocator->alloc_buffer(buffer_properties)); |
479 | + current_size++; |
480 | + } |
481 | + |
482 | + while (current_size > desired_size) |
483 | + { |
484 | + if (list.empty()) |
485 | + { |
486 | + BOOST_THROW_EXCEPTION(std::logic_error("SwapperFactory could not change algorithm")); |
487 | + } else |
488 | + { |
489 | + list.pop_back(); |
490 | + current_size--; |
491 | + } |
492 | + } |
493 | +} |
494 | + |
495 | std::shared_ptr<mc::BufferSwapper> mc::SwapperFactory::create_swapper_reuse_buffers( |
496 | - std::vector<std::shared_ptr<Buffer>>& list, size_t buffer_num, SwapperType type) const |
497 | + BufferProperties const& buffer_properties, std::vector<std::shared_ptr<Buffer>>& list, |
498 | + size_t buffer_num, SwapperType type) const |
499 | { |
500 | if (type == mc::SwapperType::synchronous) |
501 | { |
502 | - return std::make_shared<mc::BufferSwapperMulti>(list, buffer_num); |
503 | + change_swapper_size(list, synchronous_number_of_buffers, buffer_num, buffer_properties); |
504 | + return std::make_shared<mc::BufferSwapperMulti>(list, synchronous_number_of_buffers); |
505 | } |
506 | else |
507 | { |
508 | - return std::make_shared<mc::BufferSwapperSpin>(list, buffer_num); |
509 | + change_swapper_size(list, spin_number_of_buffers, buffer_num, buffer_properties); |
510 | + return std::make_shared<mc::BufferSwapperSpin>(list, spin_number_of_buffers); |
511 | } |
512 | } |
513 | |
514 | @@ -68,20 +95,19 @@ |
515 | |
516 | if (type == mc::SwapperType::synchronous) |
517 | { |
518 | - for(auto i=0; i< number_of_buffers; i++) |
519 | + for(auto i=0u; i< synchronous_number_of_buffers; i++) |
520 | { |
521 | list.push_back(gr_allocator->alloc_buffer(requested_buffer_properties)); |
522 | } |
523 | - new_swapper = std::make_shared<mc::BufferSwapperMulti>(list, number_of_buffers); |
524 | + new_swapper = std::make_shared<mc::BufferSwapperMulti>(list, synchronous_number_of_buffers); |
525 | } |
526 | else |
527 | { |
528 | - int const async_buffer_count = 3; //async only can accept 3 buffers, so ignore constructor request |
529 | - for(auto i=0; i < async_buffer_count; i++) |
530 | + for(auto i=0u; i < spin_number_of_buffers; i++) |
531 | { |
532 | list.push_back(gr_allocator->alloc_buffer(requested_buffer_properties)); |
533 | } |
534 | - new_swapper = std::make_shared<mc::BufferSwapperSpin>(list, async_buffer_count); |
535 | + new_swapper = std::make_shared<mc::BufferSwapperSpin>(list, spin_number_of_buffers); |
536 | } |
537 | |
538 | actual_buffer_properties = BufferProperties{ |
539 | |
540 | === modified file 'src/server/compositor/switching_bundle.cpp' |
541 | --- src/server/compositor/switching_bundle.cpp 2013-06-15 11:09:16 +0000 |
542 | +++ src/server/compositor/switching_bundle.cpp 2013-06-19 18:36:29 +0000 |
543 | @@ -92,9 +92,9 @@ |
544 | swapper->end_responsibility(list, size); |
545 | |
546 | if (allow_dropping) |
547 | - swapper = swapper_factory->create_swapper_reuse_buffers(list, size, mc::SwapperType::framedropping); |
548 | + swapper = swapper_factory->create_swapper_reuse_buffers(bundle_properties, list, size, mc::SwapperType::framedropping); |
549 | else |
550 | - swapper = swapper_factory->create_swapper_reuse_buffers(list, size, mc::SwapperType::synchronous); |
551 | + swapper = swapper_factory->create_swapper_reuse_buffers(bundle_properties, list, size, mc::SwapperType::synchronous); |
552 | |
553 | cv.notify_all(); |
554 | } |
555 | |
556 | === modified file 'src/server/graphics/android/android_alloc_adaptor.cpp' |
557 | --- src/server/graphics/android/android_alloc_adaptor.cpp 2013-05-22 15:33:21 +0000 |
558 | +++ src/server/graphics/android/android_alloc_adaptor.cpp 2013-06-19 18:36:29 +0000 |
559 | @@ -17,6 +17,7 @@ |
560 | * Kevin DuBois <kevin.dubois@canonical.com> |
561 | */ |
562 | |
563 | +#include "mir/graphics/android/mir_native_buffer.h" |
564 | #include "android_alloc_adaptor.h" |
565 | #include "android_format_conversion-inl.h" |
566 | |
567 | @@ -35,18 +36,13 @@ |
568 | : alloc_device(alloc_dev) |
569 | {} |
570 | |
571 | - void operator()(ANativeWindowBuffer* t) |
572 | + void operator()(mga::MirNativeBuffer* t) |
573 | { |
574 | alloc_device->free(alloc_device.get(), t->handle); |
575 | - delete t; |
576 | } |
577 | private: |
578 | std::shared_ptr<alloc_device_t> const alloc_device; |
579 | }; |
580 | - |
581 | -static void incRef(android_native_base_t*) |
582 | -{ |
583 | -} |
584 | } |
585 | |
586 | mga::AndroidAllocAdaptor::AndroidAllocAdaptor(const std::shared_ptr<struct alloc_device_t>& alloc_device) |
587 | @@ -71,8 +67,11 @@ |
588 | BOOST_THROW_EXCEPTION(std::runtime_error("buffer allocation failed\n")); |
589 | } |
590 | |
591 | - /* pack ANativeWindow buffer for the handle */ |
592 | - auto buffer = new ANativeWindowBuffer; |
593 | + AndroidBufferHandleDeleter del1(alloc_dev); |
594 | + auto tmp = new mga::MirNativeBuffer(del1); |
595 | + mga::MirNativeBufferDeleter del; |
596 | + std::shared_ptr<mga::MirNativeBuffer> buffer(tmp, del); |
597 | + |
598 | buffer->width = width; |
599 | buffer->height = height; |
600 | buffer->stride = stride; |
601 | @@ -80,17 +79,7 @@ |
602 | buffer->format = format; |
603 | buffer->usage = usage_flag; |
604 | |
605 | - /* we don't use these for refcounting buffers. however, drivers still expect to be |
606 | - able to call them */ |
607 | - buffer->common.incRef = &incRef; |
608 | - buffer->common.decRef = &incRef; |
609 | - buffer->common.magic = ANDROID_NATIVE_BUFFER_MAGIC; |
610 | - buffer->common.version = sizeof(ANativeWindowBuffer); |
611 | - |
612 | - AndroidBufferHandleDeleter del(alloc_dev); |
613 | - auto handle = std::shared_ptr<ANativeWindowBuffer>(buffer, del); |
614 | - |
615 | - return handle; |
616 | + return buffer; |
617 | } |
618 | |
619 | int mga::AndroidAllocAdaptor::convert_to_android_usage(BufferUsage usage) |
620 | |
621 | === modified file 'src/server/graphics/gl_renderer.cpp' |
622 | --- src/server/graphics/gl_renderer.cpp 2013-05-21 15:11:41 +0000 |
623 | +++ src/server/graphics/gl_renderer.cpp 2013-06-19 18:36:29 +0000 |
624 | @@ -248,14 +248,6 @@ |
625 | glDisableVertexAttribArray(resources.position_attr_loc); |
626 | } |
627 | |
628 | -void mg::GLRenderer::ensure_no_live_buffers_bound() |
629 | -{ |
630 | - /* before the system can delete buffers that back OES_EGL_image textures, it |
631 | - must make sure that none of these textures are bound in the GLContext*/ |
632 | - static int emptytexture; |
633 | - glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,1,1,0,GL_RGBA,GL_UNSIGNED_BYTE, &emptytexture); |
634 | -} |
635 | - |
636 | void mg::GLRenderer::clear() |
637 | { |
638 | glClear(GL_COLOR_BUFFER_BIT); |
639 | |
640 | === modified file 'src/server/shell/surface.cpp' |
641 | --- src/server/shell/surface.cpp 2013-06-17 19:47:07 +0000 |
642 | +++ src/server/shell/surface.cpp 2013-06-19 18:36:29 +0000 |
643 | @@ -185,6 +185,14 @@ |
644 | } |
645 | } |
646 | |
647 | +void msh::Surface::allow_framedropping(bool allow) |
648 | +{ |
649 | + if (auto const& s = surface.lock()) |
650 | + { |
651 | + s->allow_framedropping(allow); |
652 | + } |
653 | +} |
654 | + |
655 | std::shared_ptr<mc::Buffer> msh::Surface::client_buffer() const |
656 | { |
657 | if (auto const& s = surface.lock()) |
658 | @@ -236,7 +244,7 @@ |
659 | int msh::Surface::configure(MirSurfaceAttrib attrib, int value) |
660 | { |
661 | int result = 0; |
662 | - |
663 | + bool allow_dropping = false; |
664 | /* |
665 | * TODO: In future, query the shell implementation for the subset of |
666 | * attributes/types it implements. |
667 | @@ -255,6 +263,11 @@ |
668 | BOOST_THROW_EXCEPTION(std::logic_error("Invalid surface state.")); |
669 | result = state(); |
670 | break; |
671 | + case mir_surface_attrib_performance_hint: |
672 | + allow_dropping = (value == mir_surface_hint_drop_frames); |
673 | + allow_framedropping(allow_dropping); |
674 | + result = value; |
675 | + break; |
676 | default: |
677 | BOOST_THROW_EXCEPTION(std::logic_error("Invalid surface " |
678 | "attribute.")); |
679 | |
680 | === modified file 'src/server/surfaces/surface.cpp' |
681 | --- src/server/surfaces/surface.cpp 2013-06-13 10:40:42 +0000 |
682 | +++ src/server/surfaces/surface.cpp 2013-06-19 18:36:29 +0000 |
683 | @@ -177,6 +177,11 @@ |
684 | return client_buffer_resource; |
685 | } |
686 | |
687 | +void ms::Surface::allow_framedropping(bool allow) |
688 | +{ |
689 | + buffer_stream->allow_framedropping(allow); |
690 | +} |
691 | + |
692 | void ms::Surface::flag_for_render() |
693 | { |
694 | buffer_is_valid = true; |
695 | |
696 | === modified file 'src/shared/graphics/android/CMakeLists.txt' |
697 | --- src/shared/graphics/android/CMakeLists.txt 2013-03-29 22:30:35 +0000 |
698 | +++ src/shared/graphics/android/CMakeLists.txt 2013-06-19 18:36:29 +0000 |
699 | @@ -2,6 +2,7 @@ |
700 | mirsharedandroid STATIC |
701 | |
702 | mir_native_window.cpp |
703 | + mir_native_buffer.cpp |
704 | syncfence.cpp |
705 | ) |
706 | |
707 | |
708 | === added file 'src/shared/graphics/android/mir_native_buffer.cpp' |
709 | --- src/shared/graphics/android/mir_native_buffer.cpp 1970-01-01 00:00:00 +0000 |
710 | +++ src/shared/graphics/android/mir_native_buffer.cpp 2013-06-19 18:36:29 +0000 |
711 | @@ -0,0 +1,73 @@ |
712 | +/* |
713 | + * Copyright © 2013 Canonical Ltd. |
714 | + * |
715 | + * This program is free software: you can redistribute it and/or modify it |
716 | + * under the terms of the GNU Lesser General Public License version 3, |
717 | + * as published by the Free Software Foundation. |
718 | + * |
719 | + * This program is distributed in the hope that it will be useful, |
720 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
721 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
722 | + * GNU Lesser General Public License for more details. |
723 | + * |
724 | + * You should have received a copy of the GNU Lesser General Public License |
725 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
726 | + * |
727 | + * Authored by: Kevin DuBois <kevin.dubois@canonical.com> |
728 | + */ |
729 | + |
730 | +#include "mir/graphics/android/mir_native_buffer.h" |
731 | + |
732 | +namespace mga=mir::graphics::android; |
733 | + |
734 | +namespace |
735 | +{ |
736 | +static void incref_hook(struct android_native_base_t* base) |
737 | +{ |
738 | + auto buffer = reinterpret_cast<mga::MirNativeBuffer*>(base); |
739 | + buffer->driver_reference(); |
740 | +} |
741 | +static void decref_hook(struct android_native_base_t* base) |
742 | +{ |
743 | + auto buffer = reinterpret_cast<mga::MirNativeBuffer*>(base); |
744 | + buffer->driver_dereference(); |
745 | +} |
746 | +} |
747 | + |
748 | +mga::MirNativeBuffer::MirNativeBuffer(std::function<void(MirNativeBuffer*)> free) |
749 | + : free_fn(free), |
750 | + mir_reference(true), |
751 | + driver_references(0) |
752 | +{ |
753 | + common.incRef = incref_hook; |
754 | + common.decRef = decref_hook; |
755 | +} |
756 | + |
757 | + |
758 | +void mga::MirNativeBuffer::driver_reference() |
759 | +{ |
760 | + driver_references++; |
761 | +} |
762 | + |
763 | +void mga::MirNativeBuffer::driver_dereference() |
764 | +{ |
765 | + driver_references--; |
766 | + if ((!mir_reference) && (driver_references ==0)) |
767 | + { |
768 | + delete this; |
769 | + } |
770 | +} |
771 | + |
772 | +void mga::MirNativeBuffer::mir_dereference() |
773 | +{ |
774 | + mir_reference = false; |
775 | + if ((!mir_reference) && (driver_references ==0)) |
776 | + { |
777 | + delete this; |
778 | + } |
779 | +} |
780 | + |
781 | +mga::MirNativeBuffer::~MirNativeBuffer() |
782 | +{ |
783 | + free_fn(this); |
784 | +} |
785 | |
786 | === modified file 'tests/acceptance-tests/test_server_shutdown.cpp' |
787 | --- tests/acceptance-tests/test_server_shutdown.cpp 2013-06-06 08:36:17 +0000 |
788 | +++ tests/acceptance-tests/test_server_shutdown.cpp 2013-06-19 18:36:29 +0000 |
789 | @@ -51,9 +51,6 @@ |
790 | */ |
791 | std::this_thread::yield(); |
792 | } |
793 | - void ensure_no_live_buffers_bound() |
794 | - { |
795 | - } |
796 | |
797 | void clear() {} |
798 | }; |
799 | |
800 | === modified file 'tests/integration-tests/CMakeLists.txt' |
801 | --- tests/integration-tests/CMakeLists.txt 2013-05-30 03:50:54 +0000 |
802 | +++ tests/integration-tests/CMakeLists.txt 2013-06-19 18:36:29 +0000 |
803 | @@ -7,6 +7,7 @@ |
804 | test_display_info.cpp |
805 | test_display_server_main_loop_events.cpp |
806 | test_surface_first_frame_sync.cpp |
807 | + test_swapinterval.cpp |
808 | ) |
809 | |
810 | add_subdirectory(client/) |
811 | |
812 | === modified file 'tests/integration-tests/test_surface_first_frame_sync.cpp' |
813 | --- tests/integration-tests/test_surface_first_frame_sync.cpp 2013-06-12 10:27:50 +0000 |
814 | +++ tests/integration-tests/test_surface_first_frame_sync.cpp 2013-06-19 18:36:29 +0000 |
815 | @@ -96,8 +96,6 @@ |
816 | while (write(render_operations_fd, "a", 1) != 1) continue; |
817 | } |
818 | |
819 | - void ensure_no_live_buffers_bound() {} |
820 | - |
821 | private: |
822 | int render_operations_fd; |
823 | }; |
824 | |
825 | === added file 'tests/integration-tests/test_swapinterval.cpp' |
826 | --- tests/integration-tests/test_swapinterval.cpp 1970-01-01 00:00:00 +0000 |
827 | +++ tests/integration-tests/test_swapinterval.cpp 2013-06-19 18:36:29 +0000 |
828 | @@ -0,0 +1,226 @@ |
829 | +/* |
830 | + * Copyright © 2013 Canonical Ltd. |
831 | + * |
832 | + * This program is free software: you can redistribute it and/or modify |
833 | + * it under the terms of the GNU General Public License version 3 as |
834 | + * published by the Free Software Foundation. |
835 | + * |
836 | + * This program is distributed in the hope that it will be useful, |
837 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
838 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
839 | + * GNU General Public License for more details. |
840 | + * |
841 | + * You should have received a copy of the GNU General Public License |
842 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
843 | + * |
844 | + * Authored by: Kevin DuBois <kevin.dubois@canonical.com> |
845 | + */ |
846 | + |
847 | +#include "mir/geometry/rectangle.h" |
848 | +#include "mir/graphics/display.h" |
849 | +#include "mir/graphics/display_buffer.h" |
850 | +#include "mir/graphics/renderer.h" |
851 | +#include "mir/graphics/renderable.h" |
852 | +#include "mir/compositor/compositor.h" |
853 | +#include "mir/compositor/compositing_strategy.h" |
854 | +#include "mir/compositor/renderables.h" |
855 | +#include "mir/surfaces/buffer_stream.h" |
856 | +#include "mir/surfaces/buffer_stream_factory.h" |
857 | + |
858 | +#include "mir_test_framework/display_server_test_fixture.h" |
859 | +#include "mir_test_doubles/stub_buffer.h" |
860 | + |
861 | +#include "mir_toolkit/mir_client_library.h" |
862 | + |
863 | +#include <gtest/gtest.h> |
864 | + |
865 | +#include <thread> |
866 | +#include <unistd.h> |
867 | +#include <fcntl.h> |
868 | + |
869 | +namespace geom = mir::geometry; |
870 | +namespace mg = mir::graphics; |
871 | +namespace mc = mir::compositor; |
872 | +namespace mtf = mir_test_framework; |
873 | +namespace ms = mir::surfaces; |
874 | +namespace mtd = mir::test::doubles; |
875 | + |
876 | +namespace |
877 | +{ |
878 | +char const* const mir_test_socket = mtf::test_socket_file().c_str(); |
879 | + |
880 | +class CountingBufferStream : public ms::BufferStream |
881 | +{ |
882 | +public: |
883 | + CountingBufferStream(int render_operations_fd) |
884 | + : render_operations_fd(render_operations_fd) |
885 | + { |
886 | + } |
887 | + |
888 | + std::shared_ptr<mc::Buffer> secure_client_buffer() { return std::make_shared<mtd::StubBuffer>(); } |
889 | + std::shared_ptr<ms::GraphicRegion> lock_back_buffer() { return std::make_shared<mtd::StubBuffer>(); } |
890 | + geom::PixelFormat get_stream_pixel_format() { return geom::PixelFormat::abgr_8888; } |
891 | + geom::Size stream_size() { return geom::Size{}; } |
892 | + void force_requests_to_complete() {} |
893 | + void allow_framedropping(bool) |
894 | + { |
895 | + while (write(render_operations_fd, "a", 1) != 1) continue; |
896 | + } |
897 | + |
898 | +private: |
899 | + int render_operations_fd; |
900 | +}; |
901 | + |
902 | +class StubStreamFactory : public ms::BufferStreamFactory |
903 | +{ |
904 | +public: |
905 | + StubStreamFactory(int render_operations_fd) |
906 | + : render_operations_fd(render_operations_fd) |
907 | + { |
908 | + } |
909 | + |
910 | + std::shared_ptr<ms::BufferStream> create_buffer_stream(mc::BufferProperties const&) |
911 | + { |
912 | + return std::make_shared<CountingBufferStream>(render_operations_fd); |
913 | + } |
914 | +private: |
915 | + int render_operations_fd; |
916 | +}; |
917 | + |
918 | +} |
919 | + |
920 | +using SwapIntervalSignalTest = BespokeDisplayServerTestFixture; |
921 | +TEST_F(SwapIntervalSignalTest, swapinterval_test) |
922 | +{ |
923 | + static std::string const swapinterval_set{"swapinterval_set_952f3f10.tmp"}; |
924 | + static std::string const do_client_finish{"do_client_finish_952f3f10.tmp"}; |
925 | + |
926 | + std::remove(swapinterval_set.c_str()); |
927 | + std::remove(do_client_finish.c_str()); |
928 | + |
929 | + struct ServerConfig : TestingServerConfiguration |
930 | + { |
931 | + ServerConfig() |
932 | + { |
933 | + if (pipe(rendering_ops_pipe) != 0) |
934 | + { |
935 | + BOOST_THROW_EXCEPTION( |
936 | + std::runtime_error("Failed to create pipe")); |
937 | + } |
938 | + |
939 | + if (fcntl(rendering_ops_pipe[0], F_SETFL, O_NONBLOCK) != 0) |
940 | + { |
941 | + BOOST_THROW_EXCEPTION( |
942 | + std::runtime_error("Failed to make the read end of the pipe non-blocking")); |
943 | + } |
944 | + } |
945 | + |
946 | + ~ServerConfig() |
947 | + { |
948 | + if (rendering_ops_pipe[0] >= 0) |
949 | + close(rendering_ops_pipe[0]); |
950 | + if (rendering_ops_pipe[1] >= 0) |
951 | + close(rendering_ops_pipe[1]); |
952 | + } |
953 | + |
954 | + std::shared_ptr<ms::BufferStreamFactory> the_buffer_stream_factory() override |
955 | + { |
956 | + if (!stub_stream_factory) |
957 | + stub_stream_factory = std::make_shared<StubStreamFactory>(rendering_ops_pipe[1]); |
958 | + return stub_stream_factory; |
959 | + } |
960 | + |
961 | + int num_of_swapinterval_commands() |
962 | + { |
963 | + char c; |
964 | + int ops{0}; |
965 | + |
966 | + while (read(rendering_ops_pipe[0], &c, 1) == 1) |
967 | + ops++; |
968 | + |
969 | + return ops; |
970 | + } |
971 | + |
972 | + int rendering_ops_pipe[2]; |
973 | + std::shared_ptr<StubStreamFactory> stub_stream_factory; |
974 | + } server_config; |
975 | + |
976 | + launch_server_process(server_config); |
977 | + |
978 | + struct ClientConfig : TestingClientConfiguration |
979 | + { |
980 | + ClientConfig(std::string const& swapinterval_set, |
981 | + std::string const& do_client_finish) |
982 | + : swapinterval_set{swapinterval_set}, |
983 | + do_client_finish{do_client_finish} |
984 | + { |
985 | + } |
986 | + |
987 | + static void surface_callback(MirSurface*, void*) |
988 | + { |
989 | + } |
990 | + |
991 | + void exec() |
992 | + { |
993 | + MirSurfaceParameters request_params = |
994 | + { |
995 | + __PRETTY_FUNCTION__, |
996 | + 640, 480, |
997 | + mir_pixel_format_abgr_8888, |
998 | + mir_buffer_usage_hardware |
999 | + }; |
1000 | + |
1001 | + MirConnection* connection = mir_connect_sync(mir_test_socket, "testapp"); |
1002 | + MirSurface* surface = mir_connection_create_surface_sync(connection, &request_params); |
1003 | + |
1004 | + //1 is the default swapinterval |
1005 | + EXPECT_EQ(1, mir_surface_get_swapinterval(surface)); |
1006 | + |
1007 | + mir_wait_for(mir_surface_set_swapinterval(surface, 0)); |
1008 | + EXPECT_EQ(0, mir_surface_get_swapinterval(surface)); |
1009 | + |
1010 | + mir_wait_for(mir_surface_set_swapinterval(surface, 1)); |
1011 | + EXPECT_EQ(1, mir_surface_get_swapinterval(surface)); |
1012 | + |
1013 | + //swapinterval 2 not supported |
1014 | + EXPECT_EQ(NULL, mir_surface_set_swapinterval(surface, 2)); |
1015 | + EXPECT_EQ(1, mir_surface_get_swapinterval(surface)); |
1016 | + |
1017 | + set_flag(swapinterval_set); |
1018 | + wait_for(do_client_finish); |
1019 | + |
1020 | + mir_surface_release_sync(surface); |
1021 | + mir_connection_release(connection); |
1022 | + } |
1023 | + |
1024 | + /* TODO: Extract this flag mechanism and make it reusable */ |
1025 | + void set_flag(std::string const& flag_file) |
1026 | + { |
1027 | + close(open(flag_file.c_str(), O_CREAT, S_IWUSR | S_IRUSR)); |
1028 | + } |
1029 | + |
1030 | + void wait_for(std::string const& flag_file) |
1031 | + { |
1032 | + int fd = -1; |
1033 | + while ((fd = open(flag_file.c_str(), O_RDONLY, S_IWUSR | S_IRUSR)) == -1) |
1034 | + { |
1035 | + std::this_thread::sleep_for(std::chrono::milliseconds(1)); |
1036 | + } |
1037 | + close(fd); |
1038 | + } |
1039 | + |
1040 | + std::string const swapinterval_set; |
1041 | + std::string const do_client_finish; |
1042 | + } client_config{swapinterval_set, do_client_finish}; |
1043 | + |
1044 | + launch_client_process(client_config); |
1045 | + |
1046 | + run_in_test_process([&] |
1047 | + { |
1048 | + client_config.wait_for(swapinterval_set); |
1049 | + |
1050 | + EXPECT_EQ(2, server_config.num_of_swapinterval_commands()); |
1051 | + |
1052 | + client_config.set_flag(do_client_finish); |
1053 | + }); |
1054 | +} |
1055 | |
1056 | === modified file 'tests/mir_test_framework/testing_server_options.cpp' |
1057 | --- tests/mir_test_framework/testing_server_options.cpp 2013-06-12 10:27:50 +0000 |
1058 | +++ tests/mir_test_framework/testing_server_options.cpp 2013-06-19 18:36:29 +0000 |
1059 | @@ -141,10 +141,6 @@ |
1060 | r.graphic_region(); |
1061 | } |
1062 | |
1063 | - void ensure_no_live_buffers_bound() |
1064 | - { |
1065 | - } |
1066 | - |
1067 | void clear() {} |
1068 | }; |
1069 | |
1070 | |
1071 | === modified file 'tests/unit-tests/client/android/test_client_android_buffer.cpp' |
1072 | --- tests/unit-tests/client/android/test_client_android_buffer.cpp 2013-06-12 09:36:20 +0000 |
1073 | +++ tests/unit-tests/client/android/test_client_android_buffer.cpp 2013-06-19 18:36:29 +0000 |
1074 | @@ -335,6 +335,6 @@ |
1075 | ASSERT_NE(nullptr, native_handle->common.incRef); |
1076 | ASSERT_NE(nullptr, native_handle->common.decRef); |
1077 | |
1078 | - native_handle->common.incRef(NULL); |
1079 | - native_handle->common.decRef(NULL); |
1080 | + native_handle->common.incRef(&native_handle->common); |
1081 | + native_handle->common.decRef(&native_handle->common); |
1082 | } |
1083 | |
1084 | === modified file 'tests/unit-tests/compositor/test_buffer_stream.cpp' |
1085 | --- tests/unit-tests/compositor/test_buffer_stream.cpp 2013-06-17 15:55:04 +0000 |
1086 | +++ tests/unit-tests/compositor/test_buffer_stream.cpp 2013-06-19 18:36:29 +0000 |
1087 | @@ -122,3 +122,12 @@ |
1088 | |
1089 | buffer_stream.secure_client_buffer(); |
1090 | } |
1091 | + |
1092 | +TEST_F(BufferStreamTest, allow_framedropping_command) |
1093 | +{ |
1094 | + EXPECT_CALL(*mock_bundle, allow_framedropping(true)) |
1095 | + .Times(1); |
1096 | + |
1097 | + mc::BufferStreamSurfaces buffer_stream(mock_bundle); |
1098 | + buffer_stream.allow_framedropping(true); |
1099 | +} |
1100 | |
1101 | === modified file 'tests/unit-tests/compositor/test_rendering_operator.cpp' |
1102 | --- tests/unit-tests/compositor/test_rendering_operator.cpp 2013-05-22 09:56:40 +0000 |
1103 | +++ tests/unit-tests/compositor/test_rendering_operator.cpp 2013-06-19 18:36:29 +0000 |
1104 | @@ -45,9 +45,6 @@ |
1105 | |
1106 | void clear() {} |
1107 | |
1108 | - void ensure_no_live_buffers_bound() |
1109 | - { |
1110 | - } |
1111 | void render(std::function<void(std::shared_ptr<void> const&)> save_resource, mg::Renderable&) |
1112 | { |
1113 | std::shared_ptr<void> tmp; |
1114 | @@ -81,7 +78,6 @@ |
1115 | { |
1116 | public: |
1117 | MOCK_METHOD2(render, void(std::function<void(std::shared_ptr<void> const&)>, mg::Renderable&)); |
1118 | - MOCK_METHOD0(ensure_no_live_buffers_bound, void()); |
1119 | MOCK_METHOD0(clear, void ()); |
1120 | |
1121 | ~MockRenderer() noexcept {} |
1122 | @@ -122,11 +118,3 @@ |
1123 | EXPECT_EQ(use_count_before1, stub_renderer.resource1.use_count()); |
1124 | EXPECT_EQ(use_count_before2, stub_renderer.resource2.use_count()); |
1125 | } |
1126 | - |
1127 | -TEST(RenderingOperator, render_operator_ensures_no_live_texture_bound) |
1128 | -{ |
1129 | - MockRenderer mock_renderer; |
1130 | - EXPECT_CALL(mock_renderer, ensure_no_live_buffers_bound()) |
1131 | - .Times(1); |
1132 | - mc::RenderingOperator rendering_operator(mock_renderer, [](std::shared_ptr<void> const&) {}); |
1133 | -} |
1134 | |
1135 | === modified file 'tests/unit-tests/compositor/test_swapper_factory.cpp' |
1136 | --- tests/unit-tests/compositor/test_swapper_factory.cpp 2013-06-11 19:55:10 +0000 |
1137 | +++ tests/unit-tests/compositor/test_swapper_factory.cpp 2013-06-19 18:36:29 +0000 |
1138 | @@ -147,6 +147,7 @@ |
1139 | { |
1140 | using namespace testing; |
1141 | |
1142 | + mc::BufferProperties properties; |
1143 | std::vector<std::shared_ptr<mc::Buffer>> list {}; |
1144 | size_t size = 3; |
1145 | |
1146 | @@ -154,19 +155,66 @@ |
1147 | .Times(0); |
1148 | |
1149 | mc::SwapperFactory strategy(mock_buffer_allocator); |
1150 | - auto swapper = strategy.create_swapper_reuse_buffers(list, size, mc::SwapperType::framedropping); |
1151 | + auto swapper = strategy.create_swapper_reuse_buffers(properties, list, size, mc::SwapperType::framedropping); |
1152 | } |
1153 | |
1154 | TEST_F(SwapperFactoryTest, create_sync_reuse) |
1155 | { |
1156 | using namespace testing; |
1157 | |
1158 | + mc::BufferProperties properties; |
1159 | std::vector<std::shared_ptr<mc::Buffer>> list; |
1160 | size_t size = 3; |
1161 | |
1162 | EXPECT_CALL(*mock_buffer_allocator, alloc_buffer(properties)) |
1163 | .Times(0); |
1164 | |
1165 | + mc::SwapperFactory strategy(mock_buffer_allocator, 3); |
1166 | + auto swapper = strategy.create_swapper_reuse_buffers(properties, list, size, mc::SwapperType::synchronous); |
1167 | +} |
1168 | + |
1169 | +TEST_F(SwapperFactoryTest, reuse_drop_unneeded_buffer) |
1170 | +{ |
1171 | + using namespace testing; |
1172 | + |
1173 | + mc::SwapperFactory strategy(mock_buffer_allocator, 2); |
1174 | + |
1175 | + auto buffer = std::make_shared<mtd::StubBuffer>(); |
1176 | + { |
1177 | + size_t size = 3; |
1178 | + std::vector<std::shared_ptr<mc::Buffer>> list{buffer}; |
1179 | + |
1180 | + auto swapper = strategy.create_swapper_reuse_buffers( |
1181 | + properties, list, size, mc::SwapperType::synchronous); |
1182 | + } |
1183 | + EXPECT_EQ(1, buffer.use_count()); |
1184 | +} |
1185 | + |
1186 | +TEST_F(SwapperFactoryTest, reuse_drop_unneeded_buffer_error) |
1187 | +{ |
1188 | + using namespace testing; |
1189 | + |
1190 | + mc::SwapperFactory strategy(mock_buffer_allocator, 2); |
1191 | + |
1192 | + size_t size = 3; |
1193 | + std::vector<std::shared_ptr<mc::Buffer>> list{}; |
1194 | + |
1195 | + EXPECT_THROW({ |
1196 | + strategy.create_swapper_reuse_buffers( |
1197 | + properties, list, size, mc::SwapperType::synchronous); |
1198 | + }, std::logic_error); |
1199 | +} |
1200 | + |
1201 | +TEST_F(SwapperFactoryTest, reuse_alloc_additional_buffer_for_framedropping) |
1202 | +{ |
1203 | + using namespace testing; |
1204 | + |
1205 | + EXPECT_CALL(*mock_buffer_allocator, alloc_buffer(_)) |
1206 | + .Times(1); |
1207 | mc::SwapperFactory strategy(mock_buffer_allocator); |
1208 | - auto swapper = strategy.create_swapper_reuse_buffers(list, size, mc::SwapperType::synchronous); |
1209 | + |
1210 | + size_t size = 2; |
1211 | + std::vector<std::shared_ptr<mc::Buffer>> list{}; |
1212 | + auto swapper = strategy.create_swapper_reuse_buffers( |
1213 | + properties, list, size, mc::SwapperType::framedropping); |
1214 | } |
1215 | |
1216 | === modified file 'tests/unit-tests/compositor/test_switching_bundle.cpp' |
1217 | --- tests/unit-tests/compositor/test_switching_bundle.cpp 2013-06-13 08:59:25 +0000 |
1218 | +++ tests/unit-tests/compositor/test_switching_bundle.cpp 2013-06-19 18:36:29 +0000 |
1219 | @@ -90,7 +90,7 @@ |
1220 | .WillOnce(Return(stub_buffer)); |
1221 | EXPECT_CALL(*mock_secondary_swapper, client_release(stub_buffer)) |
1222 | .Times(1); |
1223 | - EXPECT_CALL(*mock_swapper_factory, create_swapper_reuse_buffers(_,_,_)) |
1224 | + EXPECT_CALL(*mock_swapper_factory, create_swapper_reuse_buffers(_,_,_,_)) |
1225 | .Times(1) |
1226 | .WillOnce(Return(mock_secondary_swapper)); |
1227 | |
1228 | @@ -126,7 +126,7 @@ |
1229 | .WillOnce(Return(stub_buffer)); |
1230 | EXPECT_CALL(*mock_secondary_swapper, compositor_release(stub_buffer)) |
1231 | .Times(1); |
1232 | - EXPECT_CALL(*mock_swapper_factory, create_swapper_reuse_buffers(_,_,_)) |
1233 | + EXPECT_CALL(*mock_swapper_factory, create_swapper_reuse_buffers(_,_,_,_)) |
1234 | .Times(1) |
1235 | .WillOnce(Return(mock_secondary_swapper)); |
1236 | |
1237 | @@ -147,7 +147,7 @@ |
1238 | .Times(1); |
1239 | EXPECT_CALL(*mock_default_swapper, end_responsibility(_,_)) |
1240 | .Times(1); |
1241 | - EXPECT_CALL(*mock_swapper_factory, create_swapper_reuse_buffers(_,_,mc::SwapperType::framedropping)) |
1242 | + EXPECT_CALL(*mock_swapper_factory, create_swapper_reuse_buffers(_,_,_,mc::SwapperType::framedropping)) |
1243 | .Times(1) |
1244 | .WillOnce(Return(mock_secondary_swapper)); |
1245 | |
1246 | |
1247 | === modified file 'tests/unit-tests/graphics/android/CMakeLists.txt' |
1248 | --- tests/unit-tests/graphics/android/CMakeLists.txt 2013-05-21 20:58:15 +0000 |
1249 | +++ tests/unit-tests/graphics/android/CMakeLists.txt 2013-06-19 18:36:29 +0000 |
1250 | @@ -22,6 +22,7 @@ |
1251 | ${CMAKE_CURRENT_SOURCE_DIR}/test_pixel_format.cpp |
1252 | ${CMAKE_CURRENT_SOURCE_DIR}/test_android_platform.cpp |
1253 | ${CMAKE_CURRENT_SOURCE_DIR}/test_interpreter_buffer_cache.cpp |
1254 | + ${CMAKE_CURRENT_SOURCE_DIR}/test_external_refcount.cpp |
1255 | ) |
1256 | |
1257 | set(UNIT_TEST_SOURCES ${UNIT_TEST_SOURCES} PARENT_SCOPE) |
1258 | |
1259 | === modified file 'tests/unit-tests/graphics/android/test_android_alloc_adaptor.cpp' |
1260 | --- tests/unit-tests/graphics/android/test_android_alloc_adaptor.cpp 2013-05-21 21:43:25 +0000 |
1261 | +++ tests/unit-tests/graphics/android/test_android_alloc_adaptor.cpp 2013-06-19 18:36:29 +0000 |
1262 | @@ -217,20 +217,13 @@ |
1263 | EXPECT_EQ(fb_usage_flags, handle->usage); |
1264 | } |
1265 | |
1266 | -TEST_F(AdaptorICSTest, handle_has_reffable_incref) |
1267 | +TEST_F(AdaptorICSTest, handle_has_strong_reference_for_c_drivers) |
1268 | { |
1269 | - struct android_native_base_t *native_base = nullptr; |
1270 | auto handle = alloc_adaptor->alloc_buffer(size, pf, usage); |
1271 | ASSERT_NE(nullptr, handle->common.incRef); |
1272 | - handle->common.incRef(native_base); |
1273 | -} |
1274 | - |
1275 | -TEST_F(AdaptorICSTest, handle_has_reffable_decref) |
1276 | -{ |
1277 | - struct android_native_base_t *native_base = nullptr; |
1278 | - auto handle = alloc_adaptor->alloc_buffer(size, pf, usage); |
1279 | ASSERT_NE(nullptr, handle->common.decRef); |
1280 | - handle->common.decRef(native_base); |
1281 | + handle->common.incRef(&handle->common); |
1282 | + handle->common.decRef(&handle->common); |
1283 | } |
1284 | |
1285 | TEST_F(AdaptorICSTest, handle_has_right_magic) |
1286 | |
1287 | === added file 'tests/unit-tests/graphics/android/test_external_refcount.cpp' |
1288 | --- tests/unit-tests/graphics/android/test_external_refcount.cpp 1970-01-01 00:00:00 +0000 |
1289 | +++ tests/unit-tests/graphics/android/test_external_refcount.cpp 2013-06-19 18:36:29 +0000 |
1290 | @@ -0,0 +1,70 @@ |
1291 | +/* |
1292 | + * Copyright © 2013 Canonical Ltd. |
1293 | + * |
1294 | + * This program is free software: you can redistribute it and/or modify |
1295 | + * it under the terms of the GNU General Public License version 3 as |
1296 | + * published by the Free Software Foundation. |
1297 | + * |
1298 | + * This program is distributed in the hope that it will be useful, |
1299 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1300 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1301 | + * GNU General Public License for more details. |
1302 | + * |
1303 | + * You should have received a copy of the GNU General Public License |
1304 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1305 | + * |
1306 | + * Authored by: Kevin DuBois <kevin.dubois@canonical.com> |
1307 | + */ |
1308 | + |
1309 | +#include "mir/graphics/android/mir_native_buffer.h" |
1310 | +#include <memory> |
1311 | +#include <gtest/gtest.h> |
1312 | + |
1313 | +namespace mga=mir::graphics::android; |
1314 | + |
1315 | +TEST(AndroidRefcount, driver_hooks) |
1316 | +{ |
1317 | + int call_count = 0; |
1318 | + mga::MirNativeBuffer* driver_reference = nullptr; |
1319 | + { |
1320 | + auto tmp = new mga::MirNativeBuffer( |
1321 | + [&](mga::MirNativeBuffer*) |
1322 | + { |
1323 | + call_count++; |
1324 | + }); |
1325 | + mga::MirNativeBufferDeleter del; |
1326 | + std::shared_ptr<mga::MirNativeBuffer> buffer(tmp, del); |
1327 | + driver_reference = buffer.get(); |
1328 | + driver_reference->common.incRef(&driver_reference->common); |
1329 | + //Mir loses its reference |
1330 | + } |
1331 | + |
1332 | + EXPECT_EQ(0, call_count); |
1333 | + driver_reference->common.decRef(&driver_reference->common); |
1334 | + EXPECT_EQ(1, call_count); |
1335 | +} |
1336 | + |
1337 | +TEST(AndroidRefcount, driver_hooks_mir_ref) |
1338 | +{ |
1339 | + int call_count = 0; |
1340 | + { |
1341 | + std::shared_ptr<mga::MirNativeBuffer> mir_reference; |
1342 | + mga::MirNativeBuffer* driver_reference = nullptr; |
1343 | + { |
1344 | + auto tmp = new mga::MirNativeBuffer( |
1345 | + [&](mga::MirNativeBuffer*) |
1346 | + { |
1347 | + call_count++; |
1348 | + }); |
1349 | + mga::MirNativeBufferDeleter del; |
1350 | + mir_reference = std::shared_ptr<mga::MirNativeBuffer>(tmp, del); |
1351 | + driver_reference = mir_reference.get(); |
1352 | + driver_reference->common.incRef(&driver_reference->common); |
1353 | + } |
1354 | + |
1355 | + //driver loses its reference |
1356 | + driver_reference->common.decRef(&driver_reference->common); |
1357 | + EXPECT_EQ(0, call_count); |
1358 | + } |
1359 | + EXPECT_EQ(1, call_count); |
1360 | +} |
1361 | |
1362 | === modified file 'tests/unit-tests/graphics/test_gl_renderer.cpp' |
1363 | --- tests/unit-tests/graphics/test_gl_renderer.cpp 2013-06-12 15:36:31 +0000 |
1364 | +++ tests/unit-tests/graphics/test_gl_renderer.cpp 2013-06-19 18:36:29 +0000 |
1365 | @@ -349,13 +349,3 @@ |
1366 | auto result = std::find(saved_resources.begin(), saved_resources.end(), gr_ptr); |
1367 | EXPECT_NE(saved_resources.end(), result); |
1368 | } |
1369 | - |
1370 | -TEST_F(GLRenderer, TestRenderEnsureNoBind) |
1371 | -{ |
1372 | - using namespace std::placeholders; |
1373 | - |
1374 | - mtd::MockRenderable rd; |
1375 | - EXPECT_CALL(mock_gl, glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,1,1,0,GL_RGBA,GL_UNSIGNED_BYTE,_)); |
1376 | - |
1377 | - renderer->ensure_no_live_buffers_bound(); |
1378 | -} |
1379 | |
1380 | === modified file 'tests/unit-tests/surfaces/test_surface.cpp' |
1381 | --- tests/unit-tests/surfaces/test_surface.cpp 2013-06-13 10:40:42 +0000 |
1382 | +++ tests/unit-tests/surfaces/test_surface.cpp 2013-06-19 18:36:29 +0000 |
1383 | @@ -420,6 +420,18 @@ |
1384 | surf.force_requests_to_complete(); |
1385 | } |
1386 | |
1387 | +TEST_F(SurfaceCreation, test_surface_allow_framedropping) |
1388 | +{ |
1389 | + using namespace testing; |
1390 | + |
1391 | + EXPECT_CALL(*mock_buffer_stream, allow_framedropping(true)) |
1392 | + .Times(1); |
1393 | + |
1394 | + ms::Surface surf{surface_name, geom::Point(), mock_buffer_stream, |
1395 | + std::shared_ptr<mi::InputChannel>(), mock_change_cb}; |
1396 | + surf.allow_framedropping(true); |
1397 | +} |
1398 | + |
1399 | TEST_F(SurfaceCreation, input_fds) |
1400 | { |
1401 | using namespace testing; |
FAILED: Continuous integration, rev:758 jenkins. qa.ubuntu. com/job/ mir-ci/ 751/ jenkins. qa.ubuntu. com/job/ mir-android- raring- i386-build/ 937/console jenkins. qa.ubuntu. com/job/ mir-clang- raring- amd64-build/ 819/console jenkins. qa.ubuntu. com/job/ mir-raring- amd64-ci/ 236/console jenkins. qa.ubuntu. com/job/ mir-vm- ci-build/ ./distribution= quantal, flavor= amd64/435
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins: 8080/job/ mir-ci/ 751/rebuild
http://