Mir

Merge lp:~kdub/mir/dropping-schedule into lp:mir

Proposed by Kevin DuBois
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
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.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

Looks good.

Nits:

51 + std::unique_lock<decltype(mutex)> lk(mutex);

Could use std::lock_guard<>

219 +TEST_F(DroppingSchedule, queues_drops_excess_buffers)

"queues_drops_..." ?

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Chris Halse Rogers (raof) wrote :

What is the cancel() call in there for? It introduces a race with anything_scheduled() (it's not possible for a consumer to call next_buffer() without possibly generating a logic_error), and I don't think it does what we want it to do.

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_queue_with(buffer).

review: Needs Fixing
Revision history for this message
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::cancelBuffer() as well.

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.

Revision history for this message
Kevin DuBois (kdub) wrote :

removed cancel(), as its not something thats needed at first, nor does it even have the ipc around at present.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Chris Halse Rogers (raof) wrote :

Seems a reasonable transition step.

review: Approve
Revision history for this message
Cemil Azizoglu (cemil-azizoglu) wrote :

ok

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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+}

Subscribers

People subscribed via source and target branches