Merge lp:~kdub/mir/dropping-schedule into lp:mir
- dropping-schedule
- Merge into development-branch
Status: | Merged |
---|---|
Approved by: | Kevin DuBois |
Approved revision: | no longer in the source branch. |
Merged at revision: | 2783 |
Proposed branch: | lp:~kdub/mir/dropping-schedule |
Merge into: | lp:mir |
Diff against target: |
238 lines (+202/-0) 5 files modified
src/server/compositor/CMakeLists.txt (+1/-0) src/server/compositor/dropping_schedule.cpp (+55/-0) src/server/compositor/dropping_schedule.h (+45/-0) tests/unit-tests/compositor/CMakeLists.txt (+1/-0) tests/unit-tests/compositor/test_dropping_schedule.cpp (+100/-0) |
To merge this branch: | bzr merge lp:~kdub/mir/dropping-schedule |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Approve | |
Cemil Azizoglu (community) | Approve | ||
Chris Halse Rogers | Approve | ||
Alexandros Frantzis (community) | Approve | ||
Review via email: mp+265303@code.launchpad.net |
Commit message
compositor: add a yet unused mc::Schedule implementation for egl-swapinterval-0 scenarios.
Description of the change
compositor: add a yet unused mc::Schedule implementation for egl-swapinterval-0 scenarios.
PS Jenkins bot (ps-jenkins) wrote : | # |
Alexandros Frantzis (afrantzis) wrote : | # |
Looks good.
Nits:
51 + std::unique_
Could use std::lock_guard<>
219 +TEST_F(
"queues_drops_..." ?
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:2753
http://
Executed test runs:
SUCCESS: http://
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 : | # |
What is the cancel() call in there for? It introduces a race with anything_
If I remember our previous discussions about this correctly, the objective of cancel() is to replace a stale back-buffer after a long period of inactivity (for example, display off). But for swapinterval 0 this is easy - submit a new buffer and you replace the stale back-buffer.
And for swap interval != 1 you need to discard the entire queue; this makes QueuingShedule vulnerable to the same race as DroppingSchedule.
I think this means that cancel() should actually be replace_
Kevin DuBois (kdub) wrote : | # |
The objective is a bit different. Its a client-facing lever that can be pushed to discard a buffer that has been submitted. Hopefully it'll help service ANativeWindow:
With swapinterval0 with 2 buffers, if one buffer is used by the compositor, and one has the last-produced content, the client has a problem getting another buffer to produce immediately. The most straightforward choices are to allocate another buffer to use, or to cancel the last-produced content and use that again.
Allocating another buffer solves this problem, (as submitting one buffer would send back the other one), but if we want to limit swapinterval0's space, cancel can help out. Cancel is not something that is crucial to the first round of integration.
Kevin DuBois (kdub) wrote : | # |
removed cancel(), as its not something thats needed at first, nor does it even have the ipc around at present.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:2754
http://
Executed test runs:
SUCCESS: http://
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 : | # |
FAILED: Continuous integration, rev:2754
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:2755
http://
Executed test runs:
SUCCESS: 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:
http://
Chris Halse Rogers (raof) wrote : | # |
Seems a reasonable transition step.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
PS Jenkins bot (ps-jenkins) : | # |
Preview Diff
1 | === modified file 'src/server/compositor/CMakeLists.txt' |
2 | --- src/server/compositor/CMakeLists.txt 2015-07-23 19:14:27 +0000 |
3 | +++ src/server/compositor/CMakeLists.txt 2015-07-27 11:30:52 +0000 |
4 | @@ -19,6 +19,7 @@ |
5 | recently_used_cache.cpp |
6 | multi_monitor_arbiter.cpp |
7 | buffer_map.cpp |
8 | + dropping_schedule.cpp |
9 | queueing_schedule.cpp |
10 | ) |
11 | |
12 | |
13 | === added file 'src/server/compositor/dropping_schedule.cpp' |
14 | --- src/server/compositor/dropping_schedule.cpp 1970-01-01 00:00:00 +0000 |
15 | +++ src/server/compositor/dropping_schedule.cpp 2015-07-27 11:30:52 +0000 |
16 | @@ -0,0 +1,55 @@ |
17 | +/* |
18 | + * Copyright © 2015 Canonical Ltd. |
19 | + * |
20 | + * This program is free software: you can redistribute it and/or modify it |
21 | + * under the terms of the GNU General Public License version 3, |
22 | + * as published by the Free Software Foundation. |
23 | + * |
24 | + * This program is distributed in the hope that it will be useful, |
25 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
26 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
27 | + * GNU General Public License for more details. |
28 | + * |
29 | + * You should have received a copy of the GNU General Public License |
30 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
31 | + * |
32 | + * Authored by: Kevin DuBois <kevin.dubois@canonical.com> |
33 | + */ |
34 | + |
35 | +#include "dropping_schedule.h" |
36 | +#include "mir/frontend/client_buffers.h" |
37 | +#include "mir/graphics/buffer.h" |
38 | + |
39 | +#include <boost/throw_exception.hpp> |
40 | +namespace mf = mir::frontend; |
41 | +namespace mg = mir::graphics; |
42 | +namespace mc = mir::compositor; |
43 | + |
44 | +mc::DroppingSchedule::DroppingSchedule(std::shared_ptr<mf::ClientBuffers> const& client_buffers) : |
45 | + sender(client_buffers) |
46 | +{ |
47 | +} |
48 | + |
49 | +void mc::DroppingSchedule::schedule(std::shared_ptr<mg::Buffer> const& buffer) |
50 | +{ |
51 | + std::lock_guard<decltype(mutex)> lk(mutex); |
52 | + if ((the_only_buffer != buffer) && the_only_buffer) |
53 | + sender->send_buffer(the_only_buffer->id()); |
54 | + the_only_buffer = buffer; |
55 | +} |
56 | + |
57 | +bool mc::DroppingSchedule::anything_scheduled() |
58 | +{ |
59 | + std::lock_guard<decltype(mutex)> lk(mutex); |
60 | + return static_cast<bool>(the_only_buffer); |
61 | +} |
62 | + |
63 | +std::shared_ptr<mg::Buffer> mc::DroppingSchedule::next_buffer() |
64 | +{ |
65 | + std::lock_guard<decltype(mutex)> lk(mutex); |
66 | + if (!the_only_buffer) |
67 | + BOOST_THROW_EXCEPTION(std::logic_error("no buffer scheduled")); |
68 | + auto buffer = the_only_buffer; |
69 | + the_only_buffer = nullptr; |
70 | + return buffer; |
71 | +} |
72 | |
73 | === added file 'src/server/compositor/dropping_schedule.h' |
74 | --- src/server/compositor/dropping_schedule.h 1970-01-01 00:00:00 +0000 |
75 | +++ src/server/compositor/dropping_schedule.h 2015-07-27 11:30:52 +0000 |
76 | @@ -0,0 +1,45 @@ |
77 | +/* |
78 | + * Copyright © 2015 Canonical Ltd. |
79 | + * |
80 | + * This program is free software: you can redistribute it and/or modify it |
81 | + * under the terms of the GNU General Public License version 3, |
82 | + * as published by the Free Software Foundation. |
83 | + * |
84 | + * This program is distributed in the hope that it will be useful, |
85 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
86 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
87 | + * GNU General Public License for more details. |
88 | + * |
89 | + * You should have received a copy of the GNU General Public License |
90 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
91 | + * |
92 | + * Authored by: Kevin DuBois <kevin.dubois@canonical.com> |
93 | + */ |
94 | + |
95 | +#ifndef MIR_COMPOSITOR_DROPPING_SCHEDULE_H_ |
96 | +#define MIR_COMPOSITOR_DROPPING_SCHEDULE_H_ |
97 | +#include <memory> |
98 | +#include <mutex> |
99 | + |
100 | +namespace mir |
101 | +{ |
102 | +namespace graphics { class Buffer; } |
103 | +namespace frontend { class ClientBuffers; } |
104 | +namespace compositor |
105 | +{ |
106 | +class DroppingSchedule |
107 | +{ |
108 | +public: |
109 | + DroppingSchedule(std::shared_ptr<frontend::ClientBuffers> const&); |
110 | + void schedule(std::shared_ptr<graphics::Buffer> const& buffer); |
111 | + bool anything_scheduled(); |
112 | + std::shared_ptr<graphics::Buffer> next_buffer(); |
113 | + |
114 | +private: |
115 | + std::mutex mutable mutex; |
116 | + std::shared_ptr<frontend::ClientBuffers> const sender; |
117 | + std::shared_ptr<graphics::Buffer> the_only_buffer; |
118 | +}; |
119 | +} |
120 | +} |
121 | +#endif /* MIR_COMPOSITOR_DROPPING_SCHEDULE_H_ */ |
122 | |
123 | === modified file 'tests/unit-tests/compositor/CMakeLists.txt' |
124 | --- tests/unit-tests/compositor/CMakeLists.txt 2015-07-23 19:14:27 +0000 |
125 | +++ tests/unit-tests/compositor/CMakeLists.txt 2015-07-27 11:30:52 +0000 |
126 | @@ -13,6 +13,7 @@ |
127 | ${CMAKE_CURRENT_SOURCE_DIR}/test_timeout_frame_dropping_policy.cpp |
128 | ${CMAKE_CURRENT_SOURCE_DIR}/test_multi_monitor_arbiter.cpp |
129 | ${CMAKE_CURRENT_SOURCE_DIR}/test_client_buffers.cpp |
130 | + ${CMAKE_CURRENT_SOURCE_DIR}/test_dropping_schedule.cpp |
131 | ${CMAKE_CURRENT_SOURCE_DIR}/test_queueing_schedule.cpp |
132 | ) |
133 | |
134 | |
135 | === added file 'tests/unit-tests/compositor/test_dropping_schedule.cpp' |
136 | --- tests/unit-tests/compositor/test_dropping_schedule.cpp 1970-01-01 00:00:00 +0000 |
137 | +++ tests/unit-tests/compositor/test_dropping_schedule.cpp 2015-07-27 11:30:52 +0000 |
138 | @@ -0,0 +1,100 @@ |
139 | +/* |
140 | + * Copyright © 2015 Canonical Ltd. |
141 | + * |
142 | + * This program is free software: you can redistribute it and/or modify |
143 | + * it under the terms of the GNU General Public License version 3 as |
144 | + * published by the Free Software Foundation. |
145 | + * |
146 | + * This program is distributed in the hope that it will be useful, |
147 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
148 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
149 | + * GNU General Public License for more details. |
150 | + * |
151 | + * You should have received a copy of the GNU General Public License |
152 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
153 | + * |
154 | + * Authored by: Kevin DuBois <kevin.dubois@canonical.com> |
155 | + */ |
156 | + |
157 | +#include "mir/frontend/client_buffers.h" |
158 | +#include "src/server/compositor/dropping_schedule.h" |
159 | +#include "mir/test/doubles/stub_buffer.h" |
160 | +#include "mir/test/fake_shared.h" |
161 | +#include <gtest/gtest.h> |
162 | + |
163 | +using namespace testing; |
164 | +namespace mtd = mir::test::doubles; |
165 | +namespace mt = mir::test; |
166 | +namespace mg = mir::graphics; |
167 | +namespace mc = mir::compositor; |
168 | +namespace mf = mir::frontend; |
169 | +namespace |
170 | +{ |
171 | + |
172 | +struct MockBufferMap : mf::ClientBuffers |
173 | +{ |
174 | + MOCK_METHOD1(add_buffer, void(mg::BufferProperties const&)); |
175 | + MOCK_METHOD1(remove_buffer, void(mg::BufferID id)); |
176 | + MOCK_METHOD1(send_buffer, void(mg::BufferID id)); |
177 | + MOCK_METHOD1(at, std::shared_ptr<mg::Buffer>&(mg::BufferID)); |
178 | + std::shared_ptr<mg::Buffer>& operator[](mg::BufferID id) { return at(id); } |
179 | +}; |
180 | + |
181 | +struct DroppingSchedule : Test |
182 | +{ |
183 | + DroppingSchedule() |
184 | + { |
185 | + for(auto i = 0u; i < num_buffers; i++) |
186 | + buffers.emplace_back(std::make_shared<mtd::StubBuffer>()); |
187 | + } |
188 | + unsigned int const num_buffers{5}; |
189 | + std::vector<std::shared_ptr<mg::Buffer>> buffers; |
190 | + |
191 | + MockBufferMap mock_client_buffers; |
192 | + mc::DroppingSchedule schedule{mt::fake_shared(mock_client_buffers)}; |
193 | + std::vector<std::shared_ptr<mg::Buffer>> drain_queue() |
194 | + { |
195 | + std::vector<std::shared_ptr<mg::Buffer>> scheduled_buffers; |
196 | + while(schedule.anything_scheduled()) |
197 | + scheduled_buffers.emplace_back(schedule.next_buffer()); |
198 | + return scheduled_buffers; |
199 | + } |
200 | +}; |
201 | +} |
202 | + |
203 | +TEST_F(DroppingSchedule, throws_if_no_buffers) |
204 | +{ |
205 | + EXPECT_FALSE(schedule.anything_scheduled()); |
206 | + EXPECT_THROW({ |
207 | + schedule.next_buffer(); |
208 | + }, std::logic_error); |
209 | +} |
210 | + |
211 | +TEST_F(DroppingSchedule, drops_excess_buffers) |
212 | +{ |
213 | + InSequence seq; |
214 | + EXPECT_CALL(mock_client_buffers, send_buffer(buffers[0]->id())); |
215 | + EXPECT_CALL(mock_client_buffers, send_buffer(buffers[1]->id())); |
216 | + EXPECT_CALL(mock_client_buffers, send_buffer(buffers[2]->id())); |
217 | + EXPECT_CALL(mock_client_buffers, send_buffer(buffers[3]->id())); |
218 | + |
219 | + for(auto i = 0u; i < num_buffers; i++) |
220 | + schedule.schedule(buffers[i]); |
221 | + |
222 | + auto queue = drain_queue(); |
223 | + ASSERT_THAT(queue, SizeIs(1)); |
224 | + EXPECT_THAT(queue[0]->id(), Eq(buffers[4]->id())); |
225 | +} |
226 | + |
227 | +TEST_F(DroppingSchedule, queueing_same_buffer_many_times_doesnt_drop) |
228 | +{ |
229 | + EXPECT_CALL(mock_client_buffers, send_buffer(_)).Times(0); |
230 | + |
231 | + schedule.schedule(buffers[2]); |
232 | + schedule.schedule(buffers[2]); |
233 | + schedule.schedule(buffers[2]); |
234 | + |
235 | + auto queue = drain_queue(); |
236 | + ASSERT_THAT(queue, SizeIs(1)); |
237 | + EXPECT_THAT(queue[0]->id(), Eq(buffers[2]->id())); |
238 | +} |
PASSED: Continuous integration, rev:2750 jenkins. qa.ubuntu. com/job/ mir-ci/ 4367/ jenkins. qa.ubuntu. com/job/ mir-android- vivid-i386- build/3227 s-jenkins. ubuntu- ci:8080/ job/mir- clang-ts- wily-amd64- build/80 jenkins. qa.ubuntu. com/job/ mir-clang- wily-amd64- build/752 jenkins. qa.ubuntu. com/job/ mir-mediumtests -vivid- touch/3175 jenkins. qa.ubuntu. com/job/ mir-wily- amd64-ci/ 516 jenkins. qa.ubuntu. com/job/ mir-wily- amd64-ci/ 516/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ mir-mediumtests -builder- vivid-armhf/ 3175 jenkins. qa.ubuntu. com/job/ mir-mediumtests -builder- vivid-armhf/ 3175/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ mir-mediumtests -runner- mako/5977 s-jenkins. ubuntu- ci:8080/ job/touch- flash-device/ 21991
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: 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- ci/4367/ rebuild
http://