Merge lp:~afrantzis/mir/client-surface-buffering-mode into lp:mir
- client-surface-buffering-mode
- Merge into development-branch
Status: | Work in progress |
---|---|
Proposed branch: | lp:~afrantzis/mir/client-surface-buffering-mode |
Merge into: | lp:mir |
Diff against target: |
499 lines (+233/-12) 18 files modified
include/client/mir_toolkit/mir_surface.h (+8/-0) include/common/mir_toolkit/common.h (+7/-0) include/server/mir/scene/surface_creation_parameters.h (+1/-0) src/client/mir_surface.cpp (+2/-0) src/client/mir_surface.h (+1/-0) src/client/mir_surface_api.cpp (+6/-0) src/client/symbols.map (+1/-0) src/protobuf/mir_protobuf.proto (+4/-0) src/server/frontend/session_mediator.cpp (+1/-0) src/server/scene/surface_allocator.cpp (+10/-2) src/server/scene/surface_creation_parameters.cpp (+1/-0) tests/acceptance-tests/CMakeLists.txt (+1/-0) tests/acceptance-tests/test_client_surface_buffering_mode.cpp (+133/-0) tests/include/mir_test_doubles/null_display_sync_group.h (+19/-3) tests/include/mir_test_doubles/stub_display.h (+13/-6) tests/include/mir_test_framework/stub_server_platform_factory.h (+3/-0) tests/mir_test_framework/stub_server_platform_factory.cpp (+13/-0) tests/mir_test_framework/stubbed_graphics_platform.cpp (+9/-1) |
To merge this branch: | bzr merge lp:~afrantzis/mir/client-surface-buffering-mode |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Robert Carr (community) | Approve | ||
Chris Halse Rogers | Needs Information | ||
PS Jenkins bot (community) | continuous-integration | Approve | |
Kevin DuBois (community) | Needs Information | ||
Daniel van Vugt | Needs Fixing | ||
Alan Griffiths | Approve | ||
Review via email: mp+256455@code.launchpad.net |
Commit message
client,server: Allow clients to specify the buffering mode for their surfaces
Description of the change
client,server: Allow clients to specify the buffering mode for their surfaces
This MP only allows setting the buffering mode at surface creation time. In the future it may be useful to also allow changing the buffering mode after creation time.
Alan Griffiths (alan-griffiths) wrote : | # |
std::chrono:
You can use literals now
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:2490
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alexandros Frantzis (afrantzis) wrote : | # |
7: [ FAILED ] ServerShutdown.
7: [ FAILED ] ClientFocusNoti
7: [ FAILED ] ClientFocusNoti
7: [ FAILED ] ClientCredsTest
7: [ FAILED ] ClientCredsTest
7: [ FAILED ] ServerDisconnec
7: [ FAILED ] ServerDisconnec
7: [ FAILED ] ServerDisconnec
7: [ FAILED ] ServerStartup.
7: [ FAILED ] ServerStartup.
7: [ FAILED ] UnresponsiveCli
7: [ FAILED ] CustomInputDisp
7: [ FAILED ] CustomInputDisp
7: [ FAILED ] CustomInputDisp
7: [ FAILED ] FocusSelection.
7: [ FAILED ] FocusSelection.
11: [ FAILED ] MultiplexingDis
Ehh?
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:2490
http://
Executed test runs:
None: http://
None: http://
None: http://
None: http://
Click here to trigger a rebuild:
http://
Daniel van Vugt (vanvugt) wrote : | # |
(0) In general I don't think this is a good idea. When I finish dynamic switching:
https:/
only clients using the default auto setting will benefit. But we want all clients to benefit. So I suggest disapprove based on that.
(1) This enum doesn't need to exist. An int is clearer:
28 +typedef enum MirBufferingMode
29 +{
30 + mir_buffering_
31 + mir_buffering_
32 + mir_buffering_
33 +} MirBufferingMode;
Daniel van Vugt (vanvugt) wrote : | # |
(0) Come to think of it, there still is a use case for this. In future if we support single buffering properly then we need this interface.
(1) Still needs to be an int.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:2490
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Kevin DuBois (kdub) wrote : | # |
It might be more flexible to just let the clients acquire more than one buffer at once, and then the clients just submit the buffer that they last-generated to the server for it to use.
Advantages:
* Gets us a bit closer to server-
* This diffuses the density of the logic in BufferQueue a bit, as the client shares in the responsibility of how the flip chain works.
* The server doesn't even have to know if the client is running in swapinterval 0 or not, it would just have a last-submitted buffer.
* Nested-passthrough can use the normal BufferQueue, instead of dancing around the limitation that it can only get one buffer at a time.
* nested becomes an normal platform, as it has a way to allocate a buffer.
* we don't have to hash out what "double" and "triple" means exactly in the client api.
- 2491. By Alexandros Frantzis
-
client: Make mir_surface_
spec_set_ buffering_ mode symbol public
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:2491
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Chris Halse Rogers (raof) wrote : | # |
*Needs discussion*
It *would* be more flexible for the client to be able to borrow multiple buffers. The simplifications Kevin mentions look pretty enticing.
It'd also make Daniel happy; we can make es2gears produce higher numbers in swapinterval 0 mode :).
This seems like it'd need a bit of design, though; particularly - what happens on resize or other invalidation, does the client need to submit buffers in the same order as received from the server?
Also worth wondering how we can use this to make Vulkan WSI easier.
Alberto Aguirre (albaguirre) wrote : | # |
> (0) In general I don't think this is a good idea. When I finish dynamic
> switching:
> https:/
> only clients using the default auto setting will benefit. But we want all
> clients to benefit. So I suggest disapprove based on that.
Any predictive algorithm needs the ability to be disabled. Especially by the client, as that the entity that has more knowledge about it's own rendering (And the tradeoffs it wants to make) that what you can guess at the server
Robert Carr (robertcarr) wrote : | # |
Kevins approach is compelling.
This is a good gain for now though.
Daniel van Vugt (vanvugt) wrote : | # |
"Kevin's approach" sounds like what was described in bug 1253868. Maybe we need to reopen that...
Alexandros Frantzis (afrantzis) wrote : | # |
It seems that we need to make some decisions at a higher level first (i.e. do allow clients to hold multiple buffers?) before deciding whether what's proposed in this MP is needed. The sprint seems a good time to discuss further.
Chris Halse Rogers (raof) wrote : | # |
Yeah, I was expecting that we'd discuss this at the sprint.
Unmerged revisions
- 2491. By Alexandros Frantzis
-
client: Make mir_surface_
spec_set_ buffering_ mode symbol public - 2490. By Alexandros Frantzis
-
client,server: Allow clients to specify the buffering mode for their surface
Preview Diff
1 | === modified file 'include/client/mir_toolkit/mir_surface.h' |
2 | --- include/client/mir_toolkit/mir_surface.h 2015-04-14 11:29:11 +0000 |
3 | +++ include/client/mir_toolkit/mir_surface.h 2015-04-17 13:13:57 +0000 |
4 | @@ -323,6 +323,14 @@ |
5 | bool mir_surface_spec_set_preferred_orientation(MirSurfaceSpec* spec, MirOrientationMode mode); |
6 | |
7 | /** |
8 | + * Set the requested buffering mode. |
9 | + * \param [in] spec Specification to mutate |
10 | + * \param [in] mode Requested buffering mode |
11 | + * \return False if buffering mode is not a valid attribute of this surface type. |
12 | + */ |
13 | +bool mir_surface_spec_set_buffering_mode(MirSurfaceSpec* spec, MirBufferingMode mode); |
14 | + |
15 | +/** |
16 | * Release the resources held by a MirSurfaceSpec. |
17 | * |
18 | * \param [in] spec Specification to release |
19 | |
20 | === modified file 'include/common/mir_toolkit/common.h' |
21 | --- include/common/mir_toolkit/common.h 2015-03-31 02:35:42 +0000 |
22 | +++ include/common/mir_toolkit/common.h 2015-04-17 13:13:57 +0000 |
23 | @@ -166,6 +166,13 @@ |
24 | mir_edge_attachment_any = mir_edge_attachment_vertical | |
25 | mir_edge_attachment_horizontal |
26 | } MirEdgeAttachment; |
27 | + |
28 | +typedef enum MirBufferingMode |
29 | +{ |
30 | + mir_buffering_mode_default = 0, |
31 | + mir_buffering_mode_double = 2, |
32 | + mir_buffering_mode_triple = 3 |
33 | +} MirBufferingMode; |
34 | /**@}*/ |
35 | |
36 | #endif |
37 | |
38 | === modified file 'include/server/mir/scene/surface_creation_parameters.h' |
39 | --- include/server/mir/scene/surface_creation_parameters.h 2015-04-14 10:23:11 +0000 |
40 | +++ include/server/mir/scene/surface_creation_parameters.h 2015-04-17 13:13:57 +0000 |
41 | @@ -87,6 +87,7 @@ |
42 | mir::optional_value<frontend::SurfaceId> parent_id; |
43 | mir::optional_value<geometry::Rectangle> aux_rect; |
44 | mir::optional_value<MirEdgeAttachment> edge_attachment; |
45 | + mir::optional_value<MirBufferingMode> buffering_mode; |
46 | |
47 | std::weak_ptr<Surface> parent; |
48 | |
49 | |
50 | === modified file 'src/client/mir_surface.cpp' |
51 | --- src/client/mir_surface.cpp 2015-04-14 11:29:11 +0000 |
52 | +++ src/client/mir_surface.cpp 2015-04-17 13:13:57 +0000 |
53 | @@ -96,6 +96,7 @@ |
54 | SERIALIZE_OPTION_IF_SET(min_height, message); |
55 | SERIALIZE_OPTION_IF_SET(max_width, message); |
56 | SERIALIZE_OPTION_IF_SET(max_height, message); |
57 | + SERIALIZE_OPTION_IF_SET(buffering_mode, message); |
58 | |
59 | if (parent.is_set() && parent.value() != nullptr) |
60 | message.set_parent_id(parent.value()->id()); |
61 | @@ -563,6 +564,7 @@ |
62 | COPY_IF_SET(min_height); |
63 | COPY_IF_SET(max_width); |
64 | COPY_IF_SET(max_height); |
65 | + COPY_IF_SET(buffering_mode); |
66 | #undef COPY_IF_SET |
67 | |
68 | if (spec.surface_name.is_set()) |
69 | |
70 | === modified file 'src/client/mir_surface.h' |
71 | --- src/client/mir_surface.h 2015-04-09 15:59:52 +0000 |
72 | +++ src/client/mir_surface.h 2015-04-17 13:13:57 +0000 |
73 | @@ -75,6 +75,7 @@ |
74 | mir::optional_value<int> height; |
75 | mir::optional_value<MirPixelFormat> pixel_format; |
76 | mir::optional_value<MirBufferUsage> buffer_usage; |
77 | + mir::optional_value<MirBufferingMode> buffering_mode; |
78 | |
79 | mir::optional_value<std::string> surface_name; |
80 | mir::optional_value<uint32_t> output_id; |
81 | |
82 | === modified file 'src/client/mir_surface_api.cpp' |
83 | --- src/client/mir_surface_api.cpp 2015-04-16 08:32:47 +0000 |
84 | +++ src/client/mir_surface_api.cpp 2015-04-17 13:13:57 +0000 |
85 | @@ -224,6 +224,12 @@ |
86 | return true; |
87 | } |
88 | |
89 | +bool mir_surface_spec_set_buffering_mode(MirSurfaceSpec* spec, MirBufferingMode mode) |
90 | +{ |
91 | + spec->buffering_mode = mode; |
92 | + return true; |
93 | +} |
94 | + |
95 | void mir_surface_spec_release(MirSurfaceSpec* spec) |
96 | { |
97 | delete spec; |
98 | |
99 | === modified file 'src/client/symbols.map' |
100 | --- src/client/symbols.map 2015-04-16 08:32:47 +0000 |
101 | +++ src/client/symbols.map 2015-04-17 13:13:57 +0000 |
102 | @@ -163,6 +163,7 @@ |
103 | mir_surface_event_get_attribute; |
104 | mir_surface_event_get_attribute_value; |
105 | mir_surface_set_swapinterval; |
106 | + mir_surface_spec_set_buffering_mode; |
107 | mir_surface_spec_set_min_width; |
108 | mir_surface_spec_set_min_height; |
109 | mir_surface_spec_set_max_width; |
110 | |
111 | === modified file 'src/protobuf/mir_protobuf.proto' |
112 | --- src/protobuf/mir_protobuf.proto 2015-04-14 10:23:11 +0000 |
113 | +++ src/protobuf/mir_protobuf.proto 2015-04-17 13:13:57 +0000 |
114 | @@ -31,6 +31,8 @@ |
115 | optional int32 min_height = 14; |
116 | optional int32 max_width = 15; |
117 | optional int32 max_height = 16; |
118 | + |
119 | + optional int32 buffering_mode = 17; |
120 | } |
121 | |
122 | // If and when we break our protocol backward-compatibility, this could be |
123 | @@ -53,6 +55,8 @@ |
124 | optional int32 min_height = 14; |
125 | optional int32 max_width = 15; |
126 | optional int32 max_height = 16; |
127 | + |
128 | + optional int32 buffering_mode = 17; |
129 | } |
130 | |
131 | |
132 | |
133 | === modified file 'src/server/frontend/session_mediator.cpp' |
134 | --- src/server/frontend/session_mediator.cpp 2015-04-16 20:59:36 +0000 |
135 | +++ src/server/frontend/session_mediator.cpp 2015-04-17 13:13:57 +0000 |
136 | @@ -239,6 +239,7 @@ |
137 | COPY_IF_SET(min_height); |
138 | COPY_IF_SET(max_width); |
139 | COPY_IF_SET(max_height); |
140 | + COPY_IF_SET(buffering_mode); |
141 | |
142 | #undef COPY_IF_SET |
143 | |
144 | |
145 | === modified file 'src/server/scene/surface_allocator.cpp' |
146 | --- src/server/scene/surface_allocator.cpp 2015-03-31 02:35:42 +0000 |
147 | +++ src/server/scene/surface_allocator.cpp 2015-04-17 13:13:57 +0000 |
148 | @@ -58,9 +58,17 @@ |
149 | mg::BufferProperties buffer_properties{params.size, |
150 | params.pixel_format, |
151 | params.buffer_usage}; |
152 | + int buffers = nbuffers; |
153 | + if (params.buffering_mode.is_set()) |
154 | + { |
155 | + if (params.buffering_mode.value() == mir_buffering_mode_double) |
156 | + buffers = 2; |
157 | + else if (params.buffering_mode.value() == mir_buffering_mode_triple) |
158 | + buffers = 3; |
159 | + } |
160 | + |
161 | auto buffer_stream = buffer_stream_factory->create_buffer_stream( |
162 | - nbuffers, |
163 | - buffer_properties); |
164 | + buffers, buffer_properties); |
165 | auto actual_size = geom::Rectangle{params.top_left, buffer_stream->stream_size()}; |
166 | |
167 | bool nonrectangular = has_alpha(params.pixel_format); |
168 | |
169 | === modified file 'src/server/scene/surface_creation_parameters.cpp' |
170 | --- src/server/scene/surface_creation_parameters.cpp 2015-01-23 03:50:26 +0000 |
171 | +++ src/server/scene/surface_creation_parameters.cpp 2015-04-17 13:13:57 +0000 |
172 | @@ -151,6 +151,7 @@ |
173 | lhs.state == rhs.state && |
174 | lhs.type == rhs.type && |
175 | lhs.preferred_orientation == rhs.preferred_orientation && |
176 | + lhs.buffering_mode == rhs.buffering_mode && |
177 | lhs.parent_id == rhs.parent_id; |
178 | } |
179 | |
180 | |
181 | === modified file 'tests/acceptance-tests/CMakeLists.txt' |
182 | --- tests/acceptance-tests/CMakeLists.txt 2015-04-09 06:20:31 +0000 |
183 | +++ tests/acceptance-tests/CMakeLists.txt 2015-04-17 13:13:57 +0000 |
184 | @@ -41,6 +41,7 @@ |
185 | test_shell_control_of_surface_configuration.cpp |
186 | test_render_override.cpp |
187 | test_surface_modifications.cpp |
188 | + test_client_surface_buffering_mode.cpp |
189 | ) |
190 | |
191 | if (MIR_TEST_PLATFORM STREQUAL "mesa") |
192 | |
193 | === added file 'tests/acceptance-tests/test_client_surface_buffering_mode.cpp' |
194 | --- tests/acceptance-tests/test_client_surface_buffering_mode.cpp 1970-01-01 00:00:00 +0000 |
195 | +++ tests/acceptance-tests/test_client_surface_buffering_mode.cpp 2015-04-17 13:13:57 +0000 |
196 | @@ -0,0 +1,133 @@ |
197 | +/* |
198 | + * Copyright © 2015 Canonical Ltd. |
199 | + * |
200 | + * This program is free software: you can redistribute it and/or modify it |
201 | + * under the terms of the GNU General Public License version 3, |
202 | + * as published by the Free Software Foundation. |
203 | + * |
204 | + * This program is distributed in the hope that it will be useful, |
205 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
206 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
207 | + * GNU General Public License for more details. |
208 | + * |
209 | + * You should have received a copy of the GNU General Public License |
210 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
211 | + * |
212 | + * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com> |
213 | + */ |
214 | + |
215 | +#include "mir_toolkit/mir_client_library.h" |
216 | +#include "mir_toolkit/debug/surface.h" |
217 | + |
218 | +#include "mir_test_framework/connected_client_headless_server.h" |
219 | +#include "mir_test_framework/stub_server_platform_factory.h" |
220 | + |
221 | +#include <unordered_set> |
222 | +#include <chrono> |
223 | + |
224 | +#include <gtest/gtest.h> |
225 | +#include <gmock/gmock.h> |
226 | + |
227 | +namespace mtf = mir_test_framework; |
228 | + |
229 | +using namespace std::literals::chrono_literals; |
230 | + |
231 | +namespace |
232 | +{ |
233 | + |
234 | +struct WithDefaultSurfaceBuffers : mtf::ConnectedClientHeadlessServer, |
235 | + ::testing::WithParamInterface<int> |
236 | +{ |
237 | + WithDefaultSurfaceBuffers() |
238 | + { |
239 | + add_to_environment("MIR_SERVER_NBUFFERS", std::to_string(GetParam()).c_str()); |
240 | + // In triple buffering mode the server initially allocates only two buffers, |
241 | + // and the third on demand. We use a non-zero vsync interval so that the client |
242 | + // can swap buffers faster than the server can process them, which forces the |
243 | + // server to allocate all surface buffers. |
244 | + mtf::set_next_vsync_interval(5ms); |
245 | + } |
246 | + |
247 | + template<typename T> using UPtr = std::unique_ptr<T,void(*)(T*)>; |
248 | + |
249 | + UPtr<MirSurface> create_surface_with_buffering_mode(MirBufferingMode mode) |
250 | + { |
251 | + auto const spec = UPtr<MirSurfaceSpec>{ |
252 | + mir_connection_create_spec_for_normal_surface( |
253 | + connection, 640, 480, mir_pixel_format_argb_8888), |
254 | + mir_surface_spec_release}; |
255 | + |
256 | + mir_surface_spec_set_buffering_mode(spec.get(), mode); |
257 | + |
258 | + return UPtr<MirSurface>{ |
259 | + mir_surface_create_sync(spec.get()), mir_surface_release_sync}; |
260 | + } |
261 | + |
262 | + UPtr<MirSurface> create_surface_without_buffering_mode() |
263 | + { |
264 | + auto const spec = UPtr<MirSurfaceSpec>{ |
265 | + mir_connection_create_spec_for_normal_surface( |
266 | + connection, 640, 480, mir_pixel_format_argb_8888), |
267 | + mir_surface_spec_release}; |
268 | + |
269 | + return UPtr<MirSurface>{ |
270 | + mir_surface_create_sync(spec.get()), mir_surface_release_sync}; |
271 | + } |
272 | + |
273 | + unsigned int number_of_buffers_for(MirSurface* surface) |
274 | + { |
275 | + std::unordered_set<uint32_t> buffers; |
276 | + |
277 | + for (int i = 0; i != 10; ++i) |
278 | + { |
279 | + mir_buffer_stream_swap_buffers_sync( |
280 | + mir_surface_get_buffer_stream(surface)); |
281 | + buffers.insert( |
282 | + mir_debug_surface_current_buffer_id(surface)); |
283 | + } |
284 | + |
285 | + return buffers.size(); |
286 | + } |
287 | +}; |
288 | + |
289 | +} |
290 | + |
291 | +TEST_P(WithDefaultSurfaceBuffers, allocates_two_buffers_when_client_requests_double_buffering) |
292 | +{ |
293 | + using namespace testing; |
294 | + |
295 | + auto const surface = create_surface_with_buffering_mode(mir_buffering_mode_double); |
296 | + |
297 | + EXPECT_THAT(number_of_buffers_for(surface.get()), Eq(2)); |
298 | +} |
299 | + |
300 | +TEST_P(WithDefaultSurfaceBuffers, allocates_three_buffers_when_client_requests_triple_buffering) |
301 | +{ |
302 | + using namespace testing; |
303 | + |
304 | + auto const surface = create_surface_with_buffering_mode(mir_buffering_mode_triple); |
305 | + |
306 | + EXPECT_THAT(number_of_buffers_for(surface.get()), Eq(3)); |
307 | +} |
308 | + |
309 | +TEST_P(WithDefaultSurfaceBuffers, allocates_default_buffers_when_client_requests_default_buffering) |
310 | +{ |
311 | + using namespace testing; |
312 | + |
313 | + auto const surface = create_surface_with_buffering_mode(mir_buffering_mode_default); |
314 | + |
315 | + EXPECT_THAT(number_of_buffers_for(surface.get()), Eq(GetParam())); |
316 | +} |
317 | + |
318 | +TEST_P(WithDefaultSurfaceBuffers, allocates_default_buffers_when_client_does_not_specify_buffering) |
319 | +{ |
320 | + using namespace testing; |
321 | + |
322 | + auto const surface = create_surface_without_buffering_mode(); |
323 | + |
324 | + EXPECT_THAT(number_of_buffers_for(surface.get()), Eq(GetParam())); |
325 | +} |
326 | + |
327 | +INSTANTIATE_TEST_CASE_P(MirServer, |
328 | + WithDefaultSurfaceBuffers, |
329 | + ::testing::Values(2,3)); |
330 | |
331 | === modified file 'tests/include/mir_test_doubles/null_display_sync_group.h' |
332 | --- tests/include/mir_test_doubles/null_display_sync_group.h 2015-02-20 19:44:17 +0000 |
333 | +++ tests/include/mir_test_doubles/null_display_sync_group.h 2015-04-17 13:13:57 +0000 |
334 | @@ -24,6 +24,7 @@ |
335 | #include "null_display_buffer.h" |
336 | #include "stub_display_buffer.h" |
337 | #include <thread> |
338 | +#include <chrono> |
339 | |
340 | namespace mir |
341 | { |
342 | @@ -36,12 +37,23 @@ |
343 | { |
344 | public: |
345 | StubDisplaySyncGroup(std::vector<geometry::Rectangle> const& output_rects) |
346 | - : output_rects{output_rects} |
347 | + : StubDisplaySyncGroup(output_rects, std::chrono::milliseconds{0}) |
348 | + { |
349 | + } |
350 | + |
351 | + StubDisplaySyncGroup(geometry::Size sz) |
352 | + : StubDisplaySyncGroup({{{0,0}, sz}}, std::chrono::milliseconds{0}) |
353 | + { |
354 | + } |
355 | + |
356 | + StubDisplaySyncGroup(std::vector<geometry::Rectangle> const& output_rects, |
357 | + std::chrono::milliseconds vsync_interval) |
358 | + : output_rects{output_rects}, |
359 | + vsync_interval{vsync_interval} |
360 | { |
361 | for (auto const& output_rect : output_rects) |
362 | display_buffers.emplace_back(output_rect); |
363 | } |
364 | - StubDisplaySyncGroup(geometry::Size sz) : StubDisplaySyncGroup({{{0,0}, sz}}) {} |
365 | |
366 | void for_each_display_buffer(std::function<void(graphics::DisplayBuffer&)> const& f) override |
367 | { |
368 | @@ -52,12 +64,16 @@ |
369 | void post() override |
370 | { |
371 | /* yield() is needed to ensure reasonable runtime under valgrind for some tests */ |
372 | - std::this_thread::yield(); |
373 | + if (vsync_interval == vsync_interval.zero()) |
374 | + std::this_thread::yield(); |
375 | + else |
376 | + std::this_thread::sleep_for(vsync_interval); |
377 | } |
378 | |
379 | private: |
380 | std::vector<geometry::Rectangle> const output_rects; |
381 | std::vector<StubDisplayBuffer> display_buffers; |
382 | + std::chrono::milliseconds vsync_interval{0}; |
383 | }; |
384 | |
385 | struct NullDisplaySyncGroup : graphics::DisplaySyncGroup |
386 | |
387 | === modified file 'tests/include/mir_test_doubles/stub_display.h' |
388 | --- tests/include/mir_test_doubles/stub_display.h 2015-03-31 02:35:42 +0000 |
389 | +++ tests/include/mir_test_doubles/stub_display.h 2015-04-17 13:13:57 +0000 |
390 | @@ -27,6 +27,7 @@ |
391 | #include "mir/geometry/rectangle.h" |
392 | |
393 | #include <vector> |
394 | +#include <chrono> |
395 | |
396 | namespace mir |
397 | { |
398 | @@ -39,15 +40,21 @@ |
399 | { |
400 | public: |
401 | StubDisplay(std::vector<geometry::Rectangle> const& output_rects) : |
402 | + StubDisplay(output_rects, std::chrono::milliseconds::zero()) |
403 | + { |
404 | + } |
405 | + |
406 | + StubDisplay(unsigned int nbuffers) : |
407 | + StubDisplay(generate_stub_rects(nbuffers)) |
408 | + { |
409 | + } |
410 | + |
411 | + StubDisplay(std::vector<geometry::Rectangle> const& output_rects, |
412 | + std::chrono::milliseconds vsync_interval) : |
413 | output_rects(output_rects) |
414 | { |
415 | for (auto const& rect : output_rects) |
416 | - groups.emplace_back(new StubDisplaySyncGroup({rect})); |
417 | - } |
418 | - |
419 | - StubDisplay(unsigned int nbuffers) : |
420 | - StubDisplay(generate_stub_rects(nbuffers)) |
421 | - { |
422 | + groups.emplace_back(new StubDisplaySyncGroup({rect}, vsync_interval)); |
423 | } |
424 | |
425 | void for_each_display_sync_group(std::function<void(graphics::DisplaySyncGroup&)> const& f) override |
426 | |
427 | === modified file 'tests/include/mir_test_framework/stub_server_platform_factory.h' |
428 | --- tests/include/mir_test_framework/stub_server_platform_factory.h 2015-04-09 06:20:31 +0000 |
429 | +++ tests/include/mir_test_framework/stub_server_platform_factory.h 2015-04-17 13:13:57 +0000 |
430 | @@ -26,6 +26,7 @@ |
431 | #include <vector> |
432 | #include <memory> |
433 | #include <string> |
434 | +#include <chrono> |
435 | |
436 | namespace geom = mir::geometry; |
437 | |
438 | @@ -53,6 +54,8 @@ |
439 | |
440 | void set_next_preset_display(std::shared_ptr<mir::graphics::Display> const& display); |
441 | |
442 | +void set_next_vsync_interval(std::chrono::milliseconds interval); |
443 | + |
444 | mir::UniqueModulePtr<FakeInputDevice> add_fake_input_device(mir::input::InputDeviceInfo const& info); |
445 | } |
446 | #endif /* MIR_TEST_FRAMEWORK_STUB_SERVER_PLATFORM_FACTORY_ */ |
447 | |
448 | === modified file 'tests/mir_test_framework/stub_server_platform_factory.cpp' |
449 | --- tests/mir_test_framework/stub_server_platform_factory.cpp 2015-04-09 06:20:31 +0000 |
450 | +++ tests/mir_test_framework/stub_server_platform_factory.cpp 2015-04-17 13:13:57 +0000 |
451 | @@ -87,3 +87,16 @@ |
452 | |
453 | return add_device(info); |
454 | } |
455 | + |
456 | +void mtf::set_next_vsync_interval( |
457 | + std::chrono::milliseconds interval) |
458 | +{ |
459 | + ensure_platform_library(); |
460 | + |
461 | + using func_sig = void(*)(std::chrono::milliseconds); |
462 | + |
463 | + auto const set_next_vsync_interval = |
464 | + platform_graphics_lib->load_function<func_sig>("set_next_vsync_interval"); |
465 | + |
466 | + return set_next_vsync_interval(interval); |
467 | +} |
468 | |
469 | === modified file 'tests/mir_test_framework/stubbed_graphics_platform.cpp' |
470 | --- tests/mir_test_framework/stubbed_graphics_platform.cpp 2015-03-31 02:35:42 +0000 |
471 | +++ tests/mir_test_framework/stubbed_graphics_platform.cpp 2015-04-17 13:13:57 +0000 |
472 | @@ -228,6 +228,7 @@ |
473 | namespace |
474 | { |
475 | std::shared_ptr<mg::Display> display_preset; |
476 | +std::chrono::milliseconds vsync_interval; |
477 | } |
478 | |
479 | std::shared_ptr<mg::Display> mtf::StubGraphicPlatform::create_display( |
480 | @@ -238,7 +239,9 @@ |
481 | if (display_preset) |
482 | return std::move(display_preset); |
483 | |
484 | - return std::make_shared<mtd::StubDisplay>(display_rects); |
485 | + auto const tmp_vsync = vsync_interval; |
486 | + vsync_interval = std::chrono::milliseconds::zero(); |
487 | + return std::make_shared<mtd::StubDisplay>(display_rects, tmp_vsync); |
488 | } |
489 | |
490 | namespace |
491 | @@ -334,3 +337,8 @@ |
492 | { |
493 | display_preset = display; |
494 | } |
495 | + |
496 | +extern "C" void set_next_vsync_interval(std::chrono::milliseconds interval) |
497 | +{ |
498 | + vsync_interval = interval; |
499 | +} |
89+bool mir_surface_ spec_set_ buffering_ mode(MirSurface Spec* spec, MirBufferingMode mode) _mode = mode;
90+{
91+ spec->buffering
92+ return true;
93+}
Possibly worth validating the buffering mode at this point and returning false if it is nonsense?