Merge lp:~afrantzis/mir/drop-stale-frames into lp:mir
- drop-stale-frames
- Merge into development-branch
Status: | Merged |
---|---|
Approved by: | Alan Griffiths |
Approved revision: | no longer in the source branch. |
Merged at revision: | 1796 |
Proposed branch: | lp:~afrantzis/mir/drop-stale-frames |
Merge into: | lp:mir |
Diff against target: |
531 lines (+315/-18) 15 files modified
include/server/mir/compositor/buffer_stream.h (+1/-0) include/test/mir_test_doubles/mock_buffer_bundle.h (+1/-0) include/test/mir_test_doubles/mock_buffer_stream.h (+1/-0) include/test/mir_test_doubles/stub_buffer_stream.h (+2/-0) server-ABI-sha1sums (+1/-1) src/server/compositor/buffer_bundle.h (+1/-0) src/server/compositor/buffer_queue.cpp (+30/-1) src/server/compositor/buffer_queue.h (+2/-0) src/server/compositor/buffer_stream_surfaces.cpp (+5/-0) src/server/compositor/buffer_stream_surfaces.h (+1/-0) src/server/scene/basic_surface.cpp (+2/-0) tests/acceptance-tests/CMakeLists.txt (+1/-0) tests/acceptance-tests/test_stale_frames.cpp (+206/-0) tests/integration-tests/test_swapinterval.cpp (+2/-16) tests/unit-tests/compositor/test_buffer_queue.cpp (+59/-0) |
To merge this branch: | bzr merge lp:~afrantzis/mir/drop-stale-frames |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Kevin DuBois (community) | Approve | ||
PS Jenkins bot (community) | continuous-integration | Approve | |
Robert Carr (community) | Approve | ||
Alan Griffiths | Approve | ||
Review via email: mp+227961@code.launchpad.net |
Commit message
server: Drop stale frames when a surface becomes exposed
When a surface changes from occluded to exposed, at best there is no
point in showing older, stale frames in quick succession, at worst the
stale frames result in visual glitches. We only care about the latest
surface buffer.
Description of the change
server: Drop stale frames when a surface becomes exposed
When a surface changes from occluded to exposed, at best there is no
point in showing older, stale frames in quick succession, at worst the
stale frames result in visual glitches. We only care about the latest
surface buffer.
This fixes one aspect of https:/
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1791
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Preview Diff
1 | === modified file 'include/server/mir/compositor/buffer_stream.h' | |||
2 | --- include/server/mir/compositor/buffer_stream.h 2014-05-22 10:00:05 +0000 | |||
3 | +++ include/server/mir/compositor/buffer_stream.h 2014-07-25 10:04:16 +0000 | |||
4 | @@ -53,6 +53,7 @@ | |||
5 | 53 | virtual void allow_framedropping(bool) = 0; | 53 | virtual void allow_framedropping(bool) = 0; |
6 | 54 | virtual void force_requests_to_complete() = 0; | 54 | virtual void force_requests_to_complete() = 0; |
7 | 55 | virtual int buffers_ready_for_compositor() const = 0; | 55 | virtual int buffers_ready_for_compositor() const = 0; |
8 | 56 | virtual void drop_old_buffers() = 0; | ||
9 | 56 | }; | 57 | }; |
10 | 57 | 58 | ||
11 | 58 | } | 59 | } |
12 | 59 | 60 | ||
13 | === modified file 'include/test/mir_test_doubles/mock_buffer_bundle.h' | |||
14 | --- include/test/mir_test_doubles/mock_buffer_bundle.h 2014-05-21 05:30:50 +0000 | |||
15 | +++ include/test/mir_test_doubles/mock_buffer_bundle.h 2014-07-25 10:04:16 +0000 | |||
16 | @@ -48,6 +48,7 @@ | |||
17 | 48 | MOCK_METHOD0(force_client_abort, void()); | 48 | MOCK_METHOD0(force_client_abort, void()); |
18 | 49 | MOCK_METHOD0(force_requests_to_complete, void()); | 49 | MOCK_METHOD0(force_requests_to_complete, void()); |
19 | 50 | MOCK_METHOD1(resize, void(const geometry::Size &)); | 50 | MOCK_METHOD1(resize, void(const geometry::Size &)); |
20 | 51 | MOCK_METHOD0(drop_old_buffers, void()); | ||
21 | 51 | int buffers_ready_for_compositor() const override { return 1; } | 52 | int buffers_ready_for_compositor() const override { return 1; } |
22 | 52 | int buffers_free_for_client() const override { return 1; } | 53 | int buffers_free_for_client() const override { return 1; } |
23 | 53 | }; | 54 | }; |
24 | 54 | 55 | ||
25 | === modified file 'include/test/mir_test_doubles/mock_buffer_stream.h' | |||
26 | --- include/test/mir_test_doubles/mock_buffer_stream.h 2014-05-22 10:00:05 +0000 | |||
27 | +++ include/test/mir_test_doubles/mock_buffer_stream.h 2014-07-25 10:04:16 +0000 | |||
28 | @@ -57,6 +57,7 @@ | |||
29 | 57 | MOCK_METHOD1(allow_framedropping, void(bool)); | 57 | MOCK_METHOD1(allow_framedropping, void(bool)); |
30 | 58 | MOCK_METHOD0(force_requests_to_complete, void()); | 58 | MOCK_METHOD0(force_requests_to_complete, void()); |
31 | 59 | MOCK_CONST_METHOD0(buffers_ready_for_compositor, int()); | 59 | MOCK_CONST_METHOD0(buffers_ready_for_compositor, int()); |
32 | 60 | MOCK_METHOD0(drop_old_buffers, void()); | ||
33 | 60 | }; | 61 | }; |
34 | 61 | } | 62 | } |
35 | 62 | } | 63 | } |
36 | 63 | 64 | ||
37 | === modified file 'include/test/mir_test_doubles/stub_buffer_stream.h' | |||
38 | --- include/test/mir_test_doubles/stub_buffer_stream.h 2014-05-22 10:00:05 +0000 | |||
39 | +++ include/test/mir_test_doubles/stub_buffer_stream.h 2014-07-25 10:04:16 +0000 | |||
40 | @@ -81,6 +81,8 @@ | |||
41 | 81 | 81 | ||
42 | 82 | int buffers_ready_for_compositor() const override { return 1; } | 82 | int buffers_ready_for_compositor() const override { return 1; } |
43 | 83 | 83 | ||
44 | 84 | void drop_old_buffers() override {} | ||
45 | 85 | |||
46 | 84 | StubBuffer stub_client_buffer; | 86 | StubBuffer stub_client_buffer; |
47 | 85 | std::shared_ptr<graphics::Buffer> stub_compositor_buffer; | 87 | std::shared_ptr<graphics::Buffer> stub_compositor_buffer; |
48 | 86 | }; | 88 | }; |
49 | 87 | 89 | ||
50 | === modified file 'server-ABI-sha1sums' | |||
51 | --- server-ABI-sha1sums 2014-07-24 11:44:53 +0000 | |||
52 | +++ server-ABI-sha1sums 2014-07-25 10:04:16 +0000 | |||
53 | @@ -9,7 +9,7 @@ | |||
54 | 9 | ba79552edce545fafc9a4f401411c44d0cb3b2cf include/server/mir/graphics/gl_extensions_base.h | 9 | ba79552edce545fafc9a4f401411c44d0cb3b2cf include/server/mir/graphics/gl_extensions_base.h |
55 | 10 | 7ef3e99901168cda296d74d05a979f47bf9c3ff1 include/server/mir/server_action_queue.h | 10 | 7ef3e99901168cda296d74d05a979f47bf9c3ff1 include/server/mir/server_action_queue.h |
56 | 11 | a3e8658107c0c13d41eaf2ca6a1be71d1dc59df6 include/server/mir/compositor/compositor_report.h | 11 | a3e8658107c0c13d41eaf2ca6a1be71d1dc59df6 include/server/mir/compositor/compositor_report.h |
58 | 12 | e439cc4a7fb8e975bed0771756e7949aad968c14 include/server/mir/compositor/buffer_stream.h | 12 | a4c8f0b0c30784ea6930a8ee6651f1d6efa47231 include/server/mir/compositor/buffer_stream.h |
59 | 13 | e787879afa46d9c8257ff1f4ae8c7900d4b5f1a4 include/server/mir/compositor/frame_dropping_policy.h | 13 | e787879afa46d9c8257ff1f4ae8c7900d4b5f1a4 include/server/mir/compositor/frame_dropping_policy.h |
60 | 14 | e0860c43bf5196a792ffd7216826925e16275d07 include/server/mir/compositor/renderer_factory.h | 14 | e0860c43bf5196a792ffd7216826925e16275d07 include/server/mir/compositor/renderer_factory.h |
61 | 15 | a9f284ba4b05d58fd3eeb628d1f56fe4ac188526 include/server/mir/compositor/compositor_id.h | 15 | a9f284ba4b05d58fd3eeb628d1f56fe4ac188526 include/server/mir/compositor/compositor_id.h |
62 | 16 | 16 | ||
63 | === modified file 'src/server/compositor/buffer_bundle.h' | |||
64 | --- src/server/compositor/buffer_bundle.h 2014-05-21 08:38:47 +0000 | |||
65 | +++ src/server/compositor/buffer_bundle.h 2014-07-25 10:04:16 +0000 | |||
66 | @@ -67,6 +67,7 @@ | |||
67 | 67 | * nbuffers-1 as it might be less. | 67 | * nbuffers-1 as it might be less. |
68 | 68 | */ | 68 | */ |
69 | 69 | virtual int buffers_free_for_client() const = 0; | 69 | virtual int buffers_free_for_client() const = 0; |
70 | 70 | virtual void drop_old_buffers() = 0; | ||
71 | 70 | 71 | ||
72 | 71 | protected: | 72 | protected: |
73 | 72 | BufferBundle() = default; | 73 | BufferBundle() = default; |
74 | 73 | 74 | ||
75 | === modified file 'src/server/compositor/buffer_queue.cpp' | |||
76 | --- src/server/compositor/buffer_queue.cpp 2014-07-21 03:35:31 +0000 | |||
77 | +++ src/server/compositor/buffer_queue.cpp 2014-07-25 10:04:16 +0000 | |||
78 | @@ -99,6 +99,7 @@ | |||
79 | 99 | : nbuffers{nbuffers}, | 99 | : nbuffers{nbuffers}, |
80 | 100 | frame_dropping_enabled{false}, | 100 | frame_dropping_enabled{false}, |
81 | 101 | the_properties{props}, | 101 | the_properties{props}, |
82 | 102 | force_new_compositor_buffer{false}, | ||
83 | 102 | gralloc{gralloc} | 103 | gralloc{gralloc} |
84 | 103 | { | 104 | { |
85 | 104 | if (nbuffers < 1) | 105 | if (nbuffers < 1) |
86 | @@ -240,7 +241,16 @@ | |||
87 | 240 | use_current_buffer = true; | 241 | use_current_buffer = true; |
88 | 241 | current_buffer_users.push_back(user_id); | 242 | current_buffer_users.push_back(user_id); |
89 | 242 | } | 243 | } |
91 | 243 | use_current_buffer |= ready_to_composite_queue.empty(); | 244 | |
92 | 245 | if (ready_to_composite_queue.empty()) | ||
93 | 246 | { | ||
94 | 247 | use_current_buffer = true; | ||
95 | 248 | } | ||
96 | 249 | else if (force_new_compositor_buffer) | ||
97 | 250 | { | ||
98 | 251 | use_current_buffer = false; | ||
99 | 252 | force_new_compositor_buffer = false; | ||
100 | 253 | } | ||
101 | 244 | 254 | ||
102 | 245 | mg::Buffer* buffer_to_release = nullptr; | 255 | mg::Buffer* buffer_to_release = nullptr; |
103 | 246 | if (!use_current_buffer) | 256 | if (!use_current_buffer) |
104 | @@ -473,3 +483,22 @@ | |||
105 | 473 | } | 483 | } |
106 | 474 | give_buffer_to_client(buffer_to_give, std::move(lock)); | 484 | give_buffer_to_client(buffer_to_give, std::move(lock)); |
107 | 475 | } | 485 | } |
108 | 486 | |||
109 | 487 | void mc::BufferQueue::drop_old_buffers() | ||
110 | 488 | { | ||
111 | 489 | std::vector<mg::Buffer*> to_release; | ||
112 | 490 | |||
113 | 491 | { | ||
114 | 492 | std::lock_guard<decltype(guard)> lock{guard}; | ||
115 | 493 | force_new_compositor_buffer = true; | ||
116 | 494 | |||
117 | 495 | while (ready_to_composite_queue.size() > 1) | ||
118 | 496 | to_release.push_back(pop(ready_to_composite_queue)); | ||
119 | 497 | } | ||
120 | 498 | |||
121 | 499 | for (auto buffer : to_release) | ||
122 | 500 | { | ||
123 | 501 | std::unique_lock<decltype(guard)> lock{guard}; | ||
124 | 502 | release(buffer, std::move(lock)); | ||
125 | 503 | } | ||
126 | 504 | } | ||
127 | 476 | 505 | ||
128 | === modified file 'src/server/compositor/buffer_queue.h' | |||
129 | --- src/server/compositor/buffer_queue.h 2014-07-17 10:28:51 +0000 | |||
130 | +++ src/server/compositor/buffer_queue.h 2014-07-25 10:04:16 +0000 | |||
131 | @@ -62,6 +62,7 @@ | |||
132 | 62 | int buffers_free_for_client() const override; | 62 | int buffers_free_for_client() const override; |
133 | 63 | bool framedropping_allowed() const; | 63 | bool framedropping_allowed() const; |
134 | 64 | bool is_a_current_buffer_user(void const* user_id) const; | 64 | bool is_a_current_buffer_user(void const* user_id) const; |
135 | 65 | void drop_old_buffers() override; | ||
136 | 65 | 66 | ||
137 | 66 | private: | 67 | private: |
138 | 67 | void give_buffer_to_client(graphics::Buffer* buffer, | 68 | void give_buffer_to_client(graphics::Buffer* buffer, |
139 | @@ -87,6 +88,7 @@ | |||
140 | 87 | int nbuffers; | 88 | int nbuffers; |
141 | 88 | bool frame_dropping_enabled; | 89 | bool frame_dropping_enabled; |
142 | 89 | graphics::BufferProperties the_properties; | 90 | graphics::BufferProperties the_properties; |
143 | 91 | bool force_new_compositor_buffer; | ||
144 | 90 | 92 | ||
145 | 91 | std::condition_variable snapshot_released; | 93 | std::condition_variable snapshot_released; |
146 | 92 | std::shared_ptr<graphics::GraphicBufferAllocator> gralloc; | 94 | std::shared_ptr<graphics::GraphicBufferAllocator> gralloc; |
147 | 93 | 95 | ||
148 | === modified file 'src/server/compositor/buffer_stream_surfaces.cpp' | |||
149 | --- src/server/compositor/buffer_stream_surfaces.cpp 2014-05-22 10:00:05 +0000 | |||
150 | +++ src/server/compositor/buffer_stream_surfaces.cpp 2014-07-25 10:04:16 +0000 | |||
151 | @@ -89,3 +89,8 @@ | |||
152 | 89 | { | 89 | { |
153 | 90 | return buffer_bundle->buffers_ready_for_compositor(); | 90 | return buffer_bundle->buffers_ready_for_compositor(); |
154 | 91 | } | 91 | } |
155 | 92 | |||
156 | 93 | void mc::BufferStreamSurfaces::drop_old_buffers() | ||
157 | 94 | { | ||
158 | 95 | buffer_bundle->drop_old_buffers(); | ||
159 | 96 | } | ||
160 | 92 | 97 | ||
161 | === modified file 'src/server/compositor/buffer_stream_surfaces.h' | |||
162 | --- src/server/compositor/buffer_stream_surfaces.h 2014-05-22 10:00:05 +0000 | |||
163 | +++ src/server/compositor/buffer_stream_surfaces.h 2014-07-25 10:04:16 +0000 | |||
164 | @@ -52,6 +52,7 @@ | |||
165 | 52 | void allow_framedropping(bool) override; | 52 | void allow_framedropping(bool) override; |
166 | 53 | void force_requests_to_complete() override; | 53 | void force_requests_to_complete() override; |
167 | 54 | int buffers_ready_for_compositor() const override; | 54 | int buffers_ready_for_compositor() const override; |
168 | 55 | void drop_old_buffers() override; | ||
169 | 55 | 56 | ||
170 | 56 | protected: | 57 | protected: |
171 | 57 | BufferStreamSurfaces(const BufferStreamSurfaces&) = delete; | 58 | BufferStreamSurfaces(const BufferStreamSurfaces&) = delete; |
172 | 58 | 59 | ||
173 | === modified file 'src/server/scene/basic_surface.cpp' | |||
174 | --- src/server/scene/basic_surface.cpp 2014-07-21 03:35:31 +0000 | |||
175 | +++ src/server/scene/basic_surface.cpp 2014-07-25 10:04:16 +0000 | |||
176 | @@ -583,6 +583,8 @@ | |||
177 | 583 | { | 583 | { |
178 | 584 | attrib_values[mir_surface_attrib_visibility] = new_visibility; | 584 | attrib_values[mir_surface_attrib_visibility] = new_visibility; |
179 | 585 | lg.unlock(); | 585 | lg.unlock(); |
180 | 586 | if (new_visibility == mir_surface_visibility_exposed) | ||
181 | 587 | surface_buffer_stream->drop_old_buffers(); | ||
182 | 586 | observers.attrib_changed(mir_surface_attrib_visibility, attrib_values[mir_surface_attrib_visibility]); | 588 | observers.attrib_changed(mir_surface_attrib_visibility, attrib_values[mir_surface_attrib_visibility]); |
183 | 587 | } | 589 | } |
184 | 588 | 590 | ||
185 | 589 | 591 | ||
186 | === modified file 'tests/acceptance-tests/CMakeLists.txt' | |||
187 | --- tests/acceptance-tests/CMakeLists.txt 2014-07-22 03:26:35 +0000 | |||
188 | +++ tests/acceptance-tests/CMakeLists.txt 2014-07-25 10:04:16 +0000 | |||
189 | @@ -40,6 +40,7 @@ | |||
190 | 40 | test_client_surface_visibility.cpp | 40 | test_client_surface_visibility.cpp |
191 | 41 | test_client_with_custom_display_config_deadlock.cpp | 41 | test_client_with_custom_display_config_deadlock.cpp |
192 | 42 | test_macros.cpp | 42 | test_macros.cpp |
193 | 43 | test_stale_frames.cpp | ||
194 | 43 | ${GENERATED_PROTOBUF_SRCS} | 44 | ${GENERATED_PROTOBUF_SRCS} |
195 | 44 | ${GENERATED_PROTOBUF_HDRS} | 45 | ${GENERATED_PROTOBUF_HDRS} |
196 | 45 | ) | 46 | ) |
197 | 46 | 47 | ||
198 | === added file 'tests/acceptance-tests/test_stale_frames.cpp' | |||
199 | --- tests/acceptance-tests/test_stale_frames.cpp 1970-01-01 00:00:00 +0000 | |||
200 | +++ tests/acceptance-tests/test_stale_frames.cpp 2014-07-25 10:04:16 +0000 | |||
201 | @@ -0,0 +1,206 @@ | |||
202 | 1 | /* | ||
203 | 2 | * Copyright © 2014 Canonical Ltd. | ||
204 | 3 | * | ||
205 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
206 | 5 | * under the terms of the GNU General Public License version 3, | ||
207 | 6 | * as published by the Free Software Foundation. | ||
208 | 7 | * | ||
209 | 8 | * This program is distributed in the hope that it will be useful, | ||
210 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
211 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
212 | 11 | * GNU General Public License for more details. | ||
213 | 12 | * | ||
214 | 13 | * You should have received a copy of the GNU General Public License | ||
215 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
216 | 15 | * | ||
217 | 16 | * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com> | ||
218 | 17 | */ | ||
219 | 18 | |||
220 | 19 | #include "mir_toolkit/mir_client_library.h" | ||
221 | 20 | #include "mir_toolkit/mir_client_library_debug.h" | ||
222 | 21 | |||
223 | 22 | #include "mir/compositor/compositor.h" | ||
224 | 23 | #include "mir/compositor/renderer_factory.h" | ||
225 | 24 | #include "mir/graphics/renderable.h" | ||
226 | 25 | #include "mir/graphics/buffer.h" | ||
227 | 26 | #include "mir/graphics/buffer_id.h" | ||
228 | 27 | |||
229 | 28 | #include "mir_test_framework/using_stub_client_platform.h" | ||
230 | 29 | #include "mir_test_framework/stubbed_server_configuration.h" | ||
231 | 30 | #include "mir_test_framework/basic_client_server_fixture.h" | ||
232 | 31 | #include "mir_test_doubles/stub_renderer.h" | ||
233 | 32 | |||
234 | 33 | #include <gtest/gtest.h> | ||
235 | 34 | #include <gmock/gmock.h> | ||
236 | 35 | |||
237 | 36 | #include <mutex> | ||
238 | 37 | #include <condition_variable> | ||
239 | 38 | |||
240 | 39 | namespace mtf = mir_test_framework; | ||
241 | 40 | namespace mtd = mir::test::doubles; | ||
242 | 41 | namespace mc = mir::compositor; | ||
243 | 42 | namespace mg = mir::graphics; | ||
244 | 43 | namespace geom = mir::geometry; | ||
245 | 44 | |||
246 | 45 | namespace | ||
247 | 46 | { | ||
248 | 47 | |||
249 | 48 | struct StubRenderer : mtd::StubRenderer | ||
250 | 49 | { | ||
251 | 50 | void render(mg::RenderableList const& renderables) const override | ||
252 | 51 | { | ||
253 | 52 | std::lock_guard<std::mutex> lock{mutex}; | ||
254 | 53 | for (auto const& r : renderables) | ||
255 | 54 | rendered_buffers_.push_back(r->buffer()->id()); | ||
256 | 55 | |||
257 | 56 | if (renderables.size() > 0) | ||
258 | 57 | new_rendered_buffer_cv.notify_all(); | ||
259 | 58 | } | ||
260 | 59 | |||
261 | 60 | std::vector<mg::BufferID> rendered_buffers() | ||
262 | 61 | { | ||
263 | 62 | std::lock_guard<std::mutex> lock{mutex}; | ||
264 | 63 | return rendered_buffers_; | ||
265 | 64 | } | ||
266 | 65 | |||
267 | 66 | std::vector<mg::BufferID> wait_for_new_rendered_buffers() | ||
268 | 67 | { | ||
269 | 68 | std::unique_lock<std::mutex> lock{mutex}; | ||
270 | 69 | |||
271 | 70 | new_rendered_buffer_cv.wait_for( | ||
272 | 71 | lock, std::chrono::seconds{2}, | ||
273 | 72 | [this] { return rendered_buffers_.size() != 0; }); | ||
274 | 73 | |||
275 | 74 | auto const rendered = std::move(rendered_buffers_); | ||
276 | 75 | return rendered; | ||
277 | 76 | } | ||
278 | 77 | |||
279 | 78 | mutable std::mutex mutex; | ||
280 | 79 | mutable std::condition_variable new_rendered_buffer_cv; | ||
281 | 80 | mutable std::vector<mg::BufferID> rendered_buffers_; | ||
282 | 81 | }; | ||
283 | 82 | |||
284 | 83 | class StubRendererFactory : public mc::RendererFactory | ||
285 | 84 | { | ||
286 | 85 | public: | ||
287 | 86 | std::unique_ptr<mc::Renderer> create_renderer_for( | ||
288 | 87 | geom::Rectangle const&, mc::DestinationAlpha) override | ||
289 | 88 | { | ||
290 | 89 | std::lock_guard<std::mutex> lock{mutex}; | ||
291 | 90 | renderer_ = new StubRenderer(); | ||
292 | 91 | renderer_created_cv.notify_all(); | ||
293 | 92 | return std::unique_ptr<mc::Renderer>{renderer_}; | ||
294 | 93 | } | ||
295 | 94 | |||
296 | 95 | StubRenderer* renderer() | ||
297 | 96 | { | ||
298 | 97 | std::unique_lock<std::mutex> lock{mutex}; | ||
299 | 98 | |||
300 | 99 | renderer_created_cv.wait_for( | ||
301 | 100 | lock, std::chrono::seconds{2}, | ||
302 | 101 | [this] { return renderer_ != nullptr; }); | ||
303 | 102 | |||
304 | 103 | return renderer_; | ||
305 | 104 | } | ||
306 | 105 | |||
307 | 106 | void clear_renderer() | ||
308 | 107 | { | ||
309 | 108 | std::lock_guard<std::mutex> lock{mutex}; | ||
310 | 109 | renderer_ = nullptr; | ||
311 | 110 | } | ||
312 | 111 | |||
313 | 112 | std::mutex mutex; | ||
314 | 113 | std::condition_variable renderer_created_cv; | ||
315 | 114 | StubRenderer* renderer_ = nullptr; | ||
316 | 115 | }; | ||
317 | 116 | |||
318 | 117 | struct StubServerConfig : mtf::StubbedServerConfiguration | ||
319 | 118 | { | ||
320 | 119 | std::shared_ptr<StubRendererFactory> the_stub_renderer_factory() | ||
321 | 120 | { | ||
322 | 121 | return stub_renderer_factory( | ||
323 | 122 | [] { return std::make_shared<StubRendererFactory>(); }); | ||
324 | 123 | } | ||
325 | 124 | |||
326 | 125 | std::shared_ptr<mc::RendererFactory> the_renderer_factory() override | ||
327 | 126 | { | ||
328 | 127 | return the_stub_renderer_factory(); | ||
329 | 128 | } | ||
330 | 129 | |||
331 | 130 | mir::CachedPtr<StubRendererFactory> stub_renderer_factory; | ||
332 | 131 | }; | ||
333 | 132 | |||
334 | 133 | using BasicFixture = mtf::BasicClientServerFixture<StubServerConfig>; | ||
335 | 134 | |||
336 | 135 | struct StaleFrames : BasicFixture | ||
337 | 136 | { | ||
338 | 137 | void SetUp() | ||
339 | 138 | { | ||
340 | 139 | BasicFixture::SetUp(); | ||
341 | 140 | |||
342 | 141 | client_create_surface(); | ||
343 | 142 | } | ||
344 | 143 | |||
345 | 144 | void TearDown() | ||
346 | 145 | { | ||
347 | 146 | mir_surface_release_sync(surface); | ||
348 | 147 | |||
349 | 148 | BasicFixture::TearDown(); | ||
350 | 149 | } | ||
351 | 150 | |||
352 | 151 | void client_create_surface() | ||
353 | 152 | { | ||
354 | 153 | MirSurfaceParameters const request_params = | ||
355 | 154 | { | ||
356 | 155 | __PRETTY_FUNCTION__, | ||
357 | 156 | 640, 480, | ||
358 | 157 | mir_pixel_format_abgr_8888, | ||
359 | 158 | mir_buffer_usage_hardware, | ||
360 | 159 | mir_display_output_id_invalid | ||
361 | 160 | }; | ||
362 | 161 | |||
363 | 162 | surface = mir_connection_create_surface_sync(connection, &request_params); | ||
364 | 163 | ASSERT_TRUE(mir_surface_is_valid(surface)); | ||
365 | 164 | } | ||
366 | 165 | |||
367 | 166 | std::vector<mg::BufferID> wait_for_new_rendered_buffers() | ||
368 | 167 | { | ||
369 | 168 | return server_configuration.the_stub_renderer_factory()->renderer()->wait_for_new_rendered_buffers(); | ||
370 | 169 | } | ||
371 | 170 | |||
372 | 171 | void stop_compositor() | ||
373 | 172 | { | ||
374 | 173 | server_configuration.the_compositor()->stop(); | ||
375 | 174 | server_configuration.the_stub_renderer_factory()->clear_renderer(); | ||
376 | 175 | } | ||
377 | 176 | |||
378 | 177 | void start_compositor() | ||
379 | 178 | { | ||
380 | 179 | server_configuration.the_compositor()->start(); | ||
381 | 180 | } | ||
382 | 181 | |||
383 | 182 | MirSurface* surface; | ||
384 | 183 | mtf::UsingStubClientPlatform using_stub_client_platform; | ||
385 | 184 | }; | ||
386 | 185 | |||
387 | 186 | } | ||
388 | 187 | |||
389 | 188 | TEST_F(StaleFrames, are_dropped_when_restarting_compositor) | ||
390 | 189 | { | ||
391 | 190 | using namespace testing; | ||
392 | 191 | |||
393 | 192 | stop_compositor(); | ||
394 | 193 | |||
395 | 194 | auto const stale_buffer_id1 = mg::BufferID{mir_debug_surface_current_buffer_id(surface)}; | ||
396 | 195 | mir_surface_swap_buffers_sync(surface); | ||
397 | 196 | |||
398 | 197 | auto const stale_buffer_id2 = mg::BufferID{mir_debug_surface_current_buffer_id(surface)}; | ||
399 | 198 | mir_surface_swap_buffers_sync(surface); | ||
400 | 199 | |||
401 | 200 | mir_surface_swap_buffers_sync(surface); | ||
402 | 201 | |||
403 | 202 | start_compositor(); | ||
404 | 203 | |||
405 | 204 | auto const new_buffers = wait_for_new_rendered_buffers(); | ||
406 | 205 | EXPECT_THAT(new_buffers, Not(AnyOf(Contains(stale_buffer_id1), Contains(stale_buffer_id2)))); | ||
407 | 206 | } | ||
408 | 0 | 207 | ||
409 | === modified file 'tests/integration-tests/test_swapinterval.cpp' | |||
410 | --- tests/integration-tests/test_swapinterval.cpp 2014-05-22 10:00:05 +0000 | |||
411 | +++ tests/integration-tests/test_swapinterval.cpp 2014-07-25 10:04:16 +0000 | |||
412 | @@ -28,6 +28,7 @@ | |||
413 | 28 | 28 | ||
414 | 29 | #include "mir_test_framework/display_server_test_fixture.h" | 29 | #include "mir_test_framework/display_server_test_fixture.h" |
415 | 30 | #include "mir_test_doubles/stub_buffer.h" | 30 | #include "mir_test_doubles/stub_buffer.h" |
416 | 31 | #include "mir_test_doubles/stub_buffer_stream.h" | ||
417 | 31 | 32 | ||
418 | 32 | #include "mir_toolkit/mir_client_library.h" | 33 | #include "mir_toolkit/mir_client_library.h" |
419 | 33 | 34 | ||
420 | @@ -48,7 +49,7 @@ | |||
421 | 48 | { | 49 | { |
422 | 49 | char const* const mir_test_socket = mtf::test_socket_file().c_str(); | 50 | char const* const mir_test_socket = mtf::test_socket_file().c_str(); |
423 | 50 | 51 | ||
425 | 51 | class CountingBufferStream : public mc::BufferStream | 52 | class CountingBufferStream : public mtd::StubBufferStream |
426 | 52 | { | 53 | { |
427 | 53 | public: | 54 | public: |
428 | 54 | CountingBufferStream(int render_operations_fd) | 55 | CountingBufferStream(int render_operations_fd) |
429 | @@ -56,16 +57,6 @@ | |||
430 | 56 | { | 57 | { |
431 | 57 | } | 58 | } |
432 | 58 | 59 | ||
433 | 59 | void acquire_client_buffer( | ||
434 | 60 | std::function<void(mg::Buffer* buffer)> complete) override | ||
435 | 61 | { | ||
436 | 62 | complete(&stub_buffer); | ||
437 | 63 | } | ||
438 | 64 | |||
439 | 65 | void release_client_buffer(mg::Buffer*) override | ||
440 | 66 | { | ||
441 | 67 | } | ||
442 | 68 | |||
443 | 69 | std::shared_ptr<mg::Buffer> lock_compositor_buffer(void const*) override | 60 | std::shared_ptr<mg::Buffer> lock_compositor_buffer(void const*) override |
444 | 70 | { return std::make_shared<mtd::StubBuffer>(); } | 61 | { return std::make_shared<mtd::StubBuffer>(); } |
445 | 71 | 62 | ||
446 | @@ -75,18 +66,13 @@ | |||
447 | 75 | MirPixelFormat get_stream_pixel_format() override | 66 | MirPixelFormat get_stream_pixel_format() override |
448 | 76 | { return mir_pixel_format_abgr_8888; } | 67 | { return mir_pixel_format_abgr_8888; } |
449 | 77 | 68 | ||
450 | 78 | geom::Size stream_size() override { return geom::Size{}; } | ||
451 | 79 | void resize(geom::Size const&) override {} | ||
452 | 80 | void force_requests_to_complete() override {} | ||
453 | 81 | void allow_framedropping(bool) override | 69 | void allow_framedropping(bool) override |
454 | 82 | { | 70 | { |
455 | 83 | while (write(render_operations_fd, "a", 1) != 1) continue; | 71 | while (write(render_operations_fd, "a", 1) != 1) continue; |
456 | 84 | } | 72 | } |
457 | 85 | int buffers_ready_for_compositor() const override { return 1; } | ||
458 | 86 | 73 | ||
459 | 87 | private: | 74 | private: |
460 | 88 | int render_operations_fd; | 75 | int render_operations_fd; |
461 | 89 | mtd::StubBuffer stub_buffer; | ||
462 | 90 | }; | 76 | }; |
463 | 91 | 77 | ||
464 | 92 | class StubStreamFactory : public ms::BufferStreamFactory | 78 | class StubStreamFactory : public ms::BufferStreamFactory |
465 | 93 | 79 | ||
466 | === modified file 'tests/unit-tests/compositor/test_buffer_queue.cpp' | |||
467 | --- tests/unit-tests/compositor/test_buffer_queue.cpp 2014-07-11 05:14:40 +0000 | |||
468 | +++ tests/unit-tests/compositor/test_buffer_queue.cpp 2014-07-25 10:04:16 +0000 | |||
469 | @@ -1455,3 +1455,62 @@ | |||
470 | 1455 | q.compositor_release(comp); | 1455 | q.compositor_release(comp); |
471 | 1456 | } | 1456 | } |
472 | 1457 | } | 1457 | } |
473 | 1458 | |||
474 | 1459 | TEST_F(BufferQueueTest, gives_compositor_a_valid_buffer_after_dropping_old_buffers_without_clients) | ||
475 | 1460 | { | ||
476 | 1461 | int const nbuffers = 3; | ||
477 | 1462 | mc::BufferQueue q(nbuffers, allocator, basic_properties, policy_factory); | ||
478 | 1463 | |||
479 | 1464 | q.drop_old_buffers(); | ||
480 | 1465 | |||
481 | 1466 | auto comp = q.compositor_acquire(this); | ||
482 | 1467 | ASSERT_THAT(comp->id(), Ne(mg::BufferID{})); | ||
483 | 1468 | } | ||
484 | 1469 | |||
485 | 1470 | TEST_F(BufferQueueTest, gives_compositor_the_newest_buffer_after_dropping_old_buffers) | ||
486 | 1471 | { | ||
487 | 1472 | int const nbuffers = 3; | ||
488 | 1473 | mc::BufferQueue q(nbuffers, allocator, basic_properties, policy_factory); | ||
489 | 1474 | |||
490 | 1475 | auto handle1 = client_acquire_async(q); | ||
491 | 1476 | ASSERT_THAT(handle1->has_acquired_buffer(), Eq(true)); | ||
492 | 1477 | handle1->release_buffer(); | ||
493 | 1478 | |||
494 | 1479 | auto handle2 = client_acquire_async(q); | ||
495 | 1480 | ASSERT_THAT(handle2->has_acquired_buffer(), Eq(true)); | ||
496 | 1481 | handle2->release_buffer(); | ||
497 | 1482 | |||
498 | 1483 | q.drop_old_buffers(); | ||
499 | 1484 | |||
500 | 1485 | auto comp = q.compositor_acquire(this); | ||
501 | 1486 | ASSERT_THAT(comp->id(), Eq(handle2->id())); | ||
502 | 1487 | q.compositor_release(comp); | ||
503 | 1488 | |||
504 | 1489 | comp = q.compositor_acquire(this); | ||
505 | 1490 | ASSERT_THAT(comp->id(), Eq(handle2->id())); | ||
506 | 1491 | } | ||
507 | 1492 | |||
508 | 1493 | TEST_F(BufferQueueTest, gives_new_compositor_the_newest_buffer_after_dropping_old_buffers) | ||
509 | 1494 | { | ||
510 | 1495 | int const nbuffers = 3; | ||
511 | 1496 | void const* const new_compositor_id{&nbuffers}; | ||
512 | 1497 | |||
513 | 1498 | mc::BufferQueue q(nbuffers, allocator, basic_properties, policy_factory); | ||
514 | 1499 | |||
515 | 1500 | auto handle1 = client_acquire_async(q); | ||
516 | 1501 | ASSERT_THAT(handle1->has_acquired_buffer(), Eq(true)); | ||
517 | 1502 | handle1->release_buffer(); | ||
518 | 1503 | |||
519 | 1504 | auto comp = q.compositor_acquire(this); | ||
520 | 1505 | ASSERT_THAT(comp->id(), Eq(handle1->id())); | ||
521 | 1506 | q.compositor_release(comp); | ||
522 | 1507 | |||
523 | 1508 | auto handle2 = client_acquire_async(q); | ||
524 | 1509 | ASSERT_THAT(handle2->has_acquired_buffer(), Eq(true)); | ||
525 | 1510 | handle2->release_buffer(); | ||
526 | 1511 | |||
527 | 1512 | q.drop_old_buffers(); | ||
528 | 1513 | |||
529 | 1514 | auto comp2 = q.compositor_acquire(new_compositor_id); | ||
530 | 1515 | ASSERT_THAT(comp2->id(), Eq(handle2->id())); | ||
531 | 1516 | } |
PASSED: Continuous integration, rev:1790 jenkins. qa.ubuntu. com/job/ mir-team- mir-development -branch- ci/2220/ jenkins. qa.ubuntu. com/job/ mir-android- utopic- i386-build/ 1055 jenkins. qa.ubuntu. com/job/ mir-clang- utopic- amd64-build/ 1061 jenkins. qa.ubuntu. com/job/ mir-mediumtests -utopic- touch/1047 jenkins. qa.ubuntu. com/job/ mir-team- mir-development -branch- utopic- amd64-ci/ 742 jenkins. qa.ubuntu. com/job/ mir-team- mir-development -branch- utopic- amd64-ci/ 742/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ mir-team- mir-development -branch- utopic- armhf-ci/ 743 jenkins. qa.ubuntu. com/job/ mir-team- mir-development -branch- utopic- armhf-ci/ 743/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- utopic- armhf/3619 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- utopic- armhf/3619/ artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ mir-mediumtests -runner- mako/2164 s-jenkins. ubuntu- ci:8080/ job/touch- flash-device/ 10300
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/mir- team-mir- development- branch- ci/2220/ rebuild
http://