Mir

Merge lp:~kdub/mir/android-multimonitor into lp:mir

Proposed by Kevin DuBois
Status: Merged
Approved by: Kevin DuBois
Approved revision: no longer in the source branch.
Merged at revision: 2356
Proposed branch: lp:~kdub/mir/android-multimonitor
Merge into: lp:mir
Prerequisite: lp:~kdub/mir/display-groups
Diff against target: 1345 lines (+531/-208)
29 files modified
src/platforms/android/server/CMakeLists.txt (+1/-0)
src/platforms/android/server/configurable_display_buffer.h (+4/-5)
src/platforms/android/server/display.cpp (+40/-41)
src/platforms/android/server/display.h (+3/-3)
src/platforms/android/server/display_buffer.cpp (+14/-13)
src/platforms/android/server/display_buffer.h (+3/-3)
src/platforms/android/server/display_device.h (+10/-5)
src/platforms/android/server/display_group.cpp (+81/-0)
src/platforms/android/server/display_group.h (+62/-0)
src/platforms/android/server/fb_device.cpp (+9/-5)
src/platforms/android/server/fb_device.h (+1/-5)
src/platforms/android/server/hwc_blanking_control.cpp (+13/-2)
src/platforms/android/server/hwc_device.cpp (+52/-36)
src/platforms/android/server/hwc_device.h (+1/-5)
src/platforms/android/server/hwc_fb_device.cpp (+10/-5)
src/platforms/android/server/hwc_fb_device.h (+1/-5)
src/platforms/android/server/swapping_gl_context.h (+2/-0)
tests/include/mir_test_doubles/mock_display_device.h (+1/-5)
tests/include/mir_test_doubles/mock_swapping_gl_context.h (+2/-0)
tests/include/mir_test_doubles/stub_swapping_gl_context.h (+2/-0)
tests/unit-tests/graphics/android/CMakeLists.txt (+1/-0)
tests/unit-tests/graphics/android/hwc_struct_helpers.h (+18/-5)
tests/unit-tests/graphics/android/test_display.cpp (+11/-4)
tests/unit-tests/graphics/android/test_display_buffer.cpp (+12/-35)
tests/unit-tests/graphics/android/test_display_group.cpp (+85/-0)
tests/unit-tests/graphics/android/test_fb_device.cpp (+3/-2)
tests/unit-tests/graphics/android/test_hwc_configuration.cpp (+15/-0)
tests/unit-tests/graphics/android/test_hwc_device.cpp (+72/-23)
tests/unit-tests/graphics/android/test_hwc_fb_device.cpp (+2/-1)
To merge this branch: bzr merge lp:~kdub/mir/android-multimonitor
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Alexandros Frantzis (community) Approve
Alan Griffiths Approve
Review via email: mp+250617@code.launchpad.net

Commit message

android: post to the external display over MHL/Slimport when present.

Description of the change

android: post to the external display over MHL/Slimport when present.

Last branch in the android multimonitor line of work!

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

I'm not set up to test the code, but it looks reasonable[1].

[1] That is reasonable apart from the pre-existing question of why we have this primary + (optional) external assumption rather than a list of polymorphic things.

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

> [1] That is reasonable apart from the pre-existing question of why we have
> this primary + (optional) external assumption rather than a list of
> polymorphic things.

Assuming you mean in some of the internals of the android classes, this is the next thing to sort out in a clean up pass.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

139 + if (config.external().connected)
140 + displays.add(mga::DisplayName::external,
141 + create_display_buffer(
142 + display_device,
143 + mga::DisplayName::external,
144 + *display_buffer_builder,
145 + external_attribs,
146 + gl_program_factory,
147 + gl_context,
148 + mga::OverlayOptimization::disabled));

Should we be creating a new display buffer every time we call for_each_display_sync_group() with a connected external screen? I would expect that we would only create the display buffer only if we don't already have one.

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

@alf, good catch, it was wasteful to create the object every time.

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

> @alf, good catch, it was wasteful to create the object every time.
Ah, also there's some reshuffling of the display configuration object's dependencies that are needed as follow-up/clean-up. (such as removing external/primary designations where we can, and merging the DisplayGroups and the configuration)

Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

