Merge lp:~kdub/mir/interval0-signal into lp:~mir-team/mir/trunk
- interval0-signal
- Merge into trunk
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 | ||||
Related bugs: |
|
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/integrati
still in pre-review, dependent on anativewindow-
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
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:/
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:758
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
UNSTABLE: http://
Click here to trigger a rebuild:
http://
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_
3. Consistency:
132 +typedef enum MirSurfacePerfo
133 +{
134 + mir_surface_
135 + mir_surface_
136 + mir_surface_
137 +} MirSurfacePerfo
"MirSurfacePerf
124 + mir_surface_
Although "hint" is a bit vague. Why not make the attribute named "swap_interval" or similar? Then you don't need MirSurfacePerfo
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_
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_
So really just #2-#4 need attention right now.
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::SwapperFact
297 + create_
298 - std::vector<
299 + BufferProperties const& buffer_properties, std::vector<
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_
289 + } else
else should be on separate line
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.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:764
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Daniel van Vugt (vanvugt) wrote : | # |
Thanks Kevin. I can see the requested changes made but have not re-reviewed yet.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:765
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Daniel van Vugt (vanvugt) wrote : | # |
A lot has landed today. So now we have:
Text conflict in src/server/
Text conflict in tests/unit-
2 conflicts encountered.
Daniel van Vugt (vanvugt) wrote : | # |
1. Conflicts:
Text conflict in src/server/
Text conflict in tests/unit-
2. Please resolve this inconsistency: "swapinterval" and "swap_interval".
Alexandros Frantzis (afrantzis) wrote : | # |
Looks good.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:766
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:767
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
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.
PS Jenkins bot (ps-jenkins) : | # |
Preview Diff
1 | === modified file 'include/client/mir_toolkit/mir_client_library.h' |
2 | --- include/client/mir_toolkit/mir_client_library.h 2013-06-20 09:43:30 +0000 |
3 | +++ include/client/mir_toolkit/mir_client_library.h 2013-06-25 19:32:30 +0000 |
4 | @@ -293,6 +293,27 @@ |
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 | + * At the time being, only swapinterval of 0 or 1 is supported. |
12 | + * \param [in] surface The surface to operate on |
13 | + * \param [in] interval The number of vblank signals that |
14 | + * mir_surface_swap_buffers will wait for |
15 | + * \return A wait handle that can be passed to mir_wait_for, |
16 | + * or NULL if the interval could not be supported |
17 | + */ |
18 | +MirWaitHandle* mir_surface_set_swapinterval(MirSurface* surface, int interval); |
19 | + |
20 | +/** |
21 | + * Query the swapinterval that the surface is operating with. |
22 | + * The default interval is 1. |
23 | + * \param [in] surface The surface to operate on |
24 | + * \return The swapinterval value that the client is operating with. |
25 | + * Returns -1 if surface is invalid. |
26 | + */ |
27 | +int mir_surface_get_swapinterval(MirSurface* surface); |
28 | + |
29 | #ifdef __cplusplus |
30 | } |
31 | /**@}*/ |
32 | |
33 | === modified file 'include/server/mir/compositor/buffer_allocation_strategy.h' |
34 | --- include/server/mir/compositor/buffer_allocation_strategy.h 2013-06-17 10:26:18 +0000 |
35 | +++ include/server/mir/compositor/buffer_allocation_strategy.h 2013-06-25 19:32:30 +0000 |
36 | @@ -45,7 +45,7 @@ |
37 | class BufferAllocationStrategy |
38 | { |
39 | public: |
40 | - virtual std::shared_ptr<BufferSwapper> create_swapper_reuse_buffers( |
41 | + virtual std::shared_ptr<BufferSwapper> create_swapper_reuse_buffers(BufferProperties const&, |
42 | std::vector<std::shared_ptr<Buffer>>&, size_t, SwapperType) const = 0; |
43 | virtual std::shared_ptr<BufferSwapper> create_swapper_new_buffers( |
44 | BufferProperties& actual_properties, BufferProperties const& requested_properties, SwapperType) const = 0; |
45 | |
46 | === modified file 'include/server/mir/compositor/buffer_stream_surfaces.h' |
47 | --- include/server/mir/compositor/buffer_stream_surfaces.h 2013-06-20 09:39:10 +0000 |
48 | +++ include/server/mir/compositor/buffer_stream_surfaces.h 2013-06-25 19:32:30 +0000 |
49 | @@ -46,6 +46,7 @@ |
50 | |
51 | geometry::PixelFormat get_stream_pixel_format(); |
52 | geometry::Size stream_size(); |
53 | + void allow_framedropping(bool); |
54 | void force_requests_to_complete(); |
55 | |
56 | protected: |
57 | |
58 | === modified file 'include/server/mir/compositor/swapper_factory.h' |
59 | --- include/server/mir/compositor/swapper_factory.h 2013-06-11 15:05:27 +0000 |
60 | +++ include/server/mir/compositor/swapper_factory.h 2013-06-25 19:32:30 +0000 |
61 | @@ -38,14 +38,18 @@ |
62 | std::shared_ptr<GraphicBufferAllocator> const& gr_alloc, |
63 | int number_of_buffers); |
64 | |
65 | - std::shared_ptr<BufferSwapper> create_swapper_reuse_buffers( |
66 | + std::shared_ptr<BufferSwapper> create_swapper_reuse_buffers(BufferProperties const&, |
67 | std::vector<std::shared_ptr<Buffer>>&, size_t, SwapperType) const; |
68 | std::shared_ptr<BufferSwapper> create_swapper_new_buffers( |
69 | BufferProperties& actual_properties, BufferProperties const& requested_properties, SwapperType) const; |
70 | |
71 | private: |
72 | + void change_swapper_size( |
73 | + std::vector<std::shared_ptr<Buffer>>&, size_t const, size_t, BufferProperties const&) const; |
74 | + |
75 | std::shared_ptr<GraphicBufferAllocator> const gr_allocator; |
76 | - int const number_of_buffers; |
77 | + unsigned int const synchronous_number_of_buffers; |
78 | + unsigned int const spin_number_of_buffers; |
79 | }; |
80 | } |
81 | } |
82 | |
83 | === modified file 'include/server/mir/shell/surface.h' |
84 | --- include/server/mir/shell/surface.h 2013-06-25 05:42:49 +0000 |
85 | +++ include/server/mir/shell/surface.h 2013-06-25 19:32:30 +0000 |
86 | @@ -87,6 +87,7 @@ |
87 | |
88 | virtual void take_input_focus(std::shared_ptr<InputTargeter> const& targeter); |
89 | |
90 | + virtual void allow_framedropping(bool); |
91 | private: |
92 | bool set_type(MirSurfaceType t); // Use configure() to make public changes |
93 | bool set_state(MirSurfaceState s); |
94 | |
95 | === modified file 'include/server/mir/surfaces/buffer_stream.h' |
96 | --- include/server/mir/surfaces/buffer_stream.h 2013-06-20 09:39:10 +0000 |
97 | +++ include/server/mir/surfaces/buffer_stream.h 2013-06-25 19:32:30 +0000 |
98 | @@ -45,6 +45,7 @@ |
99 | virtual std::shared_ptr<compositor::Buffer> lock_back_buffer() = 0; |
100 | virtual geometry::PixelFormat get_stream_pixel_format() = 0; |
101 | virtual geometry::Size stream_size() = 0; |
102 | + virtual void allow_framedropping(bool) = 0; |
103 | virtual void force_requests_to_complete() = 0; |
104 | }; |
105 | |
106 | |
107 | === modified file 'include/server/mir/surfaces/surface.h' |
108 | --- include/server/mir/surfaces/surface.h 2013-06-25 05:42:49 +0000 |
109 | +++ include/server/mir/surfaces/surface.h 2013-06-25 19:32:30 +0000 |
110 | @@ -81,6 +81,8 @@ |
111 | bool supports_input() const; |
112 | int client_input_fd() const; |
113 | int server_input_fd() const; |
114 | + |
115 | + void allow_framedropping(bool); |
116 | private: |
117 | std::string surface_name; |
118 | geometry::Point top_left_point; |
119 | |
120 | === modified file 'include/shared/mir_toolkit/common.h' |
121 | --- include/shared/mir_toolkit/common.h 2013-05-03 22:53:42 +0000 |
122 | +++ include/shared/mir_toolkit/common.h 2013-06-25 19:32:30 +0000 |
123 | @@ -35,6 +35,7 @@ |
124 | { |
125 | mir_surface_attrib_type, |
126 | mir_surface_attrib_state, |
127 | + mir_surface_attrib_swapinterval, |
128 | mir_surface_attrib_arraysize_ |
129 | } MirSurfaceAttrib; |
130 | |
131 | @@ -62,7 +63,6 @@ |
132 | mir_surface_state_fullscreen, |
133 | mir_surface_state_arraysize_ |
134 | } MirSurfaceState; |
135 | - |
136 | /**@}*/ |
137 | |
138 | #endif |
139 | |
140 | === modified file 'include/test/mir_test_doubles/mock_buffer_stream.h' |
141 | --- include/test/mir_test_doubles/mock_buffer_stream.h 2013-06-19 16:41:13 +0000 |
142 | +++ include/test/mir_test_doubles/mock_buffer_stream.h 2013-06-25 19:32:30 +0000 |
143 | @@ -36,6 +36,8 @@ |
144 | |
145 | MOCK_METHOD0(get_stream_pixel_format, geometry::PixelFormat()); |
146 | MOCK_METHOD0(stream_size, geometry::Size()); |
147 | + MOCK_METHOD0(force_client_completion, void()); |
148 | + MOCK_METHOD1(allow_framedropping, void(bool)); |
149 | MOCK_METHOD0(force_requests_to_complete, void()); |
150 | }; |
151 | } |
152 | |
153 | === modified file 'include/test/mir_test_doubles/mock_swapper_factory.h' |
154 | --- include/test/mir_test_doubles/mock_swapper_factory.h 2013-06-11 14:27:33 +0000 |
155 | +++ include/test/mir_test_doubles/mock_swapper_factory.h 2013-06-25 19:32:30 +0000 |
156 | @@ -33,8 +33,8 @@ |
157 | public: |
158 | ~MockSwapperFactory() noexcept {} |
159 | |
160 | - MOCK_CONST_METHOD3(create_swapper_reuse_buffers, |
161 | - std::shared_ptr<compositor::BufferSwapper>( |
162 | + MOCK_CONST_METHOD4(create_swapper_reuse_buffers, |
163 | + std::shared_ptr<compositor::BufferSwapper>(compositor::BufferProperties const&, |
164 | std::vector<std::shared_ptr<compositor::Buffer>>&, size_t, compositor::SwapperType)); |
165 | MOCK_CONST_METHOD3(create_swapper_new_buffers, |
166 | std::shared_ptr<compositor::BufferSwapper>( |
167 | |
168 | === modified file 'include/test/mir_test_doubles/stub_buffer_stream.h' |
169 | --- include/test/mir_test_doubles/stub_buffer_stream.h 2013-06-19 16:41:13 +0000 |
170 | +++ include/test/mir_test_doubles/stub_buffer_stream.h 2013-06-25 19:32:30 +0000 |
171 | @@ -61,6 +61,10 @@ |
172 | { |
173 | } |
174 | |
175 | + void allow_framedropping(bool) |
176 | + { |
177 | + } |
178 | + |
179 | std::shared_ptr<compositor::Buffer> stub_client_buffer; |
180 | std::shared_ptr<compositor::Buffer> stub_compositor_buffer; |
181 | }; |
182 | |
183 | === modified file 'src/client/mir_client_library.cpp' |
184 | --- src/client/mir_client_library.cpp 2013-06-20 09:43:30 +0000 |
185 | +++ src/client/mir_client_library.cpp 2013-06-25 19:32:30 +0000 |
186 | @@ -316,3 +316,15 @@ |
187 | |
188 | return state; |
189 | } |
190 | + |
191 | +MirWaitHandle* mir_surface_set_swapinterval(MirSurface* surf, int interval) |
192 | +{ |
193 | + if ((interval < 0) || (interval > 1)) |
194 | + return NULL; |
195 | + return surf ? surf->configure(mir_surface_attrib_swapinterval, interval) : NULL; |
196 | +} |
197 | + |
198 | +int mir_surface_get_swapinterval(MirSurface* surf) |
199 | +{ |
200 | + return surf ? surf->attrib(mir_surface_attrib_swapinterval) : -1; |
201 | +} |
202 | |
203 | === modified file 'src/client/mir_surface.cpp' |
204 | --- src/client/mir_surface.cpp 2013-06-20 09:43:30 +0000 |
205 | +++ src/client/mir_surface.cpp 2013-06-25 19:32:30 +0000 |
206 | @@ -58,6 +58,7 @@ |
207 | attrib_cache[i] = -1; |
208 | attrib_cache[mir_surface_attrib_type] = mir_surface_type_normal; |
209 | attrib_cache[mir_surface_attrib_state] = mir_surface_state_unknown; |
210 | + attrib_cache[mir_surface_attrib_swapinterval] = 1; |
211 | } |
212 | |
213 | MirSurface::~MirSurface() |
214 | @@ -269,6 +270,7 @@ |
215 | { |
216 | case mir_surface_attrib_type: |
217 | case mir_surface_attrib_state: |
218 | + case mir_surface_attrib_swapinterval: |
219 | if (configure_result.has_ivalue()) |
220 | attrib_cache[a] = configure_result.ivalue(); |
221 | else |
222 | |
223 | === modified file 'src/server/compositor/buffer_stream_surfaces.cpp' |
224 | --- src/server/compositor/buffer_stream_surfaces.cpp 2013-06-19 16:41:13 +0000 |
225 | +++ src/server/compositor/buffer_stream_surfaces.cpp 2013-06-25 19:32:30 +0000 |
226 | @@ -63,3 +63,7 @@ |
227 | buffer_bundle->force_requests_to_complete(); |
228 | } |
229 | |
230 | +void mc::BufferStreamSurfaces::allow_framedropping(bool allow) |
231 | +{ |
232 | + buffer_bundle->allow_framedropping(allow); |
233 | +} |
234 | |
235 | === modified file 'src/server/compositor/swapper_factory.cpp' |
236 | --- src/server/compositor/swapper_factory.cpp 2013-06-11 19:55:10 +0000 |
237 | +++ src/server/compositor/swapper_factory.cpp 2013-06-25 19:32:30 +0000 |
238 | @@ -36,7 +36,8 @@ |
239 | std::shared_ptr<GraphicBufferAllocator> const& gr_alloc, |
240 | int number_of_buffers) |
241 | : gr_allocator(gr_alloc), |
242 | - number_of_buffers(number_of_buffers) |
243 | + synchronous_number_of_buffers(number_of_buffers), |
244 | + spin_number_of_buffers(3) //spin algorithm always takes 3 buffers |
245 | { |
246 | } |
247 | |
248 | @@ -46,16 +47,43 @@ |
249 | { |
250 | } |
251 | |
252 | +void mc::SwapperFactory::change_swapper_size( |
253 | + std::vector<std::shared_ptr<mc::Buffer>>& list, |
254 | + size_t const desired_size, size_t current_size, BufferProperties const& buffer_properties) const |
255 | +{ |
256 | + while (current_size < desired_size) |
257 | + { |
258 | + list.push_back(gr_allocator->alloc_buffer(buffer_properties)); |
259 | + current_size++; |
260 | + } |
261 | + |
262 | + while (current_size > desired_size) |
263 | + { |
264 | + if (list.empty()) |
265 | + { |
266 | + BOOST_THROW_EXCEPTION(std::logic_error("SwapperFactory could not change algorithm")); |
267 | + } |
268 | + else |
269 | + { |
270 | + list.pop_back(); |
271 | + current_size--; |
272 | + } |
273 | + } |
274 | +} |
275 | + |
276 | std::shared_ptr<mc::BufferSwapper> mc::SwapperFactory::create_swapper_reuse_buffers( |
277 | - std::vector<std::shared_ptr<Buffer>>& list, size_t buffer_num, SwapperType type) const |
278 | + BufferProperties const& buffer_properties, std::vector<std::shared_ptr<Buffer>>& list, |
279 | + size_t buffer_num, SwapperType type) const |
280 | { |
281 | if (type == mc::SwapperType::synchronous) |
282 | { |
283 | - return std::make_shared<mc::BufferSwapperMulti>(list, buffer_num); |
284 | + change_swapper_size(list, synchronous_number_of_buffers, buffer_num, buffer_properties); |
285 | + return std::make_shared<mc::BufferSwapperMulti>(list, synchronous_number_of_buffers); |
286 | } |
287 | else |
288 | { |
289 | - return std::make_shared<mc::BufferSwapperSpin>(list, buffer_num); |
290 | + change_swapper_size(list, spin_number_of_buffers, buffer_num, buffer_properties); |
291 | + return std::make_shared<mc::BufferSwapperSpin>(list, spin_number_of_buffers); |
292 | } |
293 | } |
294 | |
295 | @@ -68,20 +96,19 @@ |
296 | |
297 | if (type == mc::SwapperType::synchronous) |
298 | { |
299 | - for(auto i=0; i< number_of_buffers; i++) |
300 | + for(auto i=0u; i< synchronous_number_of_buffers; i++) |
301 | { |
302 | list.push_back(gr_allocator->alloc_buffer(requested_buffer_properties)); |
303 | } |
304 | - new_swapper = std::make_shared<mc::BufferSwapperMulti>(list, number_of_buffers); |
305 | + new_swapper = std::make_shared<mc::BufferSwapperMulti>(list, synchronous_number_of_buffers); |
306 | } |
307 | else |
308 | { |
309 | - int const async_buffer_count = 3; //async only can accept 3 buffers, so ignore constructor request |
310 | - for(auto i=0; i < async_buffer_count; i++) |
311 | + for(auto i=0u; i < spin_number_of_buffers; i++) |
312 | { |
313 | list.push_back(gr_allocator->alloc_buffer(requested_buffer_properties)); |
314 | } |
315 | - new_swapper = std::make_shared<mc::BufferSwapperSpin>(list, async_buffer_count); |
316 | + new_swapper = std::make_shared<mc::BufferSwapperSpin>(list, spin_number_of_buffers); |
317 | } |
318 | |
319 | actual_buffer_properties = BufferProperties{ |
320 | |
321 | === modified file 'src/server/compositor/switching_bundle.cpp' |
322 | --- src/server/compositor/switching_bundle.cpp 2013-06-15 11:09:16 +0000 |
323 | +++ src/server/compositor/switching_bundle.cpp 2013-06-25 19:32:30 +0000 |
324 | @@ -92,9 +92,9 @@ |
325 | swapper->end_responsibility(list, size); |
326 | |
327 | if (allow_dropping) |
328 | - swapper = swapper_factory->create_swapper_reuse_buffers(list, size, mc::SwapperType::framedropping); |
329 | + swapper = swapper_factory->create_swapper_reuse_buffers(bundle_properties, list, size, mc::SwapperType::framedropping); |
330 | else |
331 | - swapper = swapper_factory->create_swapper_reuse_buffers(list, size, mc::SwapperType::synchronous); |
332 | + swapper = swapper_factory->create_swapper_reuse_buffers(bundle_properties, list, size, mc::SwapperType::synchronous); |
333 | |
334 | cv.notify_all(); |
335 | } |
336 | |
337 | === modified file 'src/server/shell/surface.cpp' |
338 | --- src/server/shell/surface.cpp 2013-06-25 05:42:49 +0000 |
339 | +++ src/server/shell/surface.cpp 2013-06-25 19:32:30 +0000 |
340 | @@ -189,6 +189,14 @@ |
341 | } |
342 | } |
343 | |
344 | +void msh::Surface::allow_framedropping(bool allow) |
345 | +{ |
346 | + if (auto const& s = surface.lock()) |
347 | + { |
348 | + s->allow_framedropping(allow); |
349 | + } |
350 | +} |
351 | + |
352 | void msh::Surface::with_most_recent_buffer_do( |
353 | std::function<void(mc::Buffer&)> const& exec) |
354 | { |
355 | @@ -242,7 +250,7 @@ |
356 | int msh::Surface::configure(MirSurfaceAttrib attrib, int value) |
357 | { |
358 | int result = 0; |
359 | - |
360 | + bool allow_dropping = false; |
361 | /* |
362 | * TODO: In future, query the shell implementation for the subset of |
363 | * attributes/types it implements. |
364 | @@ -261,6 +269,11 @@ |
365 | BOOST_THROW_EXCEPTION(std::logic_error("Invalid surface state.")); |
366 | result = state(); |
367 | break; |
368 | + case mir_surface_attrib_swapinterval: |
369 | + allow_dropping = (value == 0); |
370 | + allow_framedropping(allow_dropping); |
371 | + result = value; |
372 | + break; |
373 | default: |
374 | BOOST_THROW_EXCEPTION(std::logic_error("Invalid surface " |
375 | "attribute.")); |
376 | |
377 | === modified file 'src/server/surfaces/surface.cpp' |
378 | --- src/server/surfaces/surface.cpp 2013-06-25 05:42:49 +0000 |
379 | +++ src/server/surfaces/surface.cpp 2013-06-25 19:32:30 +0000 |
380 | @@ -176,6 +176,11 @@ |
381 | return buffer_stream->secure_client_buffer(); |
382 | } |
383 | |
384 | +void ms::Surface::allow_framedropping(bool allow) |
385 | +{ |
386 | + buffer_stream->allow_framedropping(allow); |
387 | +} |
388 | + |
389 | std::shared_ptr<mc::Buffer> ms::Surface::compositor_buffer() const |
390 | { |
391 | return buffer_stream->lock_back_buffer(); |
392 | |
393 | === modified file 'tests/integration-tests/CMakeLists.txt' |
394 | --- tests/integration-tests/CMakeLists.txt 2013-06-25 03:25:49 +0000 |
395 | +++ tests/integration-tests/CMakeLists.txt 2013-06-25 19:32:30 +0000 |
396 | @@ -7,6 +7,7 @@ |
397 | test_display_info.cpp |
398 | test_display_server_main_loop_events.cpp |
399 | test_surface_first_frame_sync.cpp |
400 | + test_swapinterval.cpp |
401 | ) |
402 | |
403 | add_subdirectory(client/) |
404 | |
405 | === added file 'tests/integration-tests/test_swapinterval.cpp' |
406 | --- tests/integration-tests/test_swapinterval.cpp 1970-01-01 00:00:00 +0000 |
407 | +++ tests/integration-tests/test_swapinterval.cpp 2013-06-25 19:32:30 +0000 |
408 | @@ -0,0 +1,226 @@ |
409 | +/* |
410 | + * Copyright © 2013 Canonical Ltd. |
411 | + * |
412 | + * This program is free software: you can redistribute it and/or modify |
413 | + * it under the terms of the GNU General Public License version 3 as |
414 | + * published by the Free Software Foundation. |
415 | + * |
416 | + * This program is distributed in the hope that it will be useful, |
417 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
418 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
419 | + * GNU General Public License for more details. |
420 | + * |
421 | + * You should have received a copy of the GNU General Public License |
422 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
423 | + * |
424 | + * Authored by: Kevin DuBois <kevin.dubois@canonical.com> |
425 | + */ |
426 | + |
427 | +#include "mir/geometry/rectangle.h" |
428 | +#include "mir/graphics/display.h" |
429 | +#include "mir/graphics/display_buffer.h" |
430 | +#include "mir/graphics/renderer.h" |
431 | +#include "mir/graphics/renderable.h" |
432 | +#include "mir/compositor/compositor.h" |
433 | +#include "mir/compositor/compositing_strategy.h" |
434 | +#include "mir/compositor/renderables.h" |
435 | +#include "mir/surfaces/buffer_stream.h" |
436 | +#include "mir/surfaces/buffer_stream_factory.h" |
437 | + |
438 | +#include "mir_test_framework/display_server_test_fixture.h" |
439 | +#include "mir_test_doubles/stub_buffer.h" |
440 | + |
441 | +#include "mir_toolkit/mir_client_library.h" |
442 | + |
443 | +#include <gtest/gtest.h> |
444 | + |
445 | +#include <thread> |
446 | +#include <unistd.h> |
447 | +#include <fcntl.h> |
448 | + |
449 | +namespace geom = mir::geometry; |
450 | +namespace mg = mir::graphics; |
451 | +namespace mc = mir::compositor; |
452 | +namespace mtf = mir_test_framework; |
453 | +namespace ms = mir::surfaces; |
454 | +namespace mtd = mir::test::doubles; |
455 | + |
456 | +namespace |
457 | +{ |
458 | +char const* const mir_test_socket = mtf::test_socket_file().c_str(); |
459 | + |
460 | +class CountingBufferStream : public ms::BufferStream |
461 | +{ |
462 | +public: |
463 | + CountingBufferStream(int render_operations_fd) |
464 | + : render_operations_fd(render_operations_fd) |
465 | + { |
466 | + } |
467 | + |
468 | + std::shared_ptr<mc::Buffer> secure_client_buffer() { return std::make_shared<mtd::StubBuffer>(); } |
469 | + std::shared_ptr<mc::Buffer> lock_back_buffer() { return std::make_shared<mtd::StubBuffer>(); } |
470 | + geom::PixelFormat get_stream_pixel_format() { return geom::PixelFormat::abgr_8888; } |
471 | + geom::Size stream_size() { return geom::Size{}; } |
472 | + void force_requests_to_complete() {} |
473 | + void allow_framedropping(bool) |
474 | + { |
475 | + while (write(render_operations_fd, "a", 1) != 1) continue; |
476 | + } |
477 | + |
478 | +private: |
479 | + int render_operations_fd; |
480 | +}; |
481 | + |
482 | +class StubStreamFactory : public ms::BufferStreamFactory |
483 | +{ |
484 | +public: |
485 | + StubStreamFactory(int render_operations_fd) |
486 | + : render_operations_fd(render_operations_fd) |
487 | + { |
488 | + } |
489 | + |
490 | + std::shared_ptr<ms::BufferStream> create_buffer_stream(mc::BufferProperties const&) |
491 | + { |
492 | + return std::make_shared<CountingBufferStream>(render_operations_fd); |
493 | + } |
494 | +private: |
495 | + int render_operations_fd; |
496 | +}; |
497 | + |
498 | +} |
499 | + |
500 | +using SwapIntervalSignalTest = BespokeDisplayServerTestFixture; |
501 | +TEST_F(SwapIntervalSignalTest, swapinterval_test) |
502 | +{ |
503 | + static std::string const swapinterval_set{"swapinterval_set_952f3f10.tmp"}; |
504 | + static std::string const do_client_finish{"do_client_finish_952f3f10.tmp"}; |
505 | + |
506 | + std::remove(swapinterval_set.c_str()); |
507 | + std::remove(do_client_finish.c_str()); |
508 | + |
509 | + struct ServerConfig : TestingServerConfiguration |
510 | + { |
511 | + ServerConfig() |
512 | + { |
513 | + if (pipe(rendering_ops_pipe) != 0) |
514 | + { |
515 | + BOOST_THROW_EXCEPTION( |
516 | + std::runtime_error("Failed to create pipe")); |
517 | + } |
518 | + |
519 | + if (fcntl(rendering_ops_pipe[0], F_SETFL, O_NONBLOCK) != 0) |
520 | + { |
521 | + BOOST_THROW_EXCEPTION( |
522 | + std::runtime_error("Failed to make the read end of the pipe non-blocking")); |
523 | + } |
524 | + } |
525 | + |
526 | + ~ServerConfig() |
527 | + { |
528 | + if (rendering_ops_pipe[0] >= 0) |
529 | + close(rendering_ops_pipe[0]); |
530 | + if (rendering_ops_pipe[1] >= 0) |
531 | + close(rendering_ops_pipe[1]); |
532 | + } |
533 | + |
534 | + std::shared_ptr<ms::BufferStreamFactory> the_buffer_stream_factory() override |
535 | + { |
536 | + if (!stub_stream_factory) |
537 | + stub_stream_factory = std::make_shared<StubStreamFactory>(rendering_ops_pipe[1]); |
538 | + return stub_stream_factory; |
539 | + } |
540 | + |
541 | + int num_of_swapinterval_commands() |
542 | + { |
543 | + char c; |
544 | + int ops{0}; |
545 | + |
546 | + while (read(rendering_ops_pipe[0], &c, 1) == 1) |
547 | + ops++; |
548 | + |
549 | + return ops; |
550 | + } |
551 | + |
552 | + int rendering_ops_pipe[2]; |
553 | + std::shared_ptr<StubStreamFactory> stub_stream_factory; |
554 | + } server_config; |
555 | + |
556 | + launch_server_process(server_config); |
557 | + |
558 | + struct ClientConfig : TestingClientConfiguration |
559 | + { |
560 | + ClientConfig(std::string const& swapinterval_set, |
561 | + std::string const& do_client_finish) |
562 | + : swapinterval_set{swapinterval_set}, |
563 | + do_client_finish{do_client_finish} |
564 | + { |
565 | + } |
566 | + |
567 | + static void surface_callback(MirSurface*, void*) |
568 | + { |
569 | + } |
570 | + |
571 | + void exec() |
572 | + { |
573 | + MirSurfaceParameters request_params = |
574 | + { |
575 | + __PRETTY_FUNCTION__, |
576 | + 640, 480, |
577 | + mir_pixel_format_abgr_8888, |
578 | + mir_buffer_usage_hardware |
579 | + }; |
580 | + |
581 | + MirConnection* connection = mir_connect_sync(mir_test_socket, "testapp"); |
582 | + MirSurface* surface = mir_connection_create_surface_sync(connection, &request_params); |
583 | + |
584 | + //1 is the default swapinterval |
585 | + EXPECT_EQ(1, mir_surface_get_swapinterval(surface)); |
586 | + |
587 | + mir_wait_for(mir_surface_set_swapinterval(surface, 0)); |
588 | + EXPECT_EQ(0, mir_surface_get_swapinterval(surface)); |
589 | + |
590 | + mir_wait_for(mir_surface_set_swapinterval(surface, 1)); |
591 | + EXPECT_EQ(1, mir_surface_get_swapinterval(surface)); |
592 | + |
593 | + //swapinterval 2 not supported |
594 | + EXPECT_EQ(NULL, mir_surface_set_swapinterval(surface, 2)); |
595 | + EXPECT_EQ(1, mir_surface_get_swapinterval(surface)); |
596 | + |
597 | + set_flag(swapinterval_set); |
598 | + wait_for(do_client_finish); |
599 | + |
600 | + mir_surface_release_sync(surface); |
601 | + mir_connection_release(connection); |
602 | + } |
603 | + |
604 | + /* TODO: Extract this flag mechanism and make it reusable */ |
605 | + void set_flag(std::string const& flag_file) |
606 | + { |
607 | + close(open(flag_file.c_str(), O_CREAT, S_IWUSR | S_IRUSR)); |
608 | + } |
609 | + |
610 | + void wait_for(std::string const& flag_file) |
611 | + { |
612 | + int fd = -1; |
613 | + while ((fd = open(flag_file.c_str(), O_RDONLY, S_IWUSR | S_IRUSR)) == -1) |
614 | + { |
615 | + std::this_thread::sleep_for(std::chrono::milliseconds(1)); |
616 | + } |
617 | + close(fd); |
618 | + } |
619 | + |
620 | + std::string const swapinterval_set; |
621 | + std::string const do_client_finish; |
622 | + } client_config{swapinterval_set, do_client_finish}; |
623 | + |
624 | + launch_client_process(client_config); |
625 | + |
626 | + run_in_test_process([&] |
627 | + { |
628 | + client_config.wait_for(swapinterval_set); |
629 | + |
630 | + EXPECT_EQ(2, server_config.num_of_swapinterval_commands()); |
631 | + |
632 | + client_config.set_flag(do_client_finish); |
633 | + }); |
634 | +} |
635 | |
636 | === modified file 'tests/unit-tests/compositor/test_buffer_stream.cpp' |
637 | --- tests/unit-tests/compositor/test_buffer_stream.cpp 2013-06-17 15:55:04 +0000 |
638 | +++ tests/unit-tests/compositor/test_buffer_stream.cpp 2013-06-25 19:32:30 +0000 |
639 | @@ -122,3 +122,12 @@ |
640 | |
641 | buffer_stream.secure_client_buffer(); |
642 | } |
643 | + |
644 | +TEST_F(BufferStreamTest, allow_framedropping_command) |
645 | +{ |
646 | + EXPECT_CALL(*mock_bundle, allow_framedropping(true)) |
647 | + .Times(1); |
648 | + |
649 | + mc::BufferStreamSurfaces buffer_stream(mock_bundle); |
650 | + buffer_stream.allow_framedropping(true); |
651 | +} |
652 | |
653 | === modified file 'tests/unit-tests/compositor/test_swapper_factory.cpp' |
654 | --- tests/unit-tests/compositor/test_swapper_factory.cpp 2013-06-11 19:55:10 +0000 |
655 | +++ tests/unit-tests/compositor/test_swapper_factory.cpp 2013-06-25 19:32:30 +0000 |
656 | @@ -147,6 +147,7 @@ |
657 | { |
658 | using namespace testing; |
659 | |
660 | + mc::BufferProperties properties; |
661 | std::vector<std::shared_ptr<mc::Buffer>> list {}; |
662 | size_t size = 3; |
663 | |
664 | @@ -154,19 +155,66 @@ |
665 | .Times(0); |
666 | |
667 | mc::SwapperFactory strategy(mock_buffer_allocator); |
668 | - auto swapper = strategy.create_swapper_reuse_buffers(list, size, mc::SwapperType::framedropping); |
669 | + auto swapper = strategy.create_swapper_reuse_buffers(properties, list, size, mc::SwapperType::framedropping); |
670 | } |
671 | |
672 | TEST_F(SwapperFactoryTest, create_sync_reuse) |
673 | { |
674 | using namespace testing; |
675 | |
676 | + mc::BufferProperties properties; |
677 | std::vector<std::shared_ptr<mc::Buffer>> list; |
678 | size_t size = 3; |
679 | |
680 | EXPECT_CALL(*mock_buffer_allocator, alloc_buffer(properties)) |
681 | .Times(0); |
682 | |
683 | + mc::SwapperFactory strategy(mock_buffer_allocator, 3); |
684 | + auto swapper = strategy.create_swapper_reuse_buffers(properties, list, size, mc::SwapperType::synchronous); |
685 | +} |
686 | + |
687 | +TEST_F(SwapperFactoryTest, reuse_drop_unneeded_buffer) |
688 | +{ |
689 | + using namespace testing; |
690 | + |
691 | + mc::SwapperFactory strategy(mock_buffer_allocator, 2); |
692 | + |
693 | + auto buffer = std::make_shared<mtd::StubBuffer>(); |
694 | + { |
695 | + size_t size = 3; |
696 | + std::vector<std::shared_ptr<mc::Buffer>> list{buffer}; |
697 | + |
698 | + auto swapper = strategy.create_swapper_reuse_buffers( |
699 | + properties, list, size, mc::SwapperType::synchronous); |
700 | + } |
701 | + EXPECT_EQ(1, buffer.use_count()); |
702 | +} |
703 | + |
704 | +TEST_F(SwapperFactoryTest, reuse_drop_unneeded_buffer_error) |
705 | +{ |
706 | + using namespace testing; |
707 | + |
708 | + mc::SwapperFactory strategy(mock_buffer_allocator, 2); |
709 | + |
710 | + size_t size = 3; |
711 | + std::vector<std::shared_ptr<mc::Buffer>> list{}; |
712 | + |
713 | + EXPECT_THROW({ |
714 | + strategy.create_swapper_reuse_buffers( |
715 | + properties, list, size, mc::SwapperType::synchronous); |
716 | + }, std::logic_error); |
717 | +} |
718 | + |
719 | +TEST_F(SwapperFactoryTest, reuse_alloc_additional_buffer_for_framedropping) |
720 | +{ |
721 | + using namespace testing; |
722 | + |
723 | + EXPECT_CALL(*mock_buffer_allocator, alloc_buffer(_)) |
724 | + .Times(1); |
725 | mc::SwapperFactory strategy(mock_buffer_allocator); |
726 | - auto swapper = strategy.create_swapper_reuse_buffers(list, size, mc::SwapperType::synchronous); |
727 | + |
728 | + size_t size = 2; |
729 | + std::vector<std::shared_ptr<mc::Buffer>> list{}; |
730 | + auto swapper = strategy.create_swapper_reuse_buffers( |
731 | + properties, list, size, mc::SwapperType::framedropping); |
732 | } |
733 | |
734 | === modified file 'tests/unit-tests/compositor/test_switching_bundle.cpp' |
735 | --- tests/unit-tests/compositor/test_switching_bundle.cpp 2013-06-13 08:59:25 +0000 |
736 | +++ tests/unit-tests/compositor/test_switching_bundle.cpp 2013-06-25 19:32:30 +0000 |
737 | @@ -90,7 +90,7 @@ |
738 | .WillOnce(Return(stub_buffer)); |
739 | EXPECT_CALL(*mock_secondary_swapper, client_release(stub_buffer)) |
740 | .Times(1); |
741 | - EXPECT_CALL(*mock_swapper_factory, create_swapper_reuse_buffers(_,_,_)) |
742 | + EXPECT_CALL(*mock_swapper_factory, create_swapper_reuse_buffers(_,_,_,_)) |
743 | .Times(1) |
744 | .WillOnce(Return(mock_secondary_swapper)); |
745 | |
746 | @@ -126,7 +126,7 @@ |
747 | .WillOnce(Return(stub_buffer)); |
748 | EXPECT_CALL(*mock_secondary_swapper, compositor_release(stub_buffer)) |
749 | .Times(1); |
750 | - EXPECT_CALL(*mock_swapper_factory, create_swapper_reuse_buffers(_,_,_)) |
751 | + EXPECT_CALL(*mock_swapper_factory, create_swapper_reuse_buffers(_,_,_,_)) |
752 | .Times(1) |
753 | .WillOnce(Return(mock_secondary_swapper)); |
754 | |
755 | @@ -147,7 +147,7 @@ |
756 | .Times(1); |
757 | EXPECT_CALL(*mock_default_swapper, end_responsibility(_,_)) |
758 | .Times(1); |
759 | - EXPECT_CALL(*mock_swapper_factory, create_swapper_reuse_buffers(_,_,mc::SwapperType::framedropping)) |
760 | + EXPECT_CALL(*mock_swapper_factory, create_swapper_reuse_buffers(_,_,_,mc::SwapperType::framedropping)) |
761 | .Times(1) |
762 | .WillOnce(Return(mock_secondary_swapper)); |
763 | |
764 | |
765 | === modified file 'tests/unit-tests/surfaces/test_surface.cpp' |
766 | --- tests/unit-tests/surfaces/test_surface.cpp 2013-06-25 05:42:49 +0000 |
767 | +++ tests/unit-tests/surfaces/test_surface.cpp 2013-06-25 19:32:30 +0000 |
768 | @@ -445,6 +445,18 @@ |
769 | surf.force_requests_to_complete(); |
770 | } |
771 | |
772 | +TEST_F(SurfaceCreation, test_surface_allow_framedropping) |
773 | +{ |
774 | + using namespace testing; |
775 | + |
776 | + EXPECT_CALL(*mock_buffer_stream, allow_framedropping(true)) |
777 | + .Times(1); |
778 | + |
779 | + ms::Surface surf{surface_name, geom::Point(), mock_buffer_stream, |
780 | + std::shared_ptr<mi::InputChannel>(), mock_change_cb}; |
781 | + surf.allow_framedropping(true); |
782 | +} |
783 | + |
784 | TEST_F(SurfaceCreation, test_surface_next_buffer_does_not_set_valid_until_second_frame) |
785 | { |
786 | ms::Surface surf{surface_name, geom::Point(), mock_buffer_stream, |
FAILED: Continuous integration, rev:758 jenkins. qa.ubuntu. com/job/ mir-ci/ 751/ jenkins. qa.ubuntu. com/job/ mir-android- raring- i386-build/ 937/console jenkins. qa.ubuntu. com/job/ mir-clang- raring- amd64-build/ 819/console jenkins. qa.ubuntu. com/job/ mir-raring- amd64-ci/ 236/console jenkins. qa.ubuntu. com/job/ mir-vm- ci-build/ ./distribution= quantal, flavor= amd64/435
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins: 8080/job/ mir-ci/ 751/rebuild
http://