Merge lp:~vanvugt/mir/fix-1476201 into lp:mir
- fix-1476201
- Merge into development-branch
Status: | Merged |
---|---|
Approved by: | Daniel van Vugt |
Approved revision: | no longer in the source branch. |
Merged at revision: | 3254 |
Proposed branch: | lp:~vanvugt/mir/fix-1476201 |
Merge into: | lp:mir |
Prerequisite: | lp:~vanvugt/mir/better-scaling-test-2 |
Diff against target: |
245 lines (+142/-9) 3 files modified
src/server/compositor/buffer_queue.cpp (+24/-4) src/server/compositor/buffer_queue.h (+1/-0) tests/unit-tests/compositor/test_buffer_queue.cpp (+117/-5) |
To merge this branch: | bzr merge lp:~vanvugt/mir/fix-1476201 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Approve | |
Mir CI Bot | continuous-integration | Approve | |
Alan Griffiths | Approve | ||
Mir development team | Pending | ||
Review via email: mp+269849@code.launchpad.net |
Commit message
Enhance BufferQueue:
to support the usage pattern found in QtMir so that it too can have
working detection of slow clients (to help us decide when to scale
to triple instead of double buffers). (LP: #1476201)
We could have changed QtMir instead, but I decided it's a perfectly
valid usage pattern and we should support both, making Mir more
robust in its ability to support third-party compositors.
Description of the change
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:2792
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:2793
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:2794
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://
Alan Griffiths (alan-griffiths) wrote : | # |
What are ghost frames?
Daniel van Vugt (vanvugt) wrote : | # |
At least two of those sizeable comments in the code explain it. If you can think of a better noun, please suggest...
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:2799
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://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:2824
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
FAILURE: http://
SUCCESS: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:2825
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
FAILURE: http://
SUCCESS: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:2826
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:2835
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
SUCCESS: http://
deb: http://
None: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:2836
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:2838
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:2838
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
Cemil Azizoglu (cemil-azizoglu) wrote : | # |
This one has been around for a while. Alan, are you happy with the name "ghost frames" or did you have a suggestion?
Alan Griffiths (alan-griffiths) wrote : | # |
> This one has been around for a while. Alan, are you happy with the name "ghost
> frames" or did you have a suggestion?
I don't know what "ghost frames" are, so I have no suggestion. The comments leave me no wiser (and, if possible, I'd prefer the code to be readable without parsing "large comments").
Daniel van Vugt (vanvugt) wrote : | # |
"Ghost frame" terminology now removed.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:2857
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alan Griffiths (alan-griffiths) wrote : | # |
It would be nice to have some automated performance testing for the scenario this is intended to support. Especially as this optimization is likely to be bypassed by the "new buffer semantics" work in progress elsewhere.
Daniel van Vugt (vanvugt) wrote : | # |
The automated performance testing (other than the unit tests below) is ready and waiting. The ClientLatency acceptance tests will start failing (unless updated) when/if dynamic queue scaling is re-enabled, as is documented in the ClientLatency test.
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:2857
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Daniel van Vugt (vanvugt) wrote : | # |
Possibly not even related to this branch, given queue scaling is still disabled:
12: /tmp/buildd/
12: Value of: observed_latency
12: Expected: is < 3.4
12: Actual: 3.40404 (of type float)
Try again.
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:2859
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:2859
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:2860
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
FAILURE: http://
None: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
FAILURE: http://
SUCCESS: http://
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2860
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:2861
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:2861
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:2863
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:2861
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:2863
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) : | # |
Preview Diff
1 | === modified file 'src/server/compositor/buffer_queue.cpp' | |||
2 | --- src/server/compositor/buffer_queue.cpp 2015-10-20 03:30:00 +0000 | |||
3 | +++ src/server/compositor/buffer_queue.cpp 2016-01-19 21:00:22 +0000 | |||
4 | @@ -139,6 +139,7 @@ | |||
5 | 139 | : nbuffers{nbuffers}, | 139 | : nbuffers{nbuffers}, |
6 | 140 | frame_deadlines_threshold{-1}, // Disable scaling by default | 140 | frame_deadlines_threshold{-1}, // Disable scaling by default |
7 | 141 | frame_deadlines_met{0}, | 141 | frame_deadlines_met{0}, |
8 | 142 | scheduled_extra_frames{0}, | ||
9 | 142 | frame_dropping_enabled{false}, | 143 | frame_dropping_enabled{false}, |
10 | 143 | current_compositor_buffer_valid{false}, | 144 | current_compositor_buffer_valid{false}, |
11 | 144 | the_properties{props}, | 145 | the_properties{props}, |
12 | @@ -266,6 +267,14 @@ | |||
13 | 266 | 267 | ||
14 | 267 | auto const buffer = pop(buffers_owned_by_client); | 268 | auto const buffer = pop(buffers_owned_by_client); |
15 | 268 | ready_to_composite_queue.push_back(buffer); | 269 | ready_to_composite_queue.push_back(buffer); |
16 | 270 | |||
17 | 271 | /* | ||
18 | 272 | * Timerless client performance detection: | ||
19 | 273 | * Over-schedule the compositor so that it can detect if the client | ||
20 | 274 | * is falling behind. Otherwise the compositor itself goes to sleep | ||
21 | 275 | * and wouldn't be able to tell a slow client from a fast one. | ||
22 | 276 | */ | ||
23 | 277 | scheduled_extra_frames = frame_deadlines_threshold - 1; | ||
24 | 269 | } | 278 | } |
25 | 270 | 279 | ||
26 | 271 | std::shared_ptr<mg::Buffer> | 280 | std::shared_ptr<mg::Buffer> |
27 | @@ -276,6 +285,15 @@ | |||
28 | 276 | bool use_current_buffer = false; | 285 | bool use_current_buffer = false; |
29 | 277 | if (is_a_current_buffer_user(user_id)) // Primary/fastest display | 286 | if (is_a_current_buffer_user(user_id)) // Primary/fastest display |
30 | 278 | { | 287 | { |
31 | 288 | /* | ||
32 | 289 | * Yes I know different compositor user_ids will get different | ||
33 | 290 | * results with this but that's OK, and actually more efficient. | ||
34 | 291 | * We only need to overschedule one display at most for the | ||
35 | 292 | * slow client detection to work. | ||
36 | 293 | */ | ||
37 | 294 | if (scheduled_extra_frames > 0) | ||
38 | 295 | --scheduled_extra_frames; | ||
39 | 296 | |||
40 | 279 | if (ready_to_composite_queue.empty()) | 297 | if (ready_to_composite_queue.empty()) |
41 | 280 | frame_deadlines_met = 0; | 298 | frame_deadlines_met = 0; |
42 | 281 | else if (frame_deadlines_met < frame_deadlines_threshold) | 299 | else if (frame_deadlines_met < frame_deadlines_threshold) |
43 | @@ -454,21 +472,21 @@ | |||
44 | 454 | } | 472 | } |
45 | 455 | 473 | ||
46 | 456 | /* | 474 | /* |
48 | 457 | * Intentionally schedule one more frame than we need, and for good | 475 | * Intentionally schedule more frames than we need, and for good |
49 | 458 | * reason... We can only accurately detect frame_deadlines_met in | 476 | * reason... We can only accurately detect frame_deadlines_met in |
50 | 459 | * compositor_acquire if compositor_acquire is still waking up at full | 477 | * compositor_acquire if compositor_acquire is still waking up at full |
51 | 460 | * frame rate even with a slow client. This is crucial to scaling the | 478 | * frame rate even with a slow client. This is crucial to scaling the |
52 | 461 | * queue performance dynamically in "client_ahead_of_compositor". | 479 | * queue performance dynamically in "client_ahead_of_compositor". |
53 | 462 | * But don't be concerned; very little is lost by over-scheduling. Under | 480 | * But don't be concerned; very little is lost by over-scheduling. Under |
54 | 463 | * normal smooth rendering conditions all frames are used (not wasted). | 481 | * normal smooth rendering conditions all frames are used (not wasted). |
56 | 464 | * And under sluggish client rendering conditions the extra frame has a | 482 | * And under sluggish client rendering conditions the extra frames have a |
57 | 465 | * critical role in providing a sample point in which we detect if the | 483 | * critical role in providing a sample point in which we detect if the |
58 | 466 | * client is keeping up. Only when the compositor changes from active to | 484 | * client is keeping up. Only when the compositor changes from active to |
59 | 467 | * idle is the extra frame wasted. Sounds like a reasonable price to pay | 485 | * idle is the extra frame wasted. Sounds like a reasonable price to pay |
60 | 468 | * for dynamic performance monitoring. | 486 | * for dynamic performance monitoring. |
61 | 469 | */ | 487 | */ |
64 | 470 | if (count && frame_deadlines_threshold >= 0) | 488 | if (frame_deadlines_threshold >= 0 && scheduled_extra_frames > 0) |
65 | 471 | ++count; | 489 | count += scheduled_extra_frames; |
66 | 472 | 490 | ||
67 | 473 | return count; | 491 | return count; |
68 | 474 | } | 492 | } |
69 | @@ -660,6 +678,8 @@ | |||
70 | 660 | std::unique_lock<decltype(guard)> lock{guard}; | 678 | std::unique_lock<decltype(guard)> lock{guard}; |
71 | 661 | release(buffer, std::move(lock)); | 679 | release(buffer, std::move(lock)); |
72 | 662 | } | 680 | } |
73 | 681 | |||
74 | 682 | scheduled_extra_frames = 0; | ||
75 | 663 | } | 683 | } |
76 | 664 | 684 | ||
77 | 665 | void mc::BufferQueue::drop_client_requests() | 685 | void mc::BufferQueue::drop_client_requests() |
78 | 666 | 686 | ||
79 | === modified file 'src/server/compositor/buffer_queue.h' | |||
80 | --- src/server/compositor/buffer_queue.h 2015-09-17 20:32:32 +0000 | |||
81 | +++ src/server/compositor/buffer_queue.h 2016-01-19 21:00:22 +0000 | |||
82 | @@ -109,6 +109,7 @@ | |||
83 | 109 | int nbuffers; | 109 | int nbuffers; |
84 | 110 | int frame_deadlines_threshold; | 110 | int frame_deadlines_threshold; |
85 | 111 | int frame_deadlines_met; | 111 | int frame_deadlines_met; |
86 | 112 | int scheduled_extra_frames; | ||
87 | 112 | bool frame_dropping_enabled; | 113 | bool frame_dropping_enabled; |
88 | 113 | bool current_compositor_buffer_valid; | 114 | bool current_compositor_buffer_valid; |
89 | 114 | graphics::BufferProperties the_properties; | 115 | graphics::BufferProperties the_properties; |
90 | 115 | 116 | ||
91 | === modified file 'tests/unit-tests/compositor/test_buffer_queue.cpp' | |||
92 | --- tests/unit-tests/compositor/test_buffer_queue.cpp 2015-09-17 20:32:32 +0000 | |||
93 | +++ tests/unit-tests/compositor/test_buffer_queue.cpp 2016-01-19 21:00:22 +0000 | |||
94 | @@ -1405,6 +1405,33 @@ | |||
95 | 1405 | q.compositor_release(c); | 1405 | q.compositor_release(c); |
96 | 1406 | } | 1406 | } |
97 | 1407 | 1407 | ||
98 | 1408 | TEST_P(WithTwoOrMoreBuffers, buffers_ready_count_tapers_off) | ||
99 | 1409 | { // Another test related to QtMir's style of doing things (LP: #1476201) | ||
100 | 1410 | mc::BufferQueue q{nbuffers, allocator, basic_properties, policy_factory}; | ||
101 | 1411 | |||
102 | 1412 | q.set_scaling_delay(3); | ||
103 | 1413 | |||
104 | 1414 | ASSERT_THAT(q.buffers_ready_for_compositor(this), Eq(0)); | ||
105 | 1415 | |||
106 | 1416 | // Produce one frame | ||
107 | 1417 | q.client_release(client_acquire_sync(q)); | ||
108 | 1418 | |||
109 | 1419 | // Ensure we're told multiple frames are ready to facilitate the | ||
110 | 1420 | // compositor detecting a slow client that misses the second one. | ||
111 | 1421 | ASSERT_THAT(q.buffers_ready_for_compositor(this), Ge(2)); | ||
112 | 1422 | |||
113 | 1423 | // Consume one frame | ||
114 | 1424 | q.compositor_release(q.compositor_acquire(this)); | ||
115 | 1425 | |||
116 | 1426 | // Finally verify the count is tapering off instead of dropping off | ||
117 | 1427 | ASSERT_THAT(q.buffers_ready_for_compositor(this), Ge(1)); | ||
118 | 1428 | |||
119 | 1429 | for (int flush = 0; flush < q.scaling_delay(); ++flush) | ||
120 | 1430 | q.compositor_release(q.compositor_acquire(this)); | ||
121 | 1431 | |||
122 | 1432 | ASSERT_THAT(q.buffers_ready_for_compositor(this), Eq(0)); | ||
123 | 1433 | } | ||
124 | 1434 | |||
125 | 1408 | TEST_P(WithTwoOrMoreBuffers, buffers_ready_eventually_reaches_zero) | 1435 | TEST_P(WithTwoOrMoreBuffers, buffers_ready_eventually_reaches_zero) |
126 | 1409 | { | 1436 | { |
127 | 1410 | mc::BufferQueue q{nbuffers, allocator, basic_properties, policy_factory}; | 1437 | mc::BufferQueue q{nbuffers, allocator, basic_properties, policy_factory}; |
128 | @@ -1425,11 +1452,12 @@ | |||
129 | 1425 | { | 1452 | { |
130 | 1426 | ASSERT_NE(0, q.buffers_ready_for_compositor(&monitor[m])); | 1453 | ASSERT_NE(0, q.buffers_ready_for_compositor(&monitor[m])); |
131 | 1427 | 1454 | ||
133 | 1428 | // Double consume to account for the +1 that | 1455 | // Extra consume to account for the additional frames that |
134 | 1429 | // buffers_ready_for_compositor adds to do dynamic performance | 1456 | // buffers_ready_for_compositor adds to do dynamic performance |
135 | 1430 | // detection. | 1457 | // detection. |
138 | 1431 | q.compositor_release(q.compositor_acquire(&monitor[m])); | 1458 | int const nflush = (q.scaling_delay() > 0) ? q.scaling_delay() : 1; |
139 | 1432 | q.compositor_release(q.compositor_acquire(&monitor[m])); | 1459 | for (int flush = 0; flush < nflush; ++flush) |
140 | 1460 | q.compositor_release(q.compositor_acquire(&monitor[m])); | ||
141 | 1433 | 1461 | ||
142 | 1434 | ASSERT_EQ(0, q.buffers_ready_for_compositor(&monitor[m])); | 1462 | ASSERT_EQ(0, q.buffers_ready_for_compositor(&monitor[m])); |
143 | 1435 | } | 1463 | } |
144 | @@ -1711,6 +1739,91 @@ | |||
145 | 1711 | EXPECT_THAT(buffers_acquired.size(), Eq(2)); | 1739 | EXPECT_THAT(buffers_acquired.size(), Eq(2)); |
146 | 1712 | } | 1740 | } |
147 | 1713 | 1741 | ||
148 | 1742 | TEST_P(WithThreeOrMoreBuffers, queue_size_scales_up_without_accumulator) | ||
149 | 1743 | { // A regression test similar to above but designed to mimic QtMir | ||
150 | 1744 | // for LP: #1476201. | ||
151 | 1745 | |||
152 | 1746 | q.allow_framedropping(false); | ||
153 | 1747 | std::unordered_set<mg::Buffer *> buffers_acquired; | ||
154 | 1748 | |||
155 | 1749 | int const delay = 3; | ||
156 | 1750 | q.set_scaling_delay(delay); | ||
157 | 1751 | |||
158 | 1752 | int const nframes = 100; | ||
159 | 1753 | |||
160 | 1754 | std::shared_ptr<AcquireWaitHandle> client; | ||
161 | 1755 | |||
162 | 1756 | for (int frame = 0; frame < nframes; ++frame) | ||
163 | 1757 | { | ||
164 | 1758 | do | ||
165 | 1759 | { | ||
166 | 1760 | if (!client) | ||
167 | 1761 | client = client_acquire_async(q); | ||
168 | 1762 | if (client->has_acquired_buffer()) | ||
169 | 1763 | { | ||
170 | 1764 | if (frame > delay) | ||
171 | 1765 | buffers_acquired.insert(client->buffer()); | ||
172 | 1766 | client->release_buffer(); | ||
173 | 1767 | client.reset(); | ||
174 | 1768 | } | ||
175 | 1769 | } while (!client); | ||
176 | 1770 | |||
177 | 1771 | q.compositor_release(q.compositor_acquire(nullptr)); | ||
178 | 1772 | } | ||
179 | 1773 | // Expect double-buffers for fast clients | ||
180 | 1774 | EXPECT_THAT(buffers_acquired.size(), Eq(2)); | ||
181 | 1775 | |||
182 | 1776 | // Now check what happens if the client becomes slow... | ||
183 | 1777 | buffers_acquired.clear(); | ||
184 | 1778 | for (int frame = 0; frame < nframes;) | ||
185 | 1779 | { | ||
186 | 1780 | do | ||
187 | 1781 | { | ||
188 | 1782 | if (!client) | ||
189 | 1783 | client = client_acquire_async(q); | ||
190 | 1784 | if (client->has_acquired_buffer()) | ||
191 | 1785 | { | ||
192 | 1786 | if (frame > delay) | ||
193 | 1787 | buffers_acquired.insert(client->buffer()); | ||
194 | 1788 | client->release_buffer(); | ||
195 | 1789 | client.reset(); | ||
196 | 1790 | } | ||
197 | 1791 | } while (!client); | ||
198 | 1792 | |||
199 | 1793 | // Mimic QtMir in that it tests buffers ready as a boolean and does | ||
200 | 1794 | // not keep its own accumulator in the compositor: | ||
201 | 1795 | while (q.buffers_ready_for_compositor(nullptr)) | ||
202 | 1796 | { | ||
203 | 1797 | q.compositor_release(q.compositor_acquire(nullptr)); | ||
204 | 1798 | ++frame; | ||
205 | 1799 | } | ||
206 | 1800 | } | ||
207 | 1801 | // Expect at least triple buffers for sluggish clients | ||
208 | 1802 | EXPECT_THAT(buffers_acquired.size(), Ge(3)); | ||
209 | 1803 | |||
210 | 1804 | // And what happens if the client becomes fast again?... | ||
211 | 1805 | buffers_acquired.clear(); | ||
212 | 1806 | for (int frame = 0; frame < nframes; ++frame) | ||
213 | 1807 | { | ||
214 | 1808 | do | ||
215 | 1809 | { | ||
216 | 1810 | if (!client) | ||
217 | 1811 | client = client_acquire_async(q); | ||
218 | 1812 | if (client->has_acquired_buffer()) | ||
219 | 1813 | { | ||
220 | 1814 | if (frame > delay) | ||
221 | 1815 | buffers_acquired.insert(client->buffer()); | ||
222 | 1816 | client->release_buffer(); | ||
223 | 1817 | client.reset(); | ||
224 | 1818 | } | ||
225 | 1819 | } while (!client); | ||
226 | 1820 | |||
227 | 1821 | q.compositor_release(q.compositor_acquire(nullptr)); | ||
228 | 1822 | } | ||
229 | 1823 | // Expect double-buffers for fast clients | ||
230 | 1824 | EXPECT_THAT(buffers_acquired.size(), Eq(2)); | ||
231 | 1825 | } | ||
232 | 1826 | |||
233 | 1714 | TEST_P(WithThreeOrMoreBuffers, greedy_compositors_need_triple_buffers) | 1827 | TEST_P(WithThreeOrMoreBuffers, greedy_compositors_need_triple_buffers) |
234 | 1715 | { | 1828 | { |
235 | 1716 | /* | 1829 | /* |
236 | @@ -1755,8 +1868,7 @@ | |||
237 | 1755 | ASSERT_EQ(0, q.buffers_ready_for_compositor(this)); | 1868 | ASSERT_EQ(0, q.buffers_ready_for_compositor(this)); |
238 | 1756 | q.client_release(client_acquire_sync(q)); | 1869 | q.client_release(client_acquire_sync(q)); |
239 | 1757 | 1870 | ||
242 | 1758 | // Detecting a slow client requires scheduling at least one extra | 1871 | // Detecting a slow client requires scheduling extra frames |
241 | 1759 | // frame... | ||
243 | 1760 | int nready = q.buffers_ready_for_compositor(this); | 1872 | int nready = q.buffers_ready_for_compositor(this); |
244 | 1761 | ASSERT_THAT(nready, Ge(2)); | 1873 | ASSERT_THAT(nready, Ge(2)); |
245 | 1762 | for (int i = 0; i < nready; ++i) | 1874 | for (int i = 0; i < nready; ++i) |
FAILED: Continuous integration, rev:2791 jenkins. qa.ubuntu. com/job/ mir-ci/ 4775/ jenkins. qa.ubuntu. com/job/ mir-android- vivid-i386- build/3796/ console s-jenkins. ubuntu- ci:8080/ job/mir- clang-ts- vivid-amd64- build/218/ console jenkins. qa.ubuntu. com/job/ mir-clang- vivid-amd64- build/2707 jenkins. qa.ubuntu. com/job/ mir-mediumtests -vivid- touch/3746/ console jenkins. qa.ubuntu. com/job/ mir-wily- amd64-ci/ 924 jenkins. qa.ubuntu. com/job/ mir-wily- amd64-ci/ 924/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ mir-mediumtests -builder- vivid-armhf/ 3746 jenkins. qa.ubuntu. com/job/ mir-mediumtests -builder- vivid-armhf/ 3746/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ mir-mediumtests -runner- mako/6479/ console s-jenkins. ubuntu- ci:8080/ job/touch- flash-device/ 22985
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/mir- ci/4775/ rebuild
http://