Looks good.

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
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/platforms/android/server/CMakeLists.txt'
2--- src/platforms/android/server/CMakeLists.txt 2015-02-20 12:11:25 +0000
3+++ src/platforms/android/server/CMakeLists.txt 2015-03-02 14:38:17 +0000
4@@ -17,6 +17,7 @@
5 android_buffer_allocator.cpp
6 buffer.cpp
7 display.cpp
8+ display_group.cpp
9 display_configuration.cpp
10 display_buffer.cpp
11 hal_component_factory.cpp
12
13=== modified file 'src/platforms/android/server/configurable_display_buffer.h'
14--- src/platforms/android/server/configurable_display_buffer.h 2015-02-26 03:20:09 +0000
15+++ src/platforms/android/server/configurable_display_buffer.h 2015-03-02 14:38:17 +0000
16@@ -19,9 +19,8 @@
17 #ifndef MIR_GRAPHICS_ANDROID_CONFIGURABLE_DISPLAY_BUFFER_H_
18 #define MIR_GRAPHICS_ANDROID_CONFIGURABLE_DISPLAY_BUFFER_H_
19
20-#include "mir/graphics/display.h"
21 #include "mir/graphics/display_buffer.h"
22-#include "mir/graphics/display_configuration.h"
23+#include "display_device.h"
24
25 namespace mir
26 {
27@@ -30,12 +29,12 @@
28 namespace android
29 {
30
31-//TODO: break this dependency, android displaybuffers shouldn't be their own DisplaySyncGroups
32-class ConfigurableDisplayBuffer : public graphics::DisplayBuffer,
33- public graphics::DisplaySyncGroup
34+class ConfigurableDisplayBuffer : public graphics::DisplayBuffer
35 {
36 public:
37 virtual void configure(MirPowerMode power_mode, MirOrientation orientation) = 0;
38+ virtual DisplayContents contents() = 0;
39+ virtual MirPowerMode power_mode() const = 0;
40 };
41
42 }
43
44=== modified file 'src/platforms/android/server/display.cpp'
45--- src/platforms/android/server/display.cpp 2015-02-26 03:20:09 +0000
46+++ src/platforms/android/server/display.cpp 2015-03-02 14:38:17 +0000
47@@ -147,30 +147,33 @@
48 mir_power_mode_off),
49 gl_context{config.primary().current_format, *gl_config, *display_report},
50 display_device(display_buffer_builder->create_display_device()),
51- primary_db{create_display_buffer(
52- display_device,
53- mga::DisplayName::primary,
54- *display_buffer_builder,
55- primary_attribs,
56- gl_program_factory,
57- gl_context,
58- overlay_option)},
59 display_change_pipe(new DisplayChangePipe),
60- gl_program_factory(gl_program_factory)
61-{
62- //Some drivers (depending on kernel state) incorrectly report an error code indicating that the display is already on. Ignore the first failure.
63- set_powermode_all_displays(*hwc_config, config, mir_power_mode_on);
64-
65- if (config.external().connected)
66- {
67- external_db = create_display_buffer(
68+ gl_program_factory(gl_program_factory),
69+ displays(
70+ display_device,
71+ create_display_buffer(
72 display_device,
73- mga::DisplayName::external,
74+ mga::DisplayName::primary,
75 *display_buffer_builder,
76- external_attribs,
77+ primary_attribs,
78 gl_program_factory,
79 gl_context,
80- mga::OverlayOptimization::disabled);
81+ overlay_option))
82+{
83+ //Some drivers (depending on kernel state) incorrectly report an error code indicating that the display is already on. Ignore the first failure.
84+ set_powermode_all_displays(*hwc_config, config, mir_power_mode_on);
85+
86+ if (config.external().connected)
87+ {
88+ displays.add(mga::DisplayName::external,
89+ create_display_buffer(
90+ display_device,
91+ mga::DisplayName::external,
92+ *display_buffer_builder,
93+ external_attribs,
94+ gl_program_factory,
95+ gl_context,
96+ mga::OverlayOptimization::disabled));
97 }
98
99 display_report->report_successful_setup_of_native_resources();
100@@ -190,8 +193,8 @@
101 {
102 if (configuration_dirty)
103 {
104- auto attribs = hwc_config->active_attribs_for(mga::DisplayName::external);
105- if (attribs.connected)
106+ external_attribs = hwc_config->active_attribs_for(mga::DisplayName::external);
107+ if (external_attribs.connected)
108 power_mode(mga::DisplayName::external, *hwc_config, config.external(), mir_power_mode_on);
109 else
110 config.external().power_mode = mir_power_mode_off;
111@@ -199,34 +202,30 @@
112 config = mga::DisplayConfiguration(
113 hwc_config->active_attribs_for(mga::DisplayName::primary),
114 config.primary().power_mode,
115- attribs,
116+ external_attribs,
117 config.external().power_mode);
118 configuration_dirty = false;
119-
120- if (config.external().connected)
121- external_db = create_display_buffer(
122- display_device,
123- mga::DisplayName::external,
124- *display_buffer_builder,
125- attribs,
126- gl_program_factory,
127- gl_context,
128- mga::OverlayOptimization::disabled);
129- else
130- external_db.reset();
131 }
132-
133 }
134
135 void mga::Display::for_each_display_sync_group(std::function<void(mg::DisplaySyncGroup&)> const& f)
136 {
137 std::lock_guard<decltype(configuration_mutex)> lock{configuration_mutex};
138 update_configuration(lock);
139+ if ((config.external().connected) && !displays.display_present(mga::DisplayName::external))
140+ displays.add(mga::DisplayName::external,
141+ create_display_buffer(
142+ display_device,
143+ mga::DisplayName::external,
144+ *display_buffer_builder,
145+ external_attribs,
146+ gl_program_factory,
147+ gl_context,
148+ mga::OverlayOptimization::disabled));
149+ if ((!config.external().connected) && displays.display_present(mga::DisplayName::external))
150+ displays.remove(mga::DisplayName::external);
151
152- if (external_db && config.external().power_mode == mir_power_mode_on)
153- f(*external_db);
154- if (config.primary().power_mode == mir_power_mode_on)
155- f(*primary_db);
156+ f(displays);
157 }
158
159 std::unique_ptr<mg::DisplayConfiguration> mga::Display::configuration() const
160@@ -252,12 +251,12 @@
161 if (config.primary().id == output.id)
162 {
163 power_mode(mga::DisplayName::primary, *hwc_config, config.primary(), output.power_mode);
164- primary_db->configure(output.power_mode, output.orientation);
165+ displays.configure(mga::DisplayName::primary, output.power_mode, output.orientation);
166 }
167 else if (config.external().connected)
168 {
169 power_mode(mga::DisplayName::external, *hwc_config, config.external(), output.power_mode);
170- if (external_db) external_db->configure(output.power_mode, output.orientation);
171+ displays.configure(mga::DisplayName::external, output.power_mode, output.orientation);
172 }
173 });
174 }
175
176=== modified file 'src/platforms/android/server/display.h'
177--- src/platforms/android/server/display.h 2015-02-26 03:20:09 +0000
178+++ src/platforms/android/server/display.h 2015-03-02 14:38:17 +0000
179@@ -21,6 +21,7 @@
180
181 #include "mir/graphics/display.h"
182 #include "gl_context.h"
183+#include "display_group.h"
184 #include "hwc_configuration.h"
185 #include "display_configuration.h"
186 #include "overlay_optimization.h"
187@@ -86,14 +87,13 @@
188 std::unique_ptr<HwcConfiguration> const hwc_config;
189 ConfigChangeSubscription const hotplug_subscription;
190 DisplayAttribs const primary_attribs; //TODO: could be removed, really only useful in construction
191- DisplayAttribs const external_attribs; //TODO: could be removed, really only useful in construction
192+ DisplayAttribs mutable external_attribs; //TODO: could be removed, really only useful in construction
193 DisplayConfiguration mutable config;
194 PbufferGLContext gl_context;
195 std::shared_ptr<DisplayDevice> display_device;
196- std::unique_ptr<ConfigurableDisplayBuffer> const primary_db;
197- std::unique_ptr<ConfigurableDisplayBuffer> mutable external_db;
198 std::unique_ptr<DisplayChangePipe> display_change_pipe;
199 std::shared_ptr<GLProgramFactory> const gl_program_factory;
200+ DisplayGroup mutable displays;
201
202 void update_configuration(std::lock_guard<decltype(configuration_mutex)> const&) const;
203 };
204
205=== modified file 'src/platforms/android/server/display_buffer.cpp'
206--- src/platforms/android/server/display_buffer.cpp 2015-02-26 03:20:09 +0000
207+++ src/platforms/android/server/display_buffer.cpp 2015-03-02 14:38:17 +0000
208@@ -49,7 +49,8 @@
209 gl_context{shared_gl_context, fb_bundle, native_window},
210 overlay_program{program_factory, gl_context, geom::Rectangle{{0,0},fb_bundle->fb_size()}},
211 overlay_enabled{overlay_option == mga::OverlayOptimization::enabled},
212- orientation_{orientation}
213+ orientation_{orientation},
214+ power_mode_{mir_power_mode_on}
215 {
216 }
217
218@@ -88,14 +89,12 @@
219 if (!needs_commit)
220 return false;
221
222- display_device->commit(display_name, *layer_list, gl_context, overlay_program);
223 return true;
224 }
225
226 void mga::DisplayBuffer::gl_swap_buffers()
227 {
228 layer_list->update_list({});
229- display_device->commit(display_name, *layer_list, gl_context, overlay_program);
230 }
231
232 MirOrientation mga::DisplayBuffer::orientation() const
233@@ -114,18 +113,20 @@
234 return false;
235 }
236
237-void mga::DisplayBuffer::for_each_display_buffer(std::function<void(mg::DisplayBuffer&)> const& f)
238-{
239- f(*this);
240-}
241-
242-void mga::DisplayBuffer::post()
243-{
244-}
245-
246 void mga::DisplayBuffer::configure(MirPowerMode power_mode, MirOrientation orientation)
247 {
248- if (power_mode != mir_power_mode_on)
249+ power_mode_ = power_mode;
250+ if (power_mode_ != mir_power_mode_on)
251 display_device->content_cleared();
252 orientation_ = orientation;
253 }
254+
255+mga::DisplayContents mga::DisplayBuffer::contents()
256+{
257+ return mga::DisplayContents{display_name, *layer_list, gl_context, overlay_program};
258+}
259+
260+MirPowerMode mga::DisplayBuffer::power_mode() const
261+{
262+ return power_mode_;
263+}
264
265=== modified file 'src/platforms/android/server/display_buffer.h'
266--- src/platforms/android/server/display_buffer.h 2015-02-26 03:20:09 +0000
267+++ src/platforms/android/server/display_buffer.h 2015-03-02 14:38:17 +0000
268@@ -61,12 +61,11 @@
269 void gl_swap_buffers() override;
270 bool post_renderables_if_optimizable(RenderableList const& renderlist) override;
271
272- void for_each_display_buffer(std::function<void(graphics::DisplayBuffer&)> const& f) override;
273- void post() override;
274-
275 MirOrientation orientation() const override;
276 bool uses_alpha() const override;
277 void configure(MirPowerMode power_mode, MirOrientation orientation) override;
278+ DisplayContents contents() override;
279+ MirPowerMode power_mode() const override;
280 private:
281 DisplayName display_name;
282 std::unique_ptr<LayerList> layer_list;
283@@ -77,6 +76,7 @@
284 HWCFallbackGLRenderer overlay_program;
285 bool overlay_enabled;
286 MirOrientation orientation_;
287+ MirPowerMode power_mode_;
288 };
289
290 }
291
292=== modified file 'src/platforms/android/server/display_device.h'
293--- src/platforms/android/server/display_device.h 2015-02-26 03:20:09 +0000
294+++ src/platforms/android/server/display_device.h 2015-03-02 14:38:17 +0000
295@@ -23,6 +23,7 @@
296 #include "mir_toolkit/common.h"
297 #include "display_name.h"
298 #include <EGL/egl.h>
299+#include <list>
300
301 namespace mir
302 {
303@@ -37,6 +38,14 @@
304 class SwappingGLContext;
305 class LayerList;
306
307+struct DisplayContents
308+{
309+ DisplayName name;
310+ LayerList& list;
311+ SwappingGLContext& context;
312+ RenderableListCompositor& compositor;
313+};
314+
315 class DisplayDevice
316 {
317 public:
318@@ -50,11 +59,7 @@
319 /* post the layer list to the display, optionally drawing using the context/compositor if
320 * instructed to by the driver
321 */
322- virtual void commit(
323- DisplayName display_name,
324- LayerList& layer_list,
325- SwappingGLContext const& context,
326- RenderableListCompositor const& compositor) = 0;
327+ virtual void commit(std::list<DisplayContents> const& contents) = 0;
328
329 //notify the DisplayDevice that the screen content was cleared in a way other than the above fns
330 virtual void content_cleared() = 0;
331
332=== added file 'src/platforms/android/server/display_group.cpp'
333--- src/platforms/android/server/display_group.cpp 1970-01-01 00:00:00 +0000
334+++ src/platforms/android/server/display_group.cpp 2015-03-02 14:38:17 +0000
335@@ -0,0 +1,81 @@
336+/*
337+ * Copyright © 2015 Canonical Ltd.
338+ *
339+ * This program is free software: you can redistribute it and/or modify it
340+ * under the terms of the GNU Lesser General Public License version 3,
341+ * as published by the Free Software Foundation.
342+ *
343+ * This program is distributed in the hope that it will be useful,
344+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
345+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
346+ * GNU Lesser General Public License for more details.
347+ *
348+ * You should have received a copy of the GNU Lesser General Public License
349+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
350+ *
351+ * Authored by: Kevin DuBois <kevin.dubois@canonical.com>
352+ */
353+
354+#include "display_group.h"
355+#include "configurable_display_buffer.h"
356+#include <boost/throw_exception.hpp>
357+#include <stdexcept>
358+
359+namespace mg = mir::graphics;
360+namespace mga = mir::graphics::android;
361+
362+mga::DisplayGroup::DisplayGroup(
363+ std::shared_ptr<mga::DisplayDevice> const& device,
364+ std::unique_ptr<mga::ConfigurableDisplayBuffer> primary_buffer) :
365+ device(device)
366+{
367+ dbs.emplace(std::make_pair(mga::DisplayName::primary, std::move(primary_buffer)));
368+}
369+
370+void mga::DisplayGroup::for_each_display_buffer(std::function<void(mg::DisplayBuffer&)> const& f)
371+{
372+ std::unique_lock<decltype(guard)> lk(guard);
373+ for(auto const& db : dbs)
374+ if (db.second->power_mode() != mir_power_mode_off)
375+ f(*db.second);
376+}
377+
378+void mga::DisplayGroup::add(DisplayName name, std::unique_ptr<ConfigurableDisplayBuffer> buffer)
379+{
380+ std::unique_lock<decltype(guard)> lk(guard);
381+ dbs.emplace(std::make_pair(name, std::move(buffer)));
382+}
383+
384+void mga::DisplayGroup::remove(DisplayName name)
385+{
386+ if (name == mga::DisplayName::primary)
387+ BOOST_THROW_EXCEPTION(std::logic_error("cannot remove primary display"));
388+
389+ std::unique_lock<decltype(guard)> lk(guard);
390+ auto it = dbs.find(name);
391+ if (it != dbs.end())
392+ dbs.erase(it);
393+}
394+
395+bool mga::DisplayGroup::display_present(DisplayName name) const
396+{
397+ std::unique_lock<decltype(guard)> lk(guard);
398+ return (dbs.end() != dbs.find(name));
399+}
400+
401+void mga::DisplayGroup::configure(DisplayName name, MirPowerMode mode, MirOrientation orientation)
402+{
403+ std::unique_lock<decltype(guard)> lk(guard);
404+ auto it = dbs.find(name);
405+ if (it != dbs.end())
406+ it->second->configure(mode, orientation);
407+}
408+
409+void mga::DisplayGroup::post()
410+{
411+ std::list<DisplayContents> contents;
412+ std::unique_lock<decltype(guard)> lk(guard);
413+ for(auto const& db : dbs)
414+ contents.emplace_back(db.second->contents());
415+ device->commit(contents);
416+}
417
418=== added file 'src/platforms/android/server/display_group.h'
419--- src/platforms/android/server/display_group.h 1970-01-01 00:00:00 +0000
420+++ src/platforms/android/server/display_group.h 2015-03-02 14:38:17 +0000
421@@ -0,0 +1,62 @@
422+/*
423+ * Copyright © 2015 Canonical Ltd.
424+ *
425+ * This program is free software: you can redistribute it and/or modify it
426+ * under the terms of the GNU Lesser General Public License version 3,
427+ * as published by the Free Software Foundation.
428+ *
429+ * This program is distributed in the hope that it will be useful,
430+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
431+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
432+ * GNU Lesser General Public License for more details.
433+ *
434+ * You should have received a copy of the GNU Lesser General Public License
435+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
436+ *
437+ * Authored by: Kevin DuBois <kevin.dubois@canonical.com>
438+ */
439+
440+#ifndef MIR_GRAPHICS_ANDROID_DISPLAY_GROUP_H_
441+#define MIR_GRAPHICS_ANDROID_DISPLAY_GROUP_H_
442+
443+#include "mir_toolkit/common.h"
444+#include "mir/graphics/display.h"
445+#include "display_name.h"
446+#include <map>
447+#include <mutex>
448+
449+namespace mir
450+{
451+namespace graphics
452+{
453+namespace android
454+{
455+class ConfigurableDisplayBuffer;
456+class DisplayDevice;
457+
458+class DisplayGroup : public graphics::DisplaySyncGroup
459+{
460+public:
461+ DisplayGroup(
462+ std::shared_ptr<DisplayDevice> const& device,
463+ std::unique_ptr<ConfigurableDisplayBuffer> primary_buffer);
464+
465+ void for_each_display_buffer(std::function<void(graphics::DisplayBuffer&)> const& f) override;
466+ void post() override;
467+
468+ void add(DisplayName name, std::unique_ptr<ConfigurableDisplayBuffer> buffer);
469+ void remove(DisplayName name);
470+ void configure(DisplayName name, MirPowerMode, MirOrientation);
471+ bool display_present(DisplayName name) const;
472+
473+private:
474+ std::mutex mutable guard;
475+ std::shared_ptr<DisplayDevice> const device;
476+ std::map<DisplayName, std::unique_ptr<ConfigurableDisplayBuffer>> dbs;
477+};
478+
479+}
480+}
481+}
482+
483+#endif /* MIR_GRAPHICS_ANDROID_DISPLAY_GROUP_H_ */
484
485=== modified file 'src/platforms/android/server/fb_device.cpp'
486--- src/platforms/android/server/fb_device.cpp 2015-02-26 03:20:09 +0000
487+++ src/platforms/android/server/fb_device.cpp 2015-03-02 14:38:17 +0000
488@@ -28,6 +28,7 @@
489
490 #include <boost/throw_exception.hpp>
491 #include <stdexcept>
492+#include <algorithm>
493
494 namespace mg = mir::graphics;
495 namespace mga=mir::graphics::android;
496@@ -77,12 +78,15 @@
497 {
498 }
499
500-void mga::FBDevice::commit(
501- DisplayName,
502- LayerList&,
503- SwappingGLContext const& context,
504- RenderableListCompositor const&)
505+void mga::FBDevice::commit(std::list<DisplayContents> const& contents)
506 {
507+ auto primary_contents = std::find_if(contents.begin(), contents.end(),
508+ [](mga::DisplayContents const& c) {
509+ return (c.name == mga::DisplayName::primary);
510+ });
511+ if (primary_contents == contents.end()) return;
512+ auto& context = primary_contents->context;
513+
514 context.swap_buffers();
515 auto const& buffer = context.last_rendered_buffer();
516 auto native_buffer = buffer->native_buffer_handle();
517
518=== modified file 'src/platforms/android/server/fb_device.h'
519--- src/platforms/android/server/fb_device.h 2015-02-26 03:20:09 +0000
520+++ src/platforms/android/server/fb_device.h 2015-03-02 14:38:17 +0000
521@@ -48,11 +48,7 @@
522 FBDevice(std::shared_ptr<framebuffer_device_t> const& fbdev);
523
524 bool compatible_renderlist(RenderableList const& renderlist) override;
525- void commit(
526- DisplayName,
527- LayerList&,
528- SwappingGLContext const& context,
529- RenderableListCompositor const& list_compositor) override;
530+ void commit(std::list<DisplayContents> const& contents) override;
531
532 private:
533 std::shared_ptr<framebuffer_device_t> const fb_device;
534
535=== modified file 'src/platforms/android/server/hwc_blanking_control.cpp'
536--- src/platforms/android/server/hwc_blanking_control.cpp 2015-02-13 06:12:34 +0000
537+++ src/platforms/android/server/hwc_blanking_control.cpp 2015-03-02 14:38:17 +0000
538@@ -18,6 +18,7 @@
539
540 #include "hwc_configuration.h"
541 #include "hwc_wrapper.h"
542+#include "mir/raii.h"
543 #include "android_format_conversion-inl.h"
544 #include <EGL/egl.h>
545 #include <EGL/eglext.h>
546@@ -145,7 +146,17 @@
547 }
548
549 mga::ConfigChangeSubscription mga::HwcBlankingControl::subscribe_to_config_changes(
550- std::function<void()> const&)
551+ std::function<void()> const& hotplug)
552 {
553- return nullptr;
554+ return std::make_shared<
555+ mir::raii::PairedCalls<std::function<void()>, std::function<void()>>>(
556+ [hotplug, this]{
557+ hwc_device->subscribe_to_events(this,
558+ [](DisplayName, std::chrono::nanoseconds){},
559+ [hotplug](DisplayName, bool){ hotplug(); },
560+ []{});
561+ },
562+ [this]{
563+ hwc_device->unsubscribe_from_events(this);
564+ });
565 }
566
567=== modified file 'src/platforms/android/server/hwc_device.cpp'
568--- src/platforms/android/server/hwc_device.cpp 2015-02-26 03:20:09 +0000
569+++ src/platforms/android/server/hwc_device.cpp 2015-03-02 14:38:17 +0000
570@@ -24,6 +24,7 @@
571 #include "framebuffer_bundle.h"
572 #include "buffer.h"
573 #include "hwc_fallback_gl_renderer.h"
574+#include "mir/raii.h"
575 #include <limits>
576 #include <algorithm>
577
578@@ -79,47 +80,62 @@
579 return it != onscreen_overlay_buffers.end();
580 }
581
582-void mga::HwcDevice::commit(
583- mga::DisplayName,
584- mga::LayerList& hwc_list,
585- SwappingGLContext const& context,
586- RenderableListCompositor const& list_compositor)
587+void mga::HwcDevice::commit(std::list<DisplayContents> const& contents)
588 {
589- hwc_list.setup_fb(context.last_rendered_buffer());
590-
591- hwc_wrapper->prepare({{hwc_list.native_list(), nullptr, nullptr}});
592-
593- if (hwc_list.needs_swapbuffers())
594- {
595- auto rejected_renderables = hwc_list.rejected_renderables();
596- if (rejected_renderables.empty())
597- context.swap_buffers();
598- else
599- list_compositor.render(std::move(rejected_renderables), context);
600- hwc_list.setup_fb(context.last_rendered_buffer());
601- hwc_list.swap_occurred();
602- }
603-
604- //setup overlays
605+ std::array<hwc_display_contents_1*, HWC_NUM_DISPLAY_TYPES> lists{{ nullptr, nullptr, nullptr }};
606 std::vector<std::shared_ptr<mg::Buffer>> next_onscreen_overlay_buffers;
607- for (auto& layer : hwc_list)
608- {
609- auto buffer = layer.layer.buffer();
610- if (layer.layer.is_overlay() && buffer)
611- {
612- if (!buffer_is_onscreen(*buffer))
613- layer.layer.set_acquirefence();
614- next_onscreen_overlay_buffers.push_back(buffer);
615- }
616- }
617-
618- hwc_wrapper->set({{hwc_list.native_list(), nullptr, nullptr}});
619+
620+ for (auto& content : contents)
621+ {
622+ if (content.name == mga::DisplayName::primary)
623+ lists[HWC_DISPLAY_PRIMARY] = content.list.native_list();
624+ else if (content.name == mga::DisplayName::external)
625+ lists[HWC_DISPLAY_EXTERNAL] = content.list.native_list();
626+
627+ content.list.setup_fb(content.context.last_rendered_buffer());
628+ }
629+
630+ hwc_wrapper->prepare(lists);
631+
632+ for (auto& content : contents)
633+ {
634+ if (content.list.needs_swapbuffers())
635+ {
636+ auto rejected_renderables = content.list.rejected_renderables();
637+ auto current_context = mir::raii::paired_calls(
638+ [&]{ content.context.make_current(); },
639+ [&]{ content.context.release_current(); });
640+ if (rejected_renderables.empty())
641+ content.context.swap_buffers();
642+ else
643+ content.compositor.render(std::move(rejected_renderables), content.context);
644+ content.list.setup_fb(content.context.last_rendered_buffer());
645+ content.list.swap_occurred();
646+ }
647+
648+ //setup overlays
649+ for (auto& layer : content.list)
650+ {
651+ auto buffer = layer.layer.buffer();
652+ if (layer.layer.is_overlay() && buffer)
653+ {
654+ if (!buffer_is_onscreen(*buffer))
655+ layer.layer.set_acquirefence();
656+ next_onscreen_overlay_buffers.push_back(buffer);
657+ }
658+ }
659+ }
660+
661+ hwc_wrapper->set(lists);
662 onscreen_overlay_buffers = std::move(next_onscreen_overlay_buffers);
663
664- for (auto& it : hwc_list)
665- it.layer.release_buffer();
666+ for (auto& content : contents)
667+ {
668+ for (auto& it : content.list)
669+ it.layer.release_buffer();
670
671- mir::Fd retire_fd(hwc_list.retirement_fence());
672+ mir::Fd retire_fd(content.list.retirement_fence());
673+ }
674 }
675
676 void mga::HwcDevice::content_cleared()
677
678=== modified file 'src/platforms/android/server/hwc_device.h'
679--- src/platforms/android/server/hwc_device.h 2015-02-26 03:20:09 +0000
680+++ src/platforms/android/server/hwc_device.h 2015-03-02 14:38:17 +0000
681@@ -44,11 +44,7 @@
682 HwcDevice(std::shared_ptr<HwcWrapper> const& hwc_wrapper);
683
684 bool compatible_renderlist(RenderableList const& renderlist) override;
685- void commit(
686- DisplayName,
687- LayerList&,
688- SwappingGLContext const& context,
689- RenderableListCompositor const& list_compositor) override;
690+ void commit(std::list<DisplayContents> const& contents) override;
691 void content_cleared() override;
692
693 private:
694
695=== modified file 'src/platforms/android/server/hwc_fb_device.cpp'
696--- src/platforms/android/server/hwc_fb_device.cpp 2015-02-26 03:20:09 +0000
697+++ src/platforms/android/server/hwc_fb_device.cpp 2015-03-02 14:38:17 +0000
698@@ -30,6 +30,7 @@
699 #include <boost/throw_exception.hpp>
700 #include <sstream>
701 #include <stdexcept>
702+#include <algorithm>
703
704 namespace mg = mir::graphics;
705 namespace mga = mir::graphics::android;
706@@ -55,12 +56,16 @@
707 {
708 }
709
710-void mga::HwcFbDevice::commit(
711- mga::DisplayName,
712- mga::LayerList& layer_list,
713- SwappingGLContext const& context,
714- RenderableListCompositor const&)
715+void mga::HwcFbDevice::commit(std::list<DisplayContents> const& contents)
716 {
717+ auto primary_contents = std::find_if(contents.begin(), contents.end(),
718+ [](mga::DisplayContents const& c) {
719+ return (c.name == mga::DisplayName::primary);
720+ });
721+ if (primary_contents == contents.end()) return;
722+ auto& layer_list = primary_contents->list;
723+ auto& context = primary_contents->context;
724+
725 layer_list.setup_fb(context.last_rendered_buffer());
726
727 if (auto display_list = layer_list.native_list())
728
729=== modified file 'src/platforms/android/server/hwc_fb_device.h'
730--- src/platforms/android/server/hwc_fb_device.h 2015-02-26 03:20:09 +0000
731+++ src/platforms/android/server/hwc_fb_device.h 2015-03-02 14:38:17 +0000
732@@ -42,11 +42,7 @@
733 std::shared_ptr<framebuffer_device_t> const& fb_device);
734
735 bool compatible_renderlist(RenderableList const& renderlist) override;
736- void commit(
737- DisplayName,
738- LayerList&,
739- SwappingGLContext const& context,
740- RenderableListCompositor const& list_compositor) override;
741+ void commit(std::list<DisplayContents> const& contents) override;
742
743 private:
744 void content_cleared() override;
745
746=== modified file 'src/platforms/android/server/swapping_gl_context.h'
747--- src/platforms/android/server/swapping_gl_context.h 2015-02-26 03:20:09 +0000
748+++ src/platforms/android/server/swapping_gl_context.h 2015-03-02 14:38:17 +0000
749@@ -32,6 +32,8 @@
750 {
751 public:
752 virtual ~SwappingGLContext() = default;
753+ virtual void make_current() const = 0;
754+ virtual void release_current() const = 0;
755 virtual void swap_buffers() const = 0;
756 virtual std::shared_ptr<Buffer> last_rendered_buffer() const = 0;
757
758
759=== modified file 'tests/include/mir_test_doubles/mock_display_device.h'
760--- tests/include/mir_test_doubles/mock_display_device.h 2015-02-26 03:20:09 +0000
761+++ tests/include/mir_test_doubles/mock_display_device.h 2015-03-02 14:38:17 +0000
762@@ -37,11 +37,7 @@
763 public:
764 ~MockDisplayDevice() noexcept {}
765 MOCK_METHOD0(content_cleared, void());
766- MOCK_METHOD4(commit, void(
767- graphics::android::DisplayName,
768- graphics::android::LayerList&,
769- graphics::android::SwappingGLContext const&,
770- graphics::android::RenderableListCompositor const&));
771+ MOCK_METHOD1(commit, void(std::list<graphics::android::DisplayContents> const&));
772 MOCK_METHOD1(compatible_renderlist, bool(
773 graphics::RenderableList const&));
774 };
775
776=== modified file 'tests/include/mir_test_doubles/mock_swapping_gl_context.h'
777--- tests/include/mir_test_doubles/mock_swapping_gl_context.h 2015-02-26 03:20:09 +0000
778+++ tests/include/mir_test_doubles/mock_swapping_gl_context.h 2015-03-02 14:38:17 +0000
779@@ -31,6 +31,8 @@
780 struct MockSwappingGLContext : public graphics::android::SwappingGLContext
781 {
782 MOCK_CONST_METHOD0(swap_buffers, void());
783+ MOCK_CONST_METHOD0(make_current, void());
784+ MOCK_CONST_METHOD0(release_current, void());
785 MOCK_CONST_METHOD0(last_rendered_buffer, std::shared_ptr<graphics::Buffer>());
786 };
787
788
789=== modified file 'tests/include/mir_test_doubles/stub_swapping_gl_context.h'
790--- tests/include/mir_test_doubles/stub_swapping_gl_context.h 2015-02-26 03:20:09 +0000
791+++ tests/include/mir_test_doubles/stub_swapping_gl_context.h 2015-03-02 14:38:17 +0000
792@@ -40,6 +40,8 @@
793 StubSwappingGLContext(std::make_shared<StubBuffer>())
794 {
795 }
796+ void make_current() const {}
797+ void release_current() const {}
798 void swap_buffers() const {}
799 std::shared_ptr<graphics::Buffer> last_rendered_buffer() const
800 {
801
802=== modified file 'tests/unit-tests/graphics/android/CMakeLists.txt'
803--- tests/unit-tests/graphics/android/CMakeLists.txt 2015-02-13 06:12:34 +0000
804+++ tests/unit-tests/graphics/android/CMakeLists.txt 2015-03-02 14:38:17 +0000
805@@ -5,6 +5,7 @@
806 ${CMAKE_CURRENT_SOURCE_DIR}/test_android_buffer_allocator.cpp
807 ${CMAKE_CURRENT_SOURCE_DIR}/test_buffer_tex_bind.cpp
808 ${CMAKE_CURRENT_SOURCE_DIR}/test_display.cpp
809+ ${CMAKE_CURRENT_SOURCE_DIR}/test_display_group.cpp
810 ${CMAKE_CURRENT_SOURCE_DIR}/test_android_alloc_adaptor.cpp
811 ${CMAKE_CURRENT_SOURCE_DIR}/test_android_buffer_allocator.cpp
812 ${CMAKE_CURRENT_SOURCE_DIR}/test_hwc_device.cpp
813
814=== modified file 'tests/unit-tests/graphics/android/hwc_struct_helpers.h'
815--- tests/unit-tests/graphics/android/hwc_struct_helpers.h 2015-02-26 03:20:09 +0000
816+++ tests/unit-tests/graphics/android/hwc_struct_helpers.h 2015-03-02 14:38:17 +0000
817@@ -108,23 +108,36 @@
818 return !(::testing::Test::HasFailure());
819 }
820
821-MATCHER_P(MatchesPrimaryList, value, std::string(""))
822+MATCHER_P(MatchesList, value, std::string(""))
823 {
824- if (arg[0] == nullptr)
825+ if (arg == nullptr)
826 return (value.empty());
827- auto const& primary_list = *arg[0];
828+ auto const& list = *arg;
829
830- EXPECT_EQ(primary_list.numHwLayers, value.size());
831+ EXPECT_EQ(list.numHwLayers, value.size());
832 auto i = 0u;
833 for(auto layer : value)
834 {
835- EXPECT_THAT(primary_list.hwLayers[i++], MatchesLegacyLayer(*layer));
836+ EXPECT_THAT(list.hwLayers[i++], MatchesLegacyLayer(*layer));
837 if (::testing::Test::HasFailure())
838 return false;
839 }
840 return !(::testing::Test::HasFailure());
841 }
842
843+MATCHER_P(MatchesPrimaryList, value, std::string(""))
844+{
845+ EXPECT_THAT(arg[0], MatchesList(value));
846+ return !(::testing::Test::HasFailure());
847+}
848+
849+MATCHER_P2(MatchesLists, primary, external, std::string(""))
850+{
851+ EXPECT_THAT(arg[0], MatchesList(primary));
852+ EXPECT_THAT(arg[1], MatchesList(external));
853+ return !(::testing::Test::HasFailure());
854+}
855+
856 MATCHER_P3(MatchesListWithEglFields, value, dpy, sur, std::string(""))
857 {
858 if (arg[0] == nullptr)
859
860=== modified file 'tests/unit-tests/graphics/android/test_display.cpp'
861--- tests/unit-tests/graphics/android/test_display.cpp 2015-02-26 03:20:09 +0000
862+++ tests/unit-tests/graphics/android/test_display.cpp 2015-03-02 14:38:17 +0000
863@@ -656,28 +656,35 @@
864 null_display_report,
865 mga::OverlayOptimization::enabled);
866
867- auto group_count = 0;
868- auto db_group_counter = [&](mg::DisplaySyncGroup&) {
869+ auto group_count = 0;
870+ auto db_count = 0;
871+ auto db_group_counter = [&](mg::DisplaySyncGroup& group) {
872 group_count++;
873+ group.for_each_display_buffer([&](mg::DisplayBuffer&) {db_count++;});
874 };
875 display.for_each_display_sync_group(db_group_counter);
876- EXPECT_THAT(group_count, Eq(2));
877+ EXPECT_THAT(group_count, Eq(1));
878+ EXPECT_THAT(db_count, Eq(2));
879
880 //hotplug external away
881 external_connected = false;
882 hotplug_fn();
883
884 group_count = 0;
885+ db_count = 0;
886 display.for_each_display_sync_group(db_group_counter);
887 EXPECT_THAT(group_count, Eq(1));
888+ EXPECT_THAT(db_count, Eq(1));
889
890 //hotplug external back
891 external_connected = true;
892 hotplug_fn();
893
894 group_count = 0;
895+ db_count = 0;
896 display.for_each_display_sync_group(db_group_counter);
897- EXPECT_THAT(group_count, Eq(2));
898+ EXPECT_THAT(group_count, Eq(1));
899+ EXPECT_THAT(db_count, Eq(2));
900 }
901
902 TEST_F(Display, turns_external_display_on_with_hotplug)
903
904=== modified file 'tests/unit-tests/graphics/android/test_display_buffer.cpp'
905--- tests/unit-tests/graphics/android/test_display_buffer.cpp 2015-02-26 03:20:09 +0000
906+++ tests/unit-tests/graphics/android/test_display_buffer.cpp 2015-03-02 14:38:17 +0000
907@@ -85,27 +85,6 @@
908 };
909 }
910
911-TEST_F(DisplayBuffer, can_post_update_with_gl_only)
912-{
913- using namespace testing;
914- mga::DisplayName external{mga::DisplayName::external};
915- std::unique_ptr<mga::LayerList> list(new mga::LayerList(std::make_shared<mga::IntegerSourceCrop>(), {}));
916- EXPECT_CALL(*mock_display_device, commit(external, Ref(*list), _, _));
917-
918- mga::DisplayBuffer db{
919- external,
920- std::move(list),
921- mock_fb_bundle,
922- mock_display_device,
923- native_window,
924- *gl_context,
925- stub_program_factory,
926- orientation,
927- mga::OverlayOptimization::enabled};
928-
929- db.gl_swap_buffers();
930-}
931-
932 TEST_F(DisplayBuffer, posts_overlay_list_returns_display_device_decision)
933 {
934 using namespace testing;
935@@ -295,30 +274,28 @@
936
937 ON_CALL(*mock_display_device, compatible_renderlist(_))
938 .WillByDefault(Return(true));
939- ON_CALL(*mock_display_device, commit(_,_,_,_))
940- .WillByDefault(Invoke([](
941- mga::DisplayName,
942- mga::LayerList& list,
943- mga::SwappingGLContext const&,
944- mga::RenderableListCompositor const&)
945+ auto set_to_overlays = [](mga::LayerList& list)
946+ {
947+ auto native_list = list.native_list();
948+ for (auto i = 0u; i < native_list->numHwLayers; i++)
949 {
950- auto native_list = list.native_list();
951- for (auto i = 0u; i < native_list->numHwLayers; i++)
952- {
953- if (native_list->hwLayers[i].compositionType == HWC_FRAMEBUFFER)
954- native_list->hwLayers[i].compositionType = HWC_OVERLAY;
955- }
956- }));
957+ if (native_list->hwLayers[i].compositionType == HWC_FRAMEBUFFER)
958+ native_list->hwLayers[i].compositionType = HWC_OVERLAY;
959+ }
960+ };
961
962 mg::RenderableList renderlist{buffer1, buffer2};
963- EXPECT_TRUE(db.post_renderables_if_optimizable(renderlist));
964+ EXPECT_TRUE(db.post_renderables_if_optimizable(renderlist));
965+ set_to_overlays(db.contents().list);
966 EXPECT_FALSE(db.post_renderables_if_optimizable(renderlist));
967
968 renderlist = mg::RenderableList{buffer2, buffer1}; //ordering changed
969 EXPECT_TRUE(db.post_renderables_if_optimizable(renderlist));
970+ set_to_overlays(db.contents().list);
971 EXPECT_FALSE(db.post_renderables_if_optimizable(renderlist));
972
973 renderlist = mg::RenderableList{buffer3, buffer1}; //buffer changed
974 EXPECT_TRUE(db.post_renderables_if_optimizable(renderlist));
975+ set_to_overlays(db.contents().list);
976 EXPECT_FALSE(db.post_renderables_if_optimizable(renderlist));
977 }
978
979=== added file 'tests/unit-tests/graphics/android/test_display_group.cpp'
980--- tests/unit-tests/graphics/android/test_display_group.cpp 1970-01-01 00:00:00 +0000
981+++ tests/unit-tests/graphics/android/test_display_group.cpp 2015-03-02 14:38:17 +0000
982@@ -0,0 +1,85 @@
983+/*
984+ * Copyright © 2015 Canonical Ltd.
985+ *
986+ * This program is free software: you can redistribute it and/or modify
987+ * it under the terms of the GNU General Public License version 3 as
988+ * published by the Free Software Foundation.
989+ *
990+ * This program is distributed in the hope that it will be useful,
991+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
992+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
993+ * GNU General Public License for more details.
994+ *
995+ * You should have received a copy of the GNU General Public License
996+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
997+ *
998+ * Authored by: Kevin DuBois <kevin.dubois@canonical.com>
999+ */
1000+
1001+#include "src/platforms/android/server/configurable_display_buffer.h"
1002+#include "src/platforms/android/server/display_group.h"
1003+#include "mir_test_doubles/mock_display_device.h"
1004+#include "mir_test_doubles/stub_renderable_list_compositor.h"
1005+#include "mir_test_doubles/stub_swapping_gl_context.h"
1006+#include "mir_test/fake_shared.h"
1007+#include <memory>
1008+
1009+namespace mg=mir::graphics;
1010+namespace mga=mir::graphics::android;
1011+namespace mtd=mir::test::doubles;
1012+namespace mt=mir::test;
1013+
1014+namespace
1015+{
1016+struct StubConfigurableDB : mga::ConfigurableDisplayBuffer
1017+{
1018+ mir::geometry::Rectangle view_area() const override { return {}; }
1019+ void make_current() override {}
1020+ void release_current() override {}
1021+ void gl_swap_buffers() override {}
1022+ bool post_renderables_if_optimizable(mg::RenderableList const&) override { return false; }
1023+ MirOrientation orientation() const override { return mir_orientation_normal; }
1024+ bool uses_alpha() const override { return false; }
1025+ void configure(MirPowerMode, MirOrientation) override {}
1026+ mga::DisplayContents contents() override
1027+ {
1028+ return mga::DisplayContents{mga::DisplayName::primary, list, context, compositor};
1029+ }
1030+ MirPowerMode power_mode() const override { return mir_power_mode_on; }
1031+ mga::LayerList mutable list{std::make_shared<mga::IntegerSourceCrop>(), {}};
1032+ mtd::StubRenderableListCompositor mutable compositor;
1033+ mtd::StubSwappingGLContext mutable context;
1034+};
1035+}
1036+
1037+TEST(DisplayGroup, db_additions_and_removals)
1038+{
1039+ using namespace testing;
1040+ NiceMock<mtd::MockDisplayDevice> mock_device;
1041+ InSequence seq;
1042+ EXPECT_CALL(mock_device, commit(SizeIs(1)));
1043+ EXPECT_CALL(mock_device, commit(SizeIs(2)));
1044+ EXPECT_CALL(mock_device, commit(SizeIs(2)));
1045+ EXPECT_CALL(mock_device, commit(SizeIs(1)));
1046+
1047+ mga::DisplayGroup group(mt::fake_shared(mock_device), std::unique_ptr<StubConfigurableDB>{new StubConfigurableDB});
1048+ group.post();
1049+
1050+ //hwc api does not allow removing primary
1051+ EXPECT_THROW({
1052+ group.remove(mga::DisplayName::primary);
1053+ }, std::logic_error);
1054+
1055+ EXPECT_FALSE(group.display_present(mga::DisplayName::external));
1056+ group.add(mga::DisplayName::external, std::unique_ptr<StubConfigurableDB>(new StubConfigurableDB));
1057+ EXPECT_TRUE(group.display_present(mga::DisplayName::external));
1058+ group.post();
1059+
1060+ //can replace primary or external
1061+ group.add(mga::DisplayName::primary, std::unique_ptr<StubConfigurableDB>(new StubConfigurableDB));
1062+ group.add(mga::DisplayName::external, std::unique_ptr<StubConfigurableDB>(new StubConfigurableDB));
1063+ group.post();
1064+ group.remove(mga::DisplayName::external);
1065+ group.remove(mga::DisplayName::external);
1066+ group.post();
1067+}
1068
1069=== modified file 'tests/unit-tests/graphics/android/test_fb_device.cpp'
1070--- tests/unit-tests/graphics/android/test_fb_device.cpp 2015-02-02 12:18:18 +0000
1071+++ tests/unit-tests/graphics/android/test_fb_device.cpp 2015-03-02 14:38:17 +0000
1072@@ -93,12 +93,13 @@
1073 .WillOnce(Return(0));
1074
1075 mga::FBDevice fbdev(fb_hal_mock);
1076+ mga::DisplayContents content{primary, list, mock_context, stub_compositor};
1077
1078 EXPECT_THROW({
1079- fbdev.commit(primary, list, mock_context, stub_compositor);
1080+ fbdev.commit({content});
1081 }, std::runtime_error);
1082
1083- fbdev.commit(primary, list, mock_context, stub_compositor);
1084+ fbdev.commit({content});
1085 }
1086
1087 //not all fb devices provide a swap interval hook. make sure we don't explode if thats the case
1088
1089=== modified file 'tests/unit-tests/graphics/android/test_hwc_configuration.cpp'
1090--- tests/unit-tests/graphics/android/test_hwc_configuration.cpp 2015-02-13 06:12:34 +0000
1091+++ tests/unit-tests/graphics/android/test_hwc_configuration.cpp 2015-03-02 14:38:17 +0000
1092@@ -227,3 +227,18 @@
1093 auto attribs = config.active_attribs_for(mga::DisplayName::external);
1094 EXPECT_THAT(attribs.vrefresh_hz, Eq(0.0f));
1095 }
1096+
1097+TEST_F(HwcConfiguration, subscribes_to_hotplug)
1098+{
1099+ using namespace testing;
1100+ std::function<void(mga::DisplayName, bool)> hotplug_fn([](mga::DisplayName, bool){});
1101+ EXPECT_CALL(*mock_hwc_wrapper, subscribe_to_events(_,_,_,_))
1102+ .WillOnce(SaveArg<2>(&hotplug_fn));
1103+ EXPECT_CALL(*mock_hwc_wrapper, unsubscribe_from_events_(_));
1104+
1105+ unsigned int call_count{0};
1106+ auto subscription = config.subscribe_to_config_changes([&]{ call_count++; });
1107+ hotplug_fn(mga::DisplayName::primary, true);
1108+ hotplug_fn(mga::DisplayName::primary, true);
1109+ EXPECT_THAT(call_count, Eq(2));
1110+}
1111
1112=== modified file 'tests/unit-tests/graphics/android/test_hwc_device.cpp'
1113--- tests/unit-tests/graphics/android/test_hwc_device.cpp 2015-02-26 03:20:09 +0000
1114+++ tests/unit-tests/graphics/android/test_hwc_device.cpp 2015-03-02 14:38:17 +0000
1115@@ -112,7 +112,7 @@
1116 std::shared_ptr<mtd::StubRenderable> const stub_renderable1;
1117 std::shared_ptr<mtd::StubRenderable> const stub_renderable2;
1118 std::shared_ptr<mtd::MockHWCDeviceWrapper> const mock_device;
1119- mtd::StubSwappingGLContext const stub_context;
1120+ mtd::StubSwappingGLContext stub_context;
1121 mg::RenderableList renderlist;
1122 std::shared_ptr<mga::LayerAdapter> const layer_adapter;
1123 mga::DisplayName primary{mga::DisplayName::primary};
1124@@ -132,8 +132,9 @@
1125 .Times(1);
1126
1127 mga::LayerList list(layer_adapter, {});
1128+ mga::DisplayContents content{primary, list, stub_context, stub_compositor};
1129 mga::HwcDevice device(mock_device);
1130- device.commit(primary, list, stub_context, stub_compositor);
1131+ device.commit({content});
1132 }
1133
1134 TEST_F(HwcDevice, calls_backup_compositor_when_overlay_rejected)
1135@@ -167,8 +168,9 @@
1136 .InSequence(seq);
1137
1138 mga::LayerList list(layer_adapter, renderlist);
1139+ mga::DisplayContents content{primary, list, stub_context, mock_compositor};
1140 mga::HwcDevice device(mock_device);
1141- device.commit(primary, list, stub_context, mock_compositor);
1142+ device.commit({content});
1143 }
1144
1145 TEST_F(HwcDevice, swaps_buffers_directly_when_no_renderables)
1146@@ -184,8 +186,9 @@
1147 EXPECT_CALL(mock_context, swap_buffers());
1148
1149 mga::LayerList list(layer_adapter, {});
1150+ mga::DisplayContents content{primary, list, mock_context, mock_compositor};
1151 mga::HwcDevice device(mock_device);
1152- device.commit(primary, list, mock_context, mock_compositor);
1153+ device.commit({content});
1154 }
1155
1156 TEST_F(HwcDevice, resets_layers_when_prepare_gl_called)
1157@@ -212,9 +215,10 @@
1158
1159 mga::HwcDevice device(mock_device);
1160 mga::LayerList list(layer_adapter, renderlist);
1161- device.commit(primary, list, stub_context, stub_compositor);
1162+ mga::DisplayContents content{primary, list, stub_context, stub_compositor};
1163+ device.commit({content});
1164 list.update_list({});
1165- device.commit(primary, list, stub_context, stub_compositor);
1166+ device.commit({content});
1167 }
1168
1169 TEST_F(HwcDevice, sets_and_updates_fences)
1170@@ -246,7 +250,8 @@
1171
1172 mga::HwcDevice device(mock_device);
1173 mga::LayerList list(layer_adapter, {});
1174- device.commit(primary, list, stub_context, stub_compositor);
1175+ mga::DisplayContents content{primary, list, stub_context, stub_compositor};
1176+ device.commit({content});
1177
1178 //check that the retire fence is closed
1179 bool retire_fence_was_closed{fcntl(hwc_retire_fence, F_GETFD) == -1};
1180@@ -297,7 +302,8 @@
1181
1182 mga::HwcDevice device(mock_device);
1183 mga::LayerList list(layer_adapter, {stub_renderable1});
1184- device.commit(primary, list, stub_context, stub_compositor);
1185+ mga::DisplayContents content{primary, list, stub_context, stub_compositor};
1186+ device.commit({content});
1187 }
1188
1189 TEST_F(HwcDevice, commits_correct_list_when_all_accepted_as_overlays)
1190@@ -360,7 +366,8 @@
1191
1192 mga::HwcDevice device(mock_device);
1193 mga::LayerList list(layer_adapter, renderlist);
1194- device.commit(primary, list, stub_context, stub_compositor);
1195+ mga::DisplayContents content{primary, list, stub_context, stub_compositor};
1196+ device.commit({content});
1197 }
1198
1199 TEST_F(HwcDevice, submits_every_time_if_at_least_one_layer_is_gl_rendered)
1200@@ -381,9 +388,10 @@
1201 .Times(2);
1202
1203 mga::LayerList list(layer_adapter, renderlist);
1204- device.commit(primary, list, stub_context, stub_compositor);
1205+ mga::DisplayContents content{primary, list, stub_context, stub_compositor};
1206+ device.commit({content});
1207 list.update_list(renderlist);
1208- device.commit(primary, list, stub_context, stub_compositor);
1209+ device.commit({content});
1210 }
1211
1212 TEST_F(HwcDevice, resets_composition_type_with_prepare) //lp:1314399
1213@@ -404,9 +412,10 @@
1214 .InSequence(seq);
1215
1216 mga::LayerList list(layer_adapter, renderlist);
1217- device.commit(primary, list, stub_context, stub_compositor);
1218+ mga::DisplayContents content{primary, list, stub_context, stub_compositor};
1219+ device.commit({content});
1220 list.update_list(renderlist2);
1221- device.commit(primary, list, stub_context, stub_compositor);
1222+ device.commit({content});
1223 }
1224
1225 //note: HWC models overlay layer buffers as owned by the display hardware until a subsequent set.
1226@@ -421,10 +430,11 @@
1227
1228 auto use_count_before = stub_buffer1.use_count();
1229 mga::LayerList list(layer_adapter, {stub_renderable1});
1230- device.commit(primary, list, stub_context, stub_compositor);
1231+ mga::DisplayContents content{primary, list, stub_context, stub_compositor};
1232+ device.commit({content});
1233 EXPECT_THAT(stub_buffer1.use_count(), Gt(use_count_before));
1234 list.update_list({stub_renderable1});
1235- device.commit(primary, list, stub_context, stub_compositor);
1236+ device.commit({content});
1237 EXPECT_THAT(stub_buffer1.use_count(), Eq(use_count_before));
1238 }
1239
1240@@ -503,12 +513,13 @@
1241
1242 mga::HwcDevice device(mock_device);
1243 mga::LayerList list(layer_adapter, renderlist);
1244- device.commit(primary, list, stub_context, stub_compositor);
1245+ mga::DisplayContents content{primary, list, stub_context, stub_compositor};
1246+ device.commit({content});
1247 //set only the 2nd layer to a new buffer. the first buffer has the same buffer, and would
1248 //still be onscreen if this wasn't against a mock
1249 stub_renderable1->set_buffer(updated_buffer);
1250 list.update_list(renderlist);
1251- device.commit(primary, list, stub_context, stub_compositor);
1252+ device.commit({content});
1253 }
1254
1255 TEST_F(HwcDevice, does_not_own_framebuffer_buffers_past_set)
1256@@ -527,7 +538,8 @@
1257 auto use_count_before = stub_buffer1.use_count();
1258
1259 mga::LayerList list(layer_adapter, {stub_renderable1});
1260- device.commit(primary, list, stub_context, stub_compositor);
1261+ mga::DisplayContents content{primary, list, stub_context, stub_compositor};
1262+ device.commit({content});
1263 EXPECT_THAT(stub_buffer1.use_count(), Eq(use_count_before));
1264 }
1265
1266@@ -566,7 +578,8 @@
1267
1268 auto use_count_before = stub_buffer1.use_count();
1269 mga::LayerList list(layer_adapter, {stub_renderable1});
1270- device.commit(primary, list, stub_context, stub_compositor);
1271+ mga::DisplayContents content{primary, list, stub_context, stub_compositor};
1272+ device.commit({content});
1273 EXPECT_THAT(stub_buffer1.use_count(), Gt(use_count_before));
1274
1275 device.content_cleared();
1276@@ -660,9 +673,10 @@
1277
1278 mga::HwcDevice device(mock_device);
1279 mga::LayerList list(layer_adapter, renderlist1);
1280- device.commit(primary, list, stub_context, stub_compositor);
1281+ mga::DisplayContents content{primary, list, stub_context, stub_compositor};
1282+ device.commit({content});
1283 list.update_list(renderlist2);
1284- device.commit(primary, list, stub_context, stub_compositor);
1285+ device.commit({content});
1286 }
1287
1288 TEST_F(HwcDevice, tracks_hwc_owned_fences_across_list_rearrange)
1289@@ -763,7 +777,42 @@
1290
1291 mga::HwcDevice device(mock_device);
1292 mga::LayerList list(layer_adapter, renderlist);
1293- device.commit(primary, list, stub_context, stub_compositor);
1294+ mga::DisplayContents content{primary, list, stub_context, stub_compositor};
1295+ device.commit({content});
1296 list.update_list(renderlist2);
1297- device.commit(primary, list, stub_context, stub_compositor);
1298+ device.commit({content});
1299+}
1300+
1301+TEST_F(HwcDevice, commits_external_list_with_both_force_gl)
1302+{
1303+ using namespace testing;
1304+ testing::NiceMock<mtd::MockSwappingGLContext> mock_context1;
1305+ testing::NiceMock<mtd::MockSwappingGLContext> mock_context2;
1306+ ON_CALL(mock_context1, last_rendered_buffer())
1307+ .WillByDefault(Return(stub_fb_buffer));
1308+ ON_CALL(mock_context2, last_rendered_buffer())
1309+ .WillByDefault(Return(stub_fb_buffer));
1310+ std::list<hwc_layer_1_t*> expected_list
1311+ {
1312+ &skip_layer,
1313+ &target_layer
1314+ };
1315+
1316+ InSequence seq;
1317+ EXPECT_CALL(*mock_device, prepare(MatchesLists(expected_list, expected_list)));
1318+ EXPECT_CALL(mock_context1, make_current());
1319+ EXPECT_CALL(mock_context1, release_current());
1320+ EXPECT_CALL(mock_context2, make_current());
1321+ EXPECT_CALL(mock_context2, release_current());
1322+ EXPECT_CALL(*mock_device, set(MatchesLists(expected_list, expected_list)));
1323+
1324+ mga::LayerList primary_list(layer_adapter, {});
1325+ mga::LayerList external_list(layer_adapter, {});
1326+
1327+ mga::HwcDevice device(mock_device);
1328+
1329+ mga::DisplayContents primary_content{primary, primary_list, mock_context1, stub_compositor};
1330+ mga::DisplayContents external_content{mga::DisplayName::external, external_list, mock_context2, stub_compositor};
1331+
1332+ device.commit({primary_content, external_content});
1333 }
1334
1335=== modified file 'tests/unit-tests/graphics/android/test_hwc_fb_device.cpp'
1336--- tests/unit-tests/graphics/android/test_hwc_fb_device.cpp 2015-02-02 12:18:18 +0000
1337+++ tests/unit-tests/graphics/android/test_hwc_fb_device.cpp 2015-03-02 14:38:17 +0000
1338@@ -172,5 +172,6 @@
1339 EXPECT_CALL(*mock_fb_device, post_interface(mock_fb_device.get(), &stub_native_buffer->native_handle))
1340 .InSequence(seq);
1341
1342- device.commit(primary, list, mock_context, stub_compositor);
1343+ mga::DisplayContents content{primary, list, mock_context, stub_compositor};
1344+ device.commit({content});
1345 }

Subscribers

People subscribed via source and target branches