Mir

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

Proposed by Kevin DuBois
Status: Merged
Approved by: Daniel van Vugt
Approved revision: no longer in the source branch.
Merged at revision: 780
Proposed branch: lp:~kdub/mir/interval0-signal
Merge into: lp:~mir-team/mir/trunk
Prerequisite: lp:~kdub/mir/anativewindow-external-refcount
Diff against target: 786 lines (+418/-23)
24 files modified
include/client/mir_toolkit/mir_client_library.h (+21/-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/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_toolkit/common.h (+1/-1)
include/test/mir_test_doubles/mock_buffer_stream.h (+2/-0)
include/test/mir_test_doubles/mock_swapper_factory.h (+2/-2)
include/test/mir_test_doubles/stub_buffer_stream.h (+4/-0)
src/client/mir_client_library.cpp (+12/-0)
src/client/mir_surface.cpp (+2/-0)
src/server/compositor/buffer_stream_surfaces.cpp (+4/-0)
src/server/compositor/swapper_factory.cpp (+36/-9)
src/server/compositor/switching_bundle.cpp (+2/-2)
src/server/shell/surface.cpp (+14/-1)
src/server/surfaces/surface.cpp (+5/-0)
tests/integration-tests/CMakeLists.txt (+1/-0)
tests/integration-tests/test_swapinterval.cpp (+226/-0)
tests/unit-tests/compositor/test_buffer_stream.cpp (+9/-0)
tests/unit-tests/compositor/test_swapper_factory.cpp (+50/-2)
tests/unit-tests/compositor/test_switching_bundle.cpp (+3/-3)
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
Daniel van Vugt Approve
Alexandros Frantzis (community) Approve
Review via email: mp+170423@code.launchpad.net

This proposal supersedes a proposal from 2013-06-17.

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 : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:759
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~kdub/mir/interval0-signal/+merge/170423/+edit-commit-message

http://jenkins.qa.ubuntu.com/job/mir-ci/771/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-android-saucy-i386-build/969
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-clang-saucy-amd64-build/851
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-saucy-amd64-ci/9
        deb: http://jenkins.qa.ubuntu.com/job/mir-saucy-amd64-ci/9/artifact/work/output/*zip*/output.zip

Click here to trigger a rebuild:
http://s-jenkins:8080/job/mir-ci/771/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

1. Swap interval >1 is valid, but not usually useful. I wonder if there's any value in generalizing so interval>1 is supported...?

2. Documentation on the limitations of swap interval ([0,1]) is missing from the comment for mir_surface_set_swapinterval.

3. Consistency:
132 +typedef enum MirSurfacePerformanceHint
133 +{
134 + mir_surface_hint_synchronous,
135 + mir_surface_hint_drop_frames,
136 + mir_surface_hint_arraysize_
137 +} MirSurfacePerformanceHint;
"MirSurfacePerformanceHint" != "mir_surface_hint". I suggest removing the word "Performance". Also from:
124 + mir_surface_attrib_performance_hint,
Although "hint" is a bit vague. Why not make the attribute named "swap_interval" or similar? Then you don't need MirSurfacePerformanceHint at all because it's just an int.

4. Lack of indentation under "196 + switch (interval)" is a style I haven't seen in Mir before. Is it within policy? Do we care?

5. I tried adding mir_surface_set_swapinterval(surface, 0) to demo_client_unaccelerated and didn't expect what I saw:
I see the swap happening *much* less often with 0 than 1. However adding a frame rate counter in the client shows it's higher for the client, as it should be. I suspect we have a buffer scheduling problem that makes interval=0 look much slower than it should. But it might just be the natural randomness of frame dropping making longer periods of green/blue appear in demo_client_unaccelerated. I will have to modify/create a software client (to actually animate something) to investigate further if this is a real issue. And even if there is an issue with it I'm not even sure this branch is to blame...

So really just #2-#4 need attention right now.

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

> 4. Lack of indentation under "196 + switch (interval)" is a style I haven't seen in Mir before.
> Is it within policy? Do we care?

I see more indentation that we normally use, not a lack of it :)

274 + void mc::SwapperFactory::change_swapper_size(
297 + create_swapper_reuse_buffers(
298 - std::vector<std::shared_ptr<Buffer>>& list, size_t buffer_num, SwapperType type) const
299 + BufferProperties const& buffer_properties, std::vector<std::shared_ptr<Buffer>>& list

It feels strange that we remove/add buffers to the vector that is handed to us (although it has no ill effect, since the caller doesn't care about the buffers). I think it would be cleaner to create and manipulate a new vector internally (and make the create_swapper_reuse_buffers() parameter const).

289 + } else

else should be on separate line

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

@Daniel
#1, we don't have a driving use case for >1 swapinterval at the moment, plus it would take some changes to the swappers, so we can put it on the wishlist.
#2 hopefully better documentation added
#3 good idea, code is cleaner with this
#4 just bad indentation, was eliminated with #3
#5 i think this is just the unaccelerated client picking blue or green frames multiple times in a row. If you call this function with an eglapp.c based gl client, you'll see higher than vsync framerates reported.

@Alexandros
I agree, have to come up with a solution to allocate a buffer when going from 2->3 buffers, and preserve the buffer for any future 3->2 transitions. The android drivers didn't like switching buffers of the same size/format/usage out from under them.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Thanks Kevin. I can see the requested changes made but have not re-reviewed yet.

review: Abstain
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

A lot has landed today. So now we have:

Text conflict in src/server/shell/surface.cpp
Text conflict in tests/unit-tests/surfaces/test_surface.cpp
2 conflicts encountered.

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

1. Conflicts:
Text conflict in src/server/shell/surface.cpp
Text conflict in tests/unit-tests/surfaces/test_surface.cpp

2. Please resolve this inconsistency: "swapinterval" and "swap_interval".

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

Looks good.

review: Approve
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)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

OK, I have no more complaints. But I'm not going to redo all the testing I've already done on earlier revisions.

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'include/client/mir_toolkit/mir_client_library.h'
--- include/client/mir_toolkit/mir_client_library.h 2013-06-20 09:43:30 +0000
+++ include/client/mir_toolkit/mir_client_library.h 2013-06-25 19:32:30 +0000
@@ -293,6 +293,27 @@
293 */293 */
294MirSurfaceState mir_surface_get_state(MirSurface *surface);294MirSurfaceState mir_surface_get_state(MirSurface *surface);
295295
296/**
297 * Set the swapinterval for mir_surface_swap_buffers. EGL users should use
298 * eglSwapInterval directly.
299 * At the time being, only swapinterval of 0 or 1 is supported.
300 * \param [in] surface The surface to operate on
301 * \param [in] interval The number of vblank signals that
302 * mir_surface_swap_buffers will wait for
303 * \return A wait handle that can be passed to mir_wait_for,
304 * or NULL if the interval could not be supported
305 */
306MirWaitHandle* mir_surface_set_swapinterval(MirSurface* surface, int interval);
307
308/**
309 * Query the swapinterval that the surface is operating with.
310 * The default interval is 1.
311 * \param [in] surface The surface to operate on
312 * \return The swapinterval value that the client is operating with.
313 * Returns -1 if surface is invalid.
314 */
315int mir_surface_get_swapinterval(MirSurface* surface);
316
296#ifdef __cplusplus317#ifdef __cplusplus
297}318}
298/**@}*/319/**@}*/
299320
=== modified file 'include/server/mir/compositor/buffer_allocation_strategy.h'
--- include/server/mir/compositor/buffer_allocation_strategy.h 2013-06-17 10:26:18 +0000
+++ include/server/mir/compositor/buffer_allocation_strategy.h 2013-06-25 19:32:30 +0000
@@ -45,7 +45,7 @@
45class BufferAllocationStrategy45class BufferAllocationStrategy
46{46{
47public:47public:
48 virtual std::shared_ptr<BufferSwapper> create_swapper_reuse_buffers(48 virtual std::shared_ptr<BufferSwapper> create_swapper_reuse_buffers(BufferProperties const&,
49 std::vector<std::shared_ptr<Buffer>>&, size_t, SwapperType) const = 0;49 std::vector<std::shared_ptr<Buffer>>&, size_t, SwapperType) const = 0;
50 virtual std::shared_ptr<BufferSwapper> create_swapper_new_buffers(50 virtual std::shared_ptr<BufferSwapper> create_swapper_new_buffers(
51 BufferProperties& actual_properties, BufferProperties const& requested_properties, SwapperType) const = 0;51 BufferProperties& actual_properties, BufferProperties const& requested_properties, SwapperType) const = 0;
5252
=== modified file 'include/server/mir/compositor/buffer_stream_surfaces.h'
--- include/server/mir/compositor/buffer_stream_surfaces.h 2013-06-20 09:39:10 +0000
+++ include/server/mir/compositor/buffer_stream_surfaces.h 2013-06-25 19:32:30 +0000
@@ -46,6 +46,7 @@
4646
47 geometry::PixelFormat get_stream_pixel_format();47 geometry::PixelFormat get_stream_pixel_format();
48 geometry::Size stream_size();48 geometry::Size stream_size();
49 void allow_framedropping(bool);
49 void force_requests_to_complete();50 void force_requests_to_complete();
5051
51protected:52protected:
5253
=== modified file 'include/server/mir/compositor/swapper_factory.h'
--- include/server/mir/compositor/swapper_factory.h 2013-06-11 15:05:27 +0000
+++ include/server/mir/compositor/swapper_factory.h 2013-06-25 19:32:30 +0000
@@ -38,14 +38,18 @@
38 std::shared_ptr<GraphicBufferAllocator> const& gr_alloc,38 std::shared_ptr<GraphicBufferAllocator> const& gr_alloc,
39 int number_of_buffers);39 int number_of_buffers);
4040
41 std::shared_ptr<BufferSwapper> create_swapper_reuse_buffers(41 std::shared_ptr<BufferSwapper> create_swapper_reuse_buffers(BufferProperties const&,
42 std::vector<std::shared_ptr<Buffer>>&, size_t, SwapperType) const;42 std::vector<std::shared_ptr<Buffer>>&, size_t, SwapperType) const;
43 std::shared_ptr<BufferSwapper> create_swapper_new_buffers(43 std::shared_ptr<BufferSwapper> create_swapper_new_buffers(
44 BufferProperties& actual_properties, BufferProperties const& requested_properties, SwapperType) const;44 BufferProperties& actual_properties, BufferProperties const& requested_properties, SwapperType) const;
4545
46private:46private:
47 void change_swapper_size(
48 std::vector<std::shared_ptr<Buffer>>&, size_t const, size_t, BufferProperties const&) const;
49
47 std::shared_ptr<GraphicBufferAllocator> const gr_allocator;50 std::shared_ptr<GraphicBufferAllocator> const gr_allocator;
48 int const number_of_buffers;51 unsigned int const synchronous_number_of_buffers;
52 unsigned int const spin_number_of_buffers;
49};53};
50}54}
51}55}
5256
=== modified file 'include/server/mir/shell/surface.h'
--- include/server/mir/shell/surface.h 2013-06-25 05:42:49 +0000
+++ include/server/mir/shell/surface.h 2013-06-25 19:32:30 +0000
@@ -87,6 +87,7 @@
8787
88 virtual void take_input_focus(std::shared_ptr<InputTargeter> const& targeter);88 virtual void take_input_focus(std::shared_ptr<InputTargeter> const& targeter);
8989
90 virtual void allow_framedropping(bool);
90private:91private:
91 bool set_type(MirSurfaceType t); // Use configure() to make public changes92 bool set_type(MirSurfaceType t); // Use configure() to make public changes
92 bool set_state(MirSurfaceState s);93 bool set_state(MirSurfaceState s);
9394
=== modified file 'include/server/mir/surfaces/buffer_stream.h'
--- include/server/mir/surfaces/buffer_stream.h 2013-06-20 09:39:10 +0000
+++ include/server/mir/surfaces/buffer_stream.h 2013-06-25 19:32:30 +0000
@@ -45,6 +45,7 @@
45 virtual std::shared_ptr<compositor::Buffer> lock_back_buffer() = 0;45 virtual std::shared_ptr<compositor::Buffer> lock_back_buffer() = 0;
46 virtual geometry::PixelFormat get_stream_pixel_format() = 0;46 virtual geometry::PixelFormat get_stream_pixel_format() = 0;
47 virtual geometry::Size stream_size() = 0;47 virtual geometry::Size stream_size() = 0;
48 virtual void allow_framedropping(bool) = 0;
48 virtual void force_requests_to_complete() = 0;49 virtual void force_requests_to_complete() = 0;
49};50};
5051
5152
=== modified file 'include/server/mir/surfaces/surface.h'
--- include/server/mir/surfaces/surface.h 2013-06-25 05:42:49 +0000
+++ include/server/mir/surfaces/surface.h 2013-06-25 19:32:30 +0000
@@ -81,6 +81,8 @@
81 bool supports_input() const;81 bool supports_input() const;
82 int client_input_fd() const;82 int client_input_fd() const;
83 int server_input_fd() const;83 int server_input_fd() const;
84
85 void allow_framedropping(bool);
84private:86private:
85 std::string surface_name;87 std::string surface_name;
86 geometry::Point top_left_point;88 geometry::Point top_left_point;
8789
=== modified file 'include/shared/mir_toolkit/common.h'
--- include/shared/mir_toolkit/common.h 2013-05-03 22:53:42 +0000
+++ include/shared/mir_toolkit/common.h 2013-06-25 19:32:30 +0000
@@ -35,6 +35,7 @@
35{35{
36 mir_surface_attrib_type,36 mir_surface_attrib_type,
37 mir_surface_attrib_state,37 mir_surface_attrib_state,
38 mir_surface_attrib_swapinterval,
38 mir_surface_attrib_arraysize_39 mir_surface_attrib_arraysize_
39} MirSurfaceAttrib;40} MirSurfaceAttrib;
4041
@@ -62,7 +63,6 @@
62 mir_surface_state_fullscreen,63 mir_surface_state_fullscreen,
63 mir_surface_state_arraysize_64 mir_surface_state_arraysize_
64} MirSurfaceState;65} MirSurfaceState;
65
66/**@}*/66/**@}*/
6767
68#endif68#endif
6969
=== modified file 'include/test/mir_test_doubles/mock_buffer_stream.h'
--- include/test/mir_test_doubles/mock_buffer_stream.h 2013-06-19 16:41:13 +0000
+++ include/test/mir_test_doubles/mock_buffer_stream.h 2013-06-25 19:32:30 +0000
@@ -36,6 +36,8 @@
3636
37 MOCK_METHOD0(get_stream_pixel_format, geometry::PixelFormat());37 MOCK_METHOD0(get_stream_pixel_format, geometry::PixelFormat());
38 MOCK_METHOD0(stream_size, geometry::Size());38 MOCK_METHOD0(stream_size, geometry::Size());
39 MOCK_METHOD0(force_client_completion, void());
40 MOCK_METHOD1(allow_framedropping, void(bool));
39 MOCK_METHOD0(force_requests_to_complete, void());41 MOCK_METHOD0(force_requests_to_complete, void());
40};42};
41}43}
4244
=== modified file 'include/test/mir_test_doubles/mock_swapper_factory.h'
--- include/test/mir_test_doubles/mock_swapper_factory.h 2013-06-11 14:27:33 +0000
+++ include/test/mir_test_doubles/mock_swapper_factory.h 2013-06-25 19:32:30 +0000
@@ -33,8 +33,8 @@
33public:33public:
34 ~MockSwapperFactory() noexcept {}34 ~MockSwapperFactory() noexcept {}
3535
36 MOCK_CONST_METHOD3(create_swapper_reuse_buffers,36 MOCK_CONST_METHOD4(create_swapper_reuse_buffers,
37 std::shared_ptr<compositor::BufferSwapper>(37 std::shared_ptr<compositor::BufferSwapper>(compositor::BufferProperties const&,
38 std::vector<std::shared_ptr<compositor::Buffer>>&, size_t, compositor::SwapperType));38 std::vector<std::shared_ptr<compositor::Buffer>>&, size_t, compositor::SwapperType));
39 MOCK_CONST_METHOD3(create_swapper_new_buffers,39 MOCK_CONST_METHOD3(create_swapper_new_buffers,
40 std::shared_ptr<compositor::BufferSwapper>(40 std::shared_ptr<compositor::BufferSwapper>(
4141
=== modified file 'include/test/mir_test_doubles/stub_buffer_stream.h'
--- include/test/mir_test_doubles/stub_buffer_stream.h 2013-06-19 16:41:13 +0000
+++ include/test/mir_test_doubles/stub_buffer_stream.h 2013-06-25 19:32:30 +0000
@@ -61,6 +61,10 @@
61 {61 {
62 }62 }
6363
64 void allow_framedropping(bool)
65 {
66 }
67
64 std::shared_ptr<compositor::Buffer> stub_client_buffer;68 std::shared_ptr<compositor::Buffer> stub_client_buffer;
65 std::shared_ptr<compositor::Buffer> stub_compositor_buffer;69 std::shared_ptr<compositor::Buffer> stub_compositor_buffer;
66};70};
6771
=== modified file 'src/client/mir_client_library.cpp'
--- src/client/mir_client_library.cpp 2013-06-20 09:43:30 +0000
+++ src/client/mir_client_library.cpp 2013-06-25 19:32:30 +0000
@@ -316,3 +316,15 @@
316316
317 return state;317 return state;
318}318}
319
320MirWaitHandle* mir_surface_set_swapinterval(MirSurface* surf, int interval)
321{
322 if ((interval < 0) || (interval > 1))
323 return NULL;
324 return surf ? surf->configure(mir_surface_attrib_swapinterval, interval) : NULL;
325}
326
327int mir_surface_get_swapinterval(MirSurface* surf)
328{
329 return surf ? surf->attrib(mir_surface_attrib_swapinterval) : -1;
330}
319331
=== modified file 'src/client/mir_surface.cpp'
--- src/client/mir_surface.cpp 2013-06-20 09:43:30 +0000
+++ src/client/mir_surface.cpp 2013-06-25 19:32:30 +0000
@@ -58,6 +58,7 @@
58 attrib_cache[i] = -1;58 attrib_cache[i] = -1;
59 attrib_cache[mir_surface_attrib_type] = mir_surface_type_normal;59 attrib_cache[mir_surface_attrib_type] = mir_surface_type_normal;
60 attrib_cache[mir_surface_attrib_state] = mir_surface_state_unknown;60 attrib_cache[mir_surface_attrib_state] = mir_surface_state_unknown;
61 attrib_cache[mir_surface_attrib_swapinterval] = 1;
61}62}
6263
63MirSurface::~MirSurface()64MirSurface::~MirSurface()
@@ -269,6 +270,7 @@
269 {270 {
270 case mir_surface_attrib_type:271 case mir_surface_attrib_type:
271 case mir_surface_attrib_state:272 case mir_surface_attrib_state:
273 case mir_surface_attrib_swapinterval:
272 if (configure_result.has_ivalue())274 if (configure_result.has_ivalue())
273 attrib_cache[a] = configure_result.ivalue();275 attrib_cache[a] = configure_result.ivalue();
274 else276 else
275277
=== modified file 'src/server/compositor/buffer_stream_surfaces.cpp'
--- src/server/compositor/buffer_stream_surfaces.cpp 2013-06-19 16:41:13 +0000
+++ src/server/compositor/buffer_stream_surfaces.cpp 2013-06-25 19:32:30 +0000
@@ -63,3 +63,7 @@
63 buffer_bundle->force_requests_to_complete();63 buffer_bundle->force_requests_to_complete();
64}64}
6565
66void mc::BufferStreamSurfaces::allow_framedropping(bool allow)
67{
68 buffer_bundle->allow_framedropping(allow);
69}
6670
=== modified file 'src/server/compositor/swapper_factory.cpp'
--- src/server/compositor/swapper_factory.cpp 2013-06-11 19:55:10 +0000
+++ src/server/compositor/swapper_factory.cpp 2013-06-25 19:32:30 +0000
@@ -36,7 +36,8 @@
36 std::shared_ptr<GraphicBufferAllocator> const& gr_alloc,36 std::shared_ptr<GraphicBufferAllocator> const& gr_alloc,
37 int number_of_buffers)37 int number_of_buffers)
38 : gr_allocator(gr_alloc),38 : gr_allocator(gr_alloc),
39 number_of_buffers(number_of_buffers)39 synchronous_number_of_buffers(number_of_buffers),
40 spin_number_of_buffers(3) //spin algorithm always takes 3 buffers
40{41{
41}42}
4243
@@ -46,16 +47,43 @@
46{47{
47}48}
4849
50void mc::SwapperFactory::change_swapper_size(
51 std::vector<std::shared_ptr<mc::Buffer>>& list,
52 size_t const desired_size, size_t current_size, BufferProperties const& buffer_properties) const
53{
54 while (current_size < desired_size)
55 {
56 list.push_back(gr_allocator->alloc_buffer(buffer_properties));
57 current_size++;
58 }
59
60 while (current_size > desired_size)
61 {
62 if (list.empty())
63 {
64 BOOST_THROW_EXCEPTION(std::logic_error("SwapperFactory could not change algorithm"));
65 }
66 else
67 {
68 list.pop_back();
69 current_size--;
70 }
71 }
72}
73
49std::shared_ptr<mc::BufferSwapper> mc::SwapperFactory::create_swapper_reuse_buffers(74std::shared_ptr<mc::BufferSwapper> mc::SwapperFactory::create_swapper_reuse_buffers(
50 std::vector<std::shared_ptr<Buffer>>& list, size_t buffer_num, SwapperType type) const75 BufferProperties const& buffer_properties, std::vector<std::shared_ptr<Buffer>>& list,
76 size_t buffer_num, SwapperType type) const
51{77{
52 if (type == mc::SwapperType::synchronous)78 if (type == mc::SwapperType::synchronous)
53 {79 {
54 return std::make_shared<mc::BufferSwapperMulti>(list, buffer_num); 80 change_swapper_size(list, synchronous_number_of_buffers, buffer_num, buffer_properties);
81 return std::make_shared<mc::BufferSwapperMulti>(list, synchronous_number_of_buffers);
55 }82 }
56 else83 else
57 {84 {
58 return std::make_shared<mc::BufferSwapperSpin>(list, buffer_num);85 change_swapper_size(list, spin_number_of_buffers, buffer_num, buffer_properties);
86 return std::make_shared<mc::BufferSwapperSpin>(list, spin_number_of_buffers);
59 }87 }
60}88}
6189
@@ -68,20 +96,19 @@
6896
69 if (type == mc::SwapperType::synchronous)97 if (type == mc::SwapperType::synchronous)
70 {98 {
71 for(auto i=0; i< number_of_buffers; i++)99 for(auto i=0u; i< synchronous_number_of_buffers; i++)
72 {100 {
73 list.push_back(gr_allocator->alloc_buffer(requested_buffer_properties));101 list.push_back(gr_allocator->alloc_buffer(requested_buffer_properties));
74 }102 }
75 new_swapper = std::make_shared<mc::BufferSwapperMulti>(list, number_of_buffers);103 new_swapper = std::make_shared<mc::BufferSwapperMulti>(list, synchronous_number_of_buffers);
76 }104 }
77 else105 else
78 {106 {
79 int const async_buffer_count = 3; //async only can accept 3 buffers, so ignore constructor request107 for(auto i=0u; i < spin_number_of_buffers; i++)
80 for(auto i=0; i < async_buffer_count; i++)
81 {108 {
82 list.push_back(gr_allocator->alloc_buffer(requested_buffer_properties));109 list.push_back(gr_allocator->alloc_buffer(requested_buffer_properties));
83 }110 }
84 new_swapper = std::make_shared<mc::BufferSwapperSpin>(list, async_buffer_count);111 new_swapper = std::make_shared<mc::BufferSwapperSpin>(list, spin_number_of_buffers);
85 }112 }
86113
87 actual_buffer_properties = BufferProperties{114 actual_buffer_properties = BufferProperties{
88115
=== modified file 'src/server/compositor/switching_bundle.cpp'
--- src/server/compositor/switching_bundle.cpp 2013-06-15 11:09:16 +0000
+++ src/server/compositor/switching_bundle.cpp 2013-06-25 19:32:30 +0000
@@ -92,9 +92,9 @@
92 swapper->end_responsibility(list, size);92 swapper->end_responsibility(list, size);
9393
94 if (allow_dropping)94 if (allow_dropping)
95 swapper = swapper_factory->create_swapper_reuse_buffers(list, size, mc::SwapperType::framedropping); 95 swapper = swapper_factory->create_swapper_reuse_buffers(bundle_properties, list, size, mc::SwapperType::framedropping);
96 else96 else
97 swapper = swapper_factory->create_swapper_reuse_buffers(list, size, mc::SwapperType::synchronous); 97 swapper = swapper_factory->create_swapper_reuse_buffers(bundle_properties, list, size, mc::SwapperType::synchronous);
9898
99 cv.notify_all();99 cv.notify_all();
100}100}
101101
=== modified file 'src/server/shell/surface.cpp'
--- src/server/shell/surface.cpp 2013-06-25 05:42:49 +0000
+++ src/server/shell/surface.cpp 2013-06-25 19:32:30 +0000
@@ -189,6 +189,14 @@
189 }189 }
190}190}
191191
192void msh::Surface::allow_framedropping(bool allow)
193{
194 if (auto const& s = surface.lock())
195 {
196 s->allow_framedropping(allow);
197 }
198}
199
192void msh::Surface::with_most_recent_buffer_do(200void msh::Surface::with_most_recent_buffer_do(
193 std::function<void(mc::Buffer&)> const& exec)201 std::function<void(mc::Buffer&)> const& exec)
194{202{
@@ -242,7 +250,7 @@
242int msh::Surface::configure(MirSurfaceAttrib attrib, int value)250int msh::Surface::configure(MirSurfaceAttrib attrib, int value)
243{251{
244 int result = 0;252 int result = 0;
245253 bool allow_dropping = false;
246 /*254 /*
247 * TODO: In future, query the shell implementation for the subset of255 * TODO: In future, query the shell implementation for the subset of
248 * attributes/types it implements.256 * attributes/types it implements.
@@ -261,6 +269,11 @@
261 BOOST_THROW_EXCEPTION(std::logic_error("Invalid surface state."));269 BOOST_THROW_EXCEPTION(std::logic_error("Invalid surface state."));
262 result = state();270 result = state();
263 break;271 break;
272 case mir_surface_attrib_swapinterval:
273 allow_dropping = (value == 0);
274 allow_framedropping(allow_dropping);
275 result = value;
276 break;
264 default:277 default:
265 BOOST_THROW_EXCEPTION(std::logic_error("Invalid surface "278 BOOST_THROW_EXCEPTION(std::logic_error("Invalid surface "
266 "attribute."));279 "attribute."));
267280
=== modified file 'src/server/surfaces/surface.cpp'
--- src/server/surfaces/surface.cpp 2013-06-25 05:42:49 +0000
+++ src/server/surfaces/surface.cpp 2013-06-25 19:32:30 +0000
@@ -176,6 +176,11 @@
176 return buffer_stream->secure_client_buffer();176 return buffer_stream->secure_client_buffer();
177}177}
178178
179void ms::Surface::allow_framedropping(bool allow)
180{
181 buffer_stream->allow_framedropping(allow);
182}
183
179std::shared_ptr<mc::Buffer> ms::Surface::compositor_buffer() const184std::shared_ptr<mc::Buffer> ms::Surface::compositor_buffer() const
180{185{
181 return buffer_stream->lock_back_buffer();186 return buffer_stream->lock_back_buffer();
182187
=== modified file 'tests/integration-tests/CMakeLists.txt'
--- tests/integration-tests/CMakeLists.txt 2013-06-25 03:25:49 +0000
+++ tests/integration-tests/CMakeLists.txt 2013-06-25 19:32:30 +0000
@@ -7,6 +7,7 @@
7 test_display_info.cpp7 test_display_info.cpp
8 test_display_server_main_loop_events.cpp8 test_display_server_main_loop_events.cpp
9 test_surface_first_frame_sync.cpp9 test_surface_first_frame_sync.cpp
10 test_swapinterval.cpp
10)11)
1112
12add_subdirectory(client/)13add_subdirectory(client/)
1314
=== added file 'tests/integration-tests/test_swapinterval.cpp'
--- tests/integration-tests/test_swapinterval.cpp 1970-01-01 00:00:00 +0000
+++ tests/integration-tests/test_swapinterval.cpp 2013-06-25 19:32:30 +0000
@@ -0,0 +1,226 @@
1/*
2 * Copyright © 2013 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Kevin DuBois <kevin.dubois@canonical.com>
17 */
18
19#include "mir/geometry/rectangle.h"
20#include "mir/graphics/display.h"
21#include "mir/graphics/display_buffer.h"
22#include "mir/graphics/renderer.h"
23#include "mir/graphics/renderable.h"
24#include "mir/compositor/compositor.h"
25#include "mir/compositor/compositing_strategy.h"
26#include "mir/compositor/renderables.h"
27#include "mir/surfaces/buffer_stream.h"
28#include "mir/surfaces/buffer_stream_factory.h"
29
30#include "mir_test_framework/display_server_test_fixture.h"
31#include "mir_test_doubles/stub_buffer.h"
32
33#include "mir_toolkit/mir_client_library.h"
34
35#include <gtest/gtest.h>
36
37#include <thread>
38#include <unistd.h>
39#include <fcntl.h>
40
41namespace geom = mir::geometry;
42namespace mg = mir::graphics;
43namespace mc = mir::compositor;
44namespace mtf = mir_test_framework;
45namespace ms = mir::surfaces;
46namespace mtd = mir::test::doubles;
47
48namespace
49{
50char const* const mir_test_socket = mtf::test_socket_file().c_str();
51
52class CountingBufferStream : public ms::BufferStream
53{
54public:
55 CountingBufferStream(int render_operations_fd)
56 : render_operations_fd(render_operations_fd)
57 {
58 }
59
60 std::shared_ptr<mc::Buffer> secure_client_buffer() { return std::make_shared<mtd::StubBuffer>(); }
61 std::shared_ptr<mc::Buffer> lock_back_buffer() { return std::make_shared<mtd::StubBuffer>(); }
62 geom::PixelFormat get_stream_pixel_format() { return geom::PixelFormat::abgr_8888; }
63 geom::Size stream_size() { return geom::Size{}; }
64 void force_requests_to_complete() {}
65 void allow_framedropping(bool)
66 {
67 while (write(render_operations_fd, "a", 1) != 1) continue;
68 }
69
70private:
71 int render_operations_fd;
72};
73
74class StubStreamFactory : public ms::BufferStreamFactory
75{
76public:
77 StubStreamFactory(int render_operations_fd)
78 : render_operations_fd(render_operations_fd)
79 {
80 }
81
82 std::shared_ptr<ms::BufferStream> create_buffer_stream(mc::BufferProperties const&)
83 {
84 return std::make_shared<CountingBufferStream>(render_operations_fd);
85 }
86private:
87 int render_operations_fd;
88};
89
90}
91
92using SwapIntervalSignalTest = BespokeDisplayServerTestFixture;
93TEST_F(SwapIntervalSignalTest, swapinterval_test)
94{
95 static std::string const swapinterval_set{"swapinterval_set_952f3f10.tmp"};
96 static std::string const do_client_finish{"do_client_finish_952f3f10.tmp"};
97
98 std::remove(swapinterval_set.c_str());
99 std::remove(do_client_finish.c_str());
100
101 struct ServerConfig : TestingServerConfiguration
102 {
103 ServerConfig()
104 {
105 if (pipe(rendering_ops_pipe) != 0)
106 {
107 BOOST_THROW_EXCEPTION(
108 std::runtime_error("Failed to create pipe"));
109 }
110
111 if (fcntl(rendering_ops_pipe[0], F_SETFL, O_NONBLOCK) != 0)
112 {
113 BOOST_THROW_EXCEPTION(
114 std::runtime_error("Failed to make the read end of the pipe non-blocking"));
115 }
116 }
117
118 ~ServerConfig()
119 {
120 if (rendering_ops_pipe[0] >= 0)
121 close(rendering_ops_pipe[0]);
122 if (rendering_ops_pipe[1] >= 0)
123 close(rendering_ops_pipe[1]);
124 }
125
126 std::shared_ptr<ms::BufferStreamFactory> the_buffer_stream_factory() override
127 {
128 if (!stub_stream_factory)
129 stub_stream_factory = std::make_shared<StubStreamFactory>(rendering_ops_pipe[1]);
130 return stub_stream_factory;
131 }
132
133 int num_of_swapinterval_commands()
134 {
135 char c;
136 int ops{0};
137
138 while (read(rendering_ops_pipe[0], &c, 1) == 1)
139 ops++;
140
141 return ops;
142 }
143
144 int rendering_ops_pipe[2];
145 std::shared_ptr<StubStreamFactory> stub_stream_factory;
146 } server_config;
147
148 launch_server_process(server_config);
149
150 struct ClientConfig : TestingClientConfiguration
151 {
152 ClientConfig(std::string const& swapinterval_set,
153 std::string const& do_client_finish)
154 : swapinterval_set{swapinterval_set},
155 do_client_finish{do_client_finish}
156 {
157 }
158
159 static void surface_callback(MirSurface*, void*)
160 {
161 }
162
163 void exec()
164 {
165 MirSurfaceParameters request_params =
166 {
167 __PRETTY_FUNCTION__,
168 640, 480,
169 mir_pixel_format_abgr_8888,
170 mir_buffer_usage_hardware
171 };
172
173 MirConnection* connection = mir_connect_sync(mir_test_socket, "testapp");
174 MirSurface* surface = mir_connection_create_surface_sync(connection, &request_params);
175
176 //1 is the default swapinterval
177 EXPECT_EQ(1, mir_surface_get_swapinterval(surface));
178
179 mir_wait_for(mir_surface_set_swapinterval(surface, 0));
180 EXPECT_EQ(0, mir_surface_get_swapinterval(surface));
181
182 mir_wait_for(mir_surface_set_swapinterval(surface, 1));
183 EXPECT_EQ(1, mir_surface_get_swapinterval(surface));
184
185 //swapinterval 2 not supported
186 EXPECT_EQ(NULL, mir_surface_set_swapinterval(surface, 2));
187 EXPECT_EQ(1, mir_surface_get_swapinterval(surface));
188
189 set_flag(swapinterval_set);
190 wait_for(do_client_finish);
191
192 mir_surface_release_sync(surface);
193 mir_connection_release(connection);
194 }
195
196 /* TODO: Extract this flag mechanism and make it reusable */
197 void set_flag(std::string const& flag_file)
198 {
199 close(open(flag_file.c_str(), O_CREAT, S_IWUSR | S_IRUSR));
200 }
201
202 void wait_for(std::string const& flag_file)
203 {
204 int fd = -1;
205 while ((fd = open(flag_file.c_str(), O_RDONLY, S_IWUSR | S_IRUSR)) == -1)
206 {
207 std::this_thread::sleep_for(std::chrono::milliseconds(1));
208 }
209 close(fd);
210 }
211
212 std::string const swapinterval_set;
213 std::string const do_client_finish;
214 } client_config{swapinterval_set, do_client_finish};
215
216 launch_client_process(client_config);
217
218 run_in_test_process([&]
219 {
220 client_config.wait_for(swapinterval_set);
221
222 EXPECT_EQ(2, server_config.num_of_swapinterval_commands());
223
224 client_config.set_flag(do_client_finish);
225 });
226}
0227
=== modified file 'tests/unit-tests/compositor/test_buffer_stream.cpp'
--- tests/unit-tests/compositor/test_buffer_stream.cpp 2013-06-17 15:55:04 +0000
+++ tests/unit-tests/compositor/test_buffer_stream.cpp 2013-06-25 19:32:30 +0000
@@ -122,3 +122,12 @@
122122
123 buffer_stream.secure_client_buffer();123 buffer_stream.secure_client_buffer();
124}124}
125
126TEST_F(BufferStreamTest, allow_framedropping_command)
127{
128 EXPECT_CALL(*mock_bundle, allow_framedropping(true))
129 .Times(1);
130
131 mc::BufferStreamSurfaces buffer_stream(mock_bundle);
132 buffer_stream.allow_framedropping(true);
133}
125134
=== modified file 'tests/unit-tests/compositor/test_swapper_factory.cpp'
--- tests/unit-tests/compositor/test_swapper_factory.cpp 2013-06-11 19:55:10 +0000
+++ tests/unit-tests/compositor/test_swapper_factory.cpp 2013-06-25 19:32:30 +0000
@@ -147,6 +147,7 @@
147{147{
148 using namespace testing;148 using namespace testing;
149149
150 mc::BufferProperties properties;
150 std::vector<std::shared_ptr<mc::Buffer>> list {};151 std::vector<std::shared_ptr<mc::Buffer>> list {};
151 size_t size = 3;152 size_t size = 3;
152153
@@ -154,19 +155,66 @@
154 .Times(0);155 .Times(0);
155156
156 mc::SwapperFactory strategy(mock_buffer_allocator);157 mc::SwapperFactory strategy(mock_buffer_allocator);
157 auto swapper = strategy.create_swapper_reuse_buffers(list, size, mc::SwapperType::framedropping);158 auto swapper = strategy.create_swapper_reuse_buffers(properties, list, size, mc::SwapperType::framedropping);
158}159}
159160
160TEST_F(SwapperFactoryTest, create_sync_reuse)161TEST_F(SwapperFactoryTest, create_sync_reuse)
161{162{
162 using namespace testing;163 using namespace testing;
163164
165 mc::BufferProperties properties;
164 std::vector<std::shared_ptr<mc::Buffer>> list;166 std::vector<std::shared_ptr<mc::Buffer>> list;
165 size_t size = 3;167 size_t size = 3;
166168
167 EXPECT_CALL(*mock_buffer_allocator, alloc_buffer(properties))169 EXPECT_CALL(*mock_buffer_allocator, alloc_buffer(properties))
168 .Times(0);170 .Times(0);
169171
172 mc::SwapperFactory strategy(mock_buffer_allocator, 3);
173 auto swapper = strategy.create_swapper_reuse_buffers(properties, list, size, mc::SwapperType::synchronous);
174}
175
176TEST_F(SwapperFactoryTest, reuse_drop_unneeded_buffer)
177{
178 using namespace testing;
179
180 mc::SwapperFactory strategy(mock_buffer_allocator, 2);
181
182 auto buffer = std::make_shared<mtd::StubBuffer>();
183 {
184 size_t size = 3;
185 std::vector<std::shared_ptr<mc::Buffer>> list{buffer};
186
187 auto swapper = strategy.create_swapper_reuse_buffers(
188 properties, list, size, mc::SwapperType::synchronous);
189 }
190 EXPECT_EQ(1, buffer.use_count());
191}
192
193TEST_F(SwapperFactoryTest, reuse_drop_unneeded_buffer_error)
194{
195 using namespace testing;
196
197 mc::SwapperFactory strategy(mock_buffer_allocator, 2);
198
199 size_t size = 3;
200 std::vector<std::shared_ptr<mc::Buffer>> list{};
201
202 EXPECT_THROW({
203 strategy.create_swapper_reuse_buffers(
204 properties, list, size, mc::SwapperType::synchronous);
205 }, std::logic_error);
206}
207
208TEST_F(SwapperFactoryTest, reuse_alloc_additional_buffer_for_framedropping)
209{
210 using namespace testing;
211
212 EXPECT_CALL(*mock_buffer_allocator, alloc_buffer(_))
213 .Times(1);
170 mc::SwapperFactory strategy(mock_buffer_allocator);214 mc::SwapperFactory strategy(mock_buffer_allocator);
171 auto swapper = strategy.create_swapper_reuse_buffers(list, size, mc::SwapperType::synchronous);215
216 size_t size = 2;
217 std::vector<std::shared_ptr<mc::Buffer>> list{};
218 auto swapper = strategy.create_swapper_reuse_buffers(
219 properties, list, size, mc::SwapperType::framedropping);
172}220}
173221
=== modified file 'tests/unit-tests/compositor/test_switching_bundle.cpp'
--- tests/unit-tests/compositor/test_switching_bundle.cpp 2013-06-13 08:59:25 +0000
+++ tests/unit-tests/compositor/test_switching_bundle.cpp 2013-06-25 19:32:30 +0000
@@ -90,7 +90,7 @@
90 .WillOnce(Return(stub_buffer));90 .WillOnce(Return(stub_buffer));
91 EXPECT_CALL(*mock_secondary_swapper, client_release(stub_buffer))91 EXPECT_CALL(*mock_secondary_swapper, client_release(stub_buffer))
92 .Times(1);92 .Times(1);
93 EXPECT_CALL(*mock_swapper_factory, create_swapper_reuse_buffers(_,_,_))93 EXPECT_CALL(*mock_swapper_factory, create_swapper_reuse_buffers(_,_,_,_))
94 .Times(1)94 .Times(1)
95 .WillOnce(Return(mock_secondary_swapper));95 .WillOnce(Return(mock_secondary_swapper));
9696
@@ -126,7 +126,7 @@
126 .WillOnce(Return(stub_buffer));126 .WillOnce(Return(stub_buffer));
127 EXPECT_CALL(*mock_secondary_swapper, compositor_release(stub_buffer))127 EXPECT_CALL(*mock_secondary_swapper, compositor_release(stub_buffer))
128 .Times(1);128 .Times(1);
129 EXPECT_CALL(*mock_swapper_factory, create_swapper_reuse_buffers(_,_,_))129 EXPECT_CALL(*mock_swapper_factory, create_swapper_reuse_buffers(_,_,_,_))
130 .Times(1)130 .Times(1)
131 .WillOnce(Return(mock_secondary_swapper));131 .WillOnce(Return(mock_secondary_swapper));
132132
@@ -147,7 +147,7 @@
147 .Times(1);147 .Times(1);
148 EXPECT_CALL(*mock_default_swapper, end_responsibility(_,_))148 EXPECT_CALL(*mock_default_swapper, end_responsibility(_,_))
149 .Times(1);149 .Times(1);
150 EXPECT_CALL(*mock_swapper_factory, create_swapper_reuse_buffers(_,_,mc::SwapperType::framedropping))150 EXPECT_CALL(*mock_swapper_factory, create_swapper_reuse_buffers(_,_,_,mc::SwapperType::framedropping))
151 .Times(1)151 .Times(1)
152 .WillOnce(Return(mock_secondary_swapper));152 .WillOnce(Return(mock_secondary_swapper));
153153
154154
=== modified file 'tests/unit-tests/surfaces/test_surface.cpp'
--- tests/unit-tests/surfaces/test_surface.cpp 2013-06-25 05:42:49 +0000
+++ tests/unit-tests/surfaces/test_surface.cpp 2013-06-25 19:32:30 +0000
@@ -445,6 +445,18 @@
445 surf.force_requests_to_complete();445 surf.force_requests_to_complete();
446}446}
447447
448TEST_F(SurfaceCreation, test_surface_allow_framedropping)
449{
450 using namespace testing;
451
452 EXPECT_CALL(*mock_buffer_stream, allow_framedropping(true))
453 .Times(1);
454
455 ms::Surface surf{surface_name, geom::Point(), mock_buffer_stream,
456 std::shared_ptr<mi::InputChannel>(), mock_change_cb};
457 surf.allow_framedropping(true);
458}
459
448TEST_F(SurfaceCreation, test_surface_next_buffer_does_not_set_valid_until_second_frame)460TEST_F(SurfaceCreation, test_surface_next_buffer_does_not_set_valid_until_second_frame)
449{461{
450 ms::Surface surf{surface_name, geom::Point(), mock_buffer_stream,462 ms::Surface surf{surface_name, geom::Point(), mock_buffer_stream,

Subscribers

People subscribed via source and target branches