Mir

Merge lp:~kdub/mir/interval0-signal into lp:~mir-team/mir/trunk

Proposed by Kevin DuBois
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
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/integration-tests/test_swapinterval.cpp tests from the client's request until the point that the request hits the compositor systems at mc::BufferStream

still in pre-review, dependent on anativewindow-external-refcount

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

Preview Diff

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

Subscribers

People subscribed via source and target branches