Mir

Merge lp:~andreas-pokorny/mir/add-display-configuration-output-assembly-to-display-device into lp:mir

Proposed by Andreas Pokorny
Status: Rejected
Rejected by: Andreas Pokorny
Proposed branch: lp:~andreas-pokorny/mir/add-display-configuration-output-assembly-to-display-device
Merge into: lp:mir
Diff against target: 899 lines (+608/-23)
18 files modified
src/platform/graphics/android/CMakeLists.txt (+1/-0)
src/platform/graphics/android/display_configuration_utilities.cpp (+57/-0)
src/platform/graphics/android/display_configuration_utilities.h (+35/-0)
src/platform/graphics/android/display_device.h (+2/-0)
src/platform/graphics/android/fb_device.cpp (+18/-5)
src/platform/graphics/android/fb_device.h (+1/-0)
src/platform/graphics/android/hwc_device.cpp (+116/-0)
src/platform/graphics/android/hwc_device.h (+1/-0)
src/platform/graphics/android/hwc_fb_device.cpp (+9/-0)
src/platform/graphics/android/hwc_fb_device.h (+1/-0)
src/platform/graphics/android/hwc_wrapper.h (+13/-0)
src/platform/graphics/android/real_hwc_wrapper.cpp (+45/-0)
src/platform/graphics/android/real_hwc_wrapper.h (+2/-0)
tests/include/mir_test_doubles/mock_display_device.h (+1/-0)
tests/include/mir_test_doubles/mock_fb_hal_device.h (+11/-5)
tests/include/mir_test_doubles/mock_hwc_device_wrapper.h (+3/-0)
tests/unit-tests/graphics/android/test_fb_device.cpp (+46/-1)
tests/unit-tests/graphics/android/test_hwc_common_device.cpp (+246/-12)
To merge this branch: bzr merge lp:~andreas-pokorny/mir/add-display-configuration-output-assembly-to-display-device
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Needs Fixing
Kevin DuBois (community) Needs Fixing
Review via email: mp+239978@code.launchpad.net

Commit message

Add means to query display output configuration from DisplayDevice

This adds methods to DisplayDevice and HwcWrapper to assemble a DisplayConfigurationOutput using the fb and hwc interfaces and EGL. The code is largely borrowed from mir::graphics::android::Framebuffers. This change does not yet make mir::android::DisplayConfiguration use this code path.

Description of the change

Adds a method to query the output configuration for a hwc display. With this MP the code path is not yet in use, but just prepared.

To post a comment you must log in.
Revision history for this message
Kevin DuBois (kdub) wrote :

407 +++ src/platform/graphics/android/real_hwc_wrapper.cpp
This is supposed to be an adapter layer around the hwc interface. Its kept thin and mostly in terms of hwc types so that the logs can closely reflect the actual calls to the 3rd party code. This lets us collaborate more easily with vendors. It shouldn't be doing heavy lifting. The code that was added is a duplication of the code in framebuffers.cpp

77 +++ src/platform/graphics/android/display_configuration_utilities.h
given this would only be used by the fb device, it would probably be better to be in an anonymous namespace closer to the creation of the the fb_device.cpp file instead of in the two types of DisplayDevices that rely on the framebuffer device.

200 +#include <EGL/egl.h>
201 +#include <EGL/eglext.h>
I've gone through some pains to keep egl out of the displaydevice setup, would like to keep the egl stuff in the DisplayBuffer or the HwcFallbackRenderer

290 + for(auto config : configs)
const&

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

52 + 25.4f * float(device.width) / float(device.xdpi),
53 + 25.4f * float(device.height) / float(device.ydpi)
magic numbers

873 +TEST_F(HWC10Tests, display_configuration_matches_expectations)
847 +TEST_F(PostHWC10Tests, queries_egl_configuration)
introduction of new terminology with HWC10 and PostHWC10. In current code, hwc 1.0 is called HwcFbDevice, hwc 1.1+ is called HwcDevice.

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

Is this being reworked based on kdub's feedback?

Or should we review as is?

Unmerged revisions

2008. By Andreas Pokorny

Add means to query display output configuration from DisplayDevice

This adds a methods to DisplayDevice and HwcWrapper to assemble a
DisplayConfigurationOutput using the fb and hwc interfaces and EGL.
The code is largely borrowed from mir::graphics::android::Framebuffers.
This change does not yet make mir::android::DisplayConfiguration use this
code path.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/platform/graphics/android/CMakeLists.txt'
2--- src/platform/graphics/android/CMakeLists.txt 2014-10-01 06:25:56 +0000
3+++ src/platform/graphics/android/CMakeLists.txt 2014-10-29 12:29:38 +0000
4@@ -14,6 +14,7 @@
5 buffer.cpp
6 display.cpp
7 display_configuration.cpp
8+ display_configuration_utilities.cpp
9 display_buffer.cpp
10 output_builder.cpp
11 hwc_layerlist.cpp
12
13=== added file 'src/platform/graphics/android/display_configuration_utilities.cpp'
14--- src/platform/graphics/android/display_configuration_utilities.cpp 1970-01-01 00:00:00 +0000
15+++ src/platform/graphics/android/display_configuration_utilities.cpp 2014-10-29 12:29:38 +0000
16@@ -0,0 +1,57 @@
17+/*
18+ * Copyright © 2014 Canonical Ltd.
19+ *
20+ * This program is free software: you can redistribute it and/or modify it
21+ * under the terms of the GNU Lesser 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 Lesser General Public License for more details.
28+ *
29+ * You should have received a copy of the GNU Lesser General Public License
30+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
31+ *
32+ * Authored by:
33+ * Andreas Pokorny <andreas.pokorny@canonical.com>
34+ */
35+
36+#include "display_configuration_utilities.h"
37+#include "android_format_conversion-inl.h"
38+
39+#include "mir/graphics/display_configuration.h"
40+#include "mir/geometry/point.h"
41+#include "mir/geometry/size.h"
42+
43+#include <hardware/gralloc.h>
44+#include <hardware/fb.h>
45+
46+namespace mg = mir::graphics;
47+namespace mga = mg::android;
48+namespace geom = mir::geometry;
49+mg::DisplayConfigurationOutput mga::create_output_configuration_from_fb(framebuffer_device_t const& device)
50+{
51+ geometry::Size size_in_mm(
52+ 25.4f * float(device.width) / float(device.xdpi),
53+ 25.4f * float(device.height) / float(device.ydpi)
54+ );
55+
56+ return mg::DisplayConfigurationOutput
57+ {
58+ mg::DisplayConfigurationOutputId{0},
59+ mg::DisplayConfigurationCardId{0},
60+ mg::DisplayConfigurationOutputType::lvds,
61+ { mga::to_mir_format(device.format) }, // query for more?
62+ { {geom::Size{device.width, device.height}, double(device.fps)}},
63+ 0,
64+ size_in_mm,
65+ true,
66+ true,
67+ geom::Point{0,0}, // top left
68+ 0,
69+ mga::to_mir_format(device.format),
70+ mir_power_mode_on,
71+ mir_orientation_normal
72+ };
73+}
74
75=== added file 'src/platform/graphics/android/display_configuration_utilities.h'
76--- src/platform/graphics/android/display_configuration_utilities.h 1970-01-01 00:00:00 +0000
77+++ src/platform/graphics/android/display_configuration_utilities.h 2014-10-29 12:29:38 +0000
78@@ -0,0 +1,35 @@
79+/*
80+ * Copyright © 2014 Canonical Ltd.
81+ *
82+ * This program is free software: you can redistribute it and/or modify it
83+ * under the terms of the GNU Lesser General Public License version 3,
84+ * as published by the Free Software Foundation.
85+ *
86+ * This program is distributed in the hope that it will be useful,
87+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
88+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
89+ * GNU Lesser General Public License for more details.
90+ *
91+ * You should have received a copy of the GNU Lesser General Public License
92+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
93+ *
94+ * Authored by:
95+ * Andreas Pokorny <andreas.pokorny@canonical.com>
96+ */
97+
98+#ifndef MIR_GRAPHICS_ANDROID_DISPLAY_CONFIGURATION_UTILITIES_H_
99+#define MIR_GRAPHICS_ANDROID_DISPLAY_CONFIGURATION_UTILITIES_H_
100+
101+struct framebuffer_device_t;
102+namespace mir
103+{
104+namespace graphics
105+{
106+struct DisplayConfigurationOutput;
107+namespace android
108+{
109+DisplayConfigurationOutput create_output_configuration_from_fb(framebuffer_device_t const& device);
110+}
111+}
112+}
113+#endif /* MIR_GRAPHICS_ANDROID_DISPLAY_CONFIGURATION_UTILITIES_H_ */
114
115=== modified file 'src/platform/graphics/android/display_device.h'
116--- src/platform/graphics/android/display_device.h 2014-10-01 06:25:56 +0000
117+++ src/platform/graphics/android/display_device.h 2014-10-29 12:29:38 +0000
118@@ -20,6 +20,7 @@
119 #define MIR_GRAPHICS_ANDROID_DISPLAY_SUPPORT_PROVIDER_H_
120
121 #include "mir/graphics/renderable.h"
122+#include "mir/graphics/display_configuration.h"
123 #include "mir_toolkit/common.h"
124 #include <EGL/egl.h>
125
126@@ -50,6 +51,7 @@
127 RenderableList const& list,
128 RenderableListCompositor const& list_compositor) = 0;
129 virtual bool apply_orientation(MirOrientation orientation) const = 0;
130+ virtual DisplayConfigurationOutput get_output_configuration(DisplayConfigurationOutputId id) const = 0;
131
132 protected:
133 DisplayDevice() = default;
134
135=== modified file 'src/platform/graphics/android/fb_device.cpp'
136--- src/platform/graphics/android/fb_device.cpp 2014-10-01 06:25:56 +0000
137+++ src/platform/graphics/android/fb_device.cpp 2014-10-29 12:29:38 +0000
138@@ -16,14 +16,18 @@
139 * Authored by: Kevin DuBois <kevin.dubois@canonical.com>
140 */
141
142+#include "fb_device.h"
143+#include "swapping_gl_context.h"
144+#include "framebuffer_bundle.h"
145+#include "buffer.h"
146+#include "display_configuration_utilities.h"
147+
148 #include "mir/graphics/buffer.h"
149 #include "mir/graphics/android/native_buffer.h"
150 #include "mir/graphics/android/sync_fence.h"
151-#include "swapping_gl_context.h"
152-#include "android_format_conversion-inl.h"
153-#include "fb_device.h"
154-#include "framebuffer_bundle.h"
155-#include "buffer.h"
156+
157+// usage of HWC_DISPLAY_PRIMARY to identify output attached to framebuffer:
158+#include "hardware/hwcomposer_defs.h"
159
160 #include <boost/throw_exception.hpp>
161 #include <stdexcept>
162@@ -80,3 +84,12 @@
163 fb_device->enableScreen(fb_device.get(), enable);
164 }
165 }
166+
167+
168+mg::DisplayConfigurationOutput mga::FBDevice::get_output_configuration(mg::DisplayConfigurationOutputId id) const
169+{
170+ if (id.as_value() != HWC_DISPLAY_PRIMARY)
171+ BOOST_THROW_EXCEPTION(std::runtime_error("only primary display supported"));
172+
173+ return mga::create_output_configuration_from_fb(*fb_device);
174+}
175
176=== modified file 'src/platform/graphics/android/fb_device.h'
177--- src/platform/graphics/android/fb_device.h 2014-10-01 06:25:56 +0000
178+++ src/platform/graphics/android/fb_device.h 2014-10-29 12:29:38 +0000
179@@ -42,6 +42,7 @@
180 SwappingGLContext const& context,
181 RenderableList const& list,
182 RenderableListCompositor const& list_compositor);
183+ DisplayConfigurationOutput get_output_configuration(DisplayConfigurationOutputId id) const override;
184
185 private:
186 std::shared_ptr<framebuffer_device_t> const fb_device;
187
188=== modified file 'src/platform/graphics/android/hwc_device.cpp'
189--- src/platform/graphics/android/hwc_device.cpp 2014-10-01 06:25:56 +0000
190+++ src/platform/graphics/android/hwc_device.cpp 2014-10-29 12:29:38 +0000
191@@ -25,6 +25,15 @@
192 #include "framebuffer_bundle.h"
193 #include "buffer.h"
194 #include "hwc_fallback_gl_renderer.h"
195+#include "android_format_conversion-inl.h"
196+
197+#include "mir/geometry/size.h"
198+#include "mir/geometry/point.h"
199+
200+#include <EGL/egl.h>
201+#include <EGL/eglext.h>
202+
203+#include <boost/throw_exception.hpp>
204 #include <limits>
205 #include <algorithm>
206
207@@ -63,6 +72,59 @@
208 }
209 return false;
210 }
211+
212+std::vector<MirPixelFormat> determine_hwc11_fb_formats()
213+{
214+ static EGLint const fb_egl_config_attr [] =
215+ {
216+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
217+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
218+ EGL_FRAMEBUFFER_TARGET_ANDROID, EGL_TRUE,
219+ EGL_NONE
220+ };
221+
222+ const EGLint config_size = 64;
223+ EGLConfig fb_egl_config[config_size];
224+ int matching_configs;
225+ EGLint major, minor;
226+ auto egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
227+ eglInitialize(egl_display, &major, &minor);
228+ eglChooseConfig(egl_display, fb_egl_config_attr, fb_egl_config, config_size, &matching_configs);
229+
230+ std::vector<MirPixelFormat> formats;
231+ std::transform(fb_egl_config, fb_egl_config+matching_configs,
232+ std::back_inserter(formats),
233+ [&](EGLConfig const& cfg)
234+ {
235+ int visual_id;
236+ eglGetConfigAttrib(egl_display, cfg, EGL_NATIVE_VISUAL_ID, &visual_id);
237+ return mga::to_mir_format(visual_id);
238+ }
239+ );
240+
241+ std::sort(begin(formats), end(formats));
242+ formats.erase(
243+ std::unique(
244+ begin(formats),
245+ std::remove_if(begin(formats), end(formats),
246+ [](MirPixelFormat const& item )
247+ {
248+ return item == mir_pixel_format_invalid;
249+ })
250+ ),
251+ end(formats)
252+ );
253+
254+ if (formats.empty())
255+ {
256+ //we couldn't figure out the fb format via egl. In this case, we
257+ //assume abgr_8888. HWC api really should provide this information directly.
258+ formats.push_back(mir_pixel_format_abgr_8888);
259+ }
260+
261+ eglTerminate(egl_display);
262+ return formats;
263+}
264 }
265
266 mga::HwcDevice::HwcDevice(std::shared_ptr<HwcWrapper> const& hwc_wrapper,
267@@ -194,3 +256,57 @@
268 {
269 onscreen_overlay_buffers.clear();
270 }
271+
272+mg::DisplayConfigurationOutput mga::HwcDevice::get_output_configuration(DisplayConfigurationOutputId id) const
273+{
274+ // TODO: only support primary for now, external is not allowed for now
275+ if (id.as_value() != HWC_DISPLAY_PRIMARY &&
276+ id.as_value() != HWC_DISPLAY_EXTERNAL)
277+ BOOST_THROW_EXCEPTION(std::runtime_error("display not supported"));
278+
279+ auto configs = hwc_wrapper->get_display_configs(id);
280+
281+ if (configs.empty())
282+ BOOST_THROW_EXCEPTION(std::runtime_error("No configs available for display"));
283+
284+ std::vector<MirPixelFormat> formats{ determine_hwc11_fb_formats() };
285+ MirPixelFormat current_format = formats[0];
286+
287+ std::vector<DisplayConfigurationMode> modes;
288+ geometry::Size output_size(0, 0);
289+
290+ for(auto config : configs)
291+ {
292+ auto attributes = hwc_wrapper->get_display_config_attributes(id, config);
293+ modes.push_back(DisplayConfigurationMode{attributes.size, attributes.refresh_rate_hz});
294+ geometry::Size size_in_mm(
295+ 25.4f * attributes.size.width.as_float() / float(attributes.dpi_x),
296+ 25.4f * attributes.size.height.as_float() / float(attributes.dpi_y)
297+ );
298+
299+ if (size_in_mm.width.as_int() * size_in_mm.height.as_int() > output_size.width.as_int() * output_size.height.as_int())
300+ output_size = size_in_mm;
301+ }
302+
303+ size_t preferred_mode_index = 0;
304+
305+ return mg::DisplayConfigurationOutput
306+ {
307+ id,
308+ mg::DisplayConfigurationCardId{0},
309+ id.as_value() == HWC_DISPLAY_PRIMARY?
310+ mg::DisplayConfigurationOutputType::lvds:
311+ mg::DisplayConfigurationOutputType::hdmia,
312+ std::move(formats),
313+ std::move(modes),
314+ preferred_mode_index,
315+ output_size,
316+ true,
317+ true,
318+ geometry::Point{0,0}, // top left
319+ 0, // current mode
320+ current_format,
321+ mir_power_mode_on,
322+ mir_orientation_normal
323+ };
324+}
325
326=== modified file 'src/platform/graphics/android/hwc_device.h'
327--- src/platform/graphics/android/hwc_device.h 2014-10-01 06:25:56 +0000
328+++ src/platform/graphics/android/hwc_device.h 2014-10-29 12:29:38 +0000
329@@ -50,6 +50,7 @@
330 SwappingGLContext const& context,
331 RenderableList const& list,
332 RenderableListCompositor const& list_compositor);
333+ DisplayConfigurationOutput get_output_configuration(DisplayConfigurationOutputId id) const override;
334
335 private:
336 bool buffer_is_onscreen(Buffer const&) const;
337
338=== modified file 'src/platform/graphics/android/hwc_fb_device.cpp'
339--- src/platform/graphics/android/hwc_fb_device.cpp 2014-10-01 06:25:56 +0000
340+++ src/platform/graphics/android/hwc_fb_device.cpp 2014-10-29 12:29:38 +0000
341@@ -21,6 +21,7 @@
342 #include "hwc_vsync_coordinator.h"
343 #include "framebuffer_bundle.h"
344 #include "android_format_conversion-inl.h"
345+#include "display_configuration_utilities.h"
346 #include "hwc_wrapper.h"
347 #include "hwc_fallback_gl_renderer.h"
348 #include "mir/graphics/buffer.h"
349@@ -88,3 +89,11 @@
350 {
351 return false;
352 }
353+
354+mg::DisplayConfigurationOutput mga::HwcFbDevice::get_output_configuration(mg::DisplayConfigurationOutputId id) const
355+{
356+ if (id.as_value() != HWC_DISPLAY_PRIMARY)
357+ BOOST_THROW_EXCEPTION(std::runtime_error("only primary display supported"));
358+
359+ return mga::create_output_configuration_from_fb(*fb_device);
360+}
361
362=== modified file 'src/platform/graphics/android/hwc_fb_device.h'
363--- src/platform/graphics/android/hwc_fb_device.h 2014-10-01 06:25:56 +0000
364+++ src/platform/graphics/android/hwc_fb_device.h 2014-10-29 12:29:38 +0000
365@@ -44,6 +44,7 @@
366 SwappingGLContext const& context,
367 RenderableList const& list,
368 RenderableListCompositor const& list_compositor);
369+ DisplayConfigurationOutput get_output_configuration(DisplayConfigurationOutputId id) const override;
370
371 private:
372 std::shared_ptr<HwcWrapper> const hwc_wrapper;
373
374=== modified file 'src/platform/graphics/android/hwc_wrapper.h'
375--- src/platform/graphics/android/hwc_wrapper.h 2014-10-01 06:25:56 +0000
376+++ src/platform/graphics/android/hwc_wrapper.h 2014-10-29 12:29:38 +0000
377@@ -19,6 +19,9 @@
378 #ifndef MIR_GRAPHICS_ANDROID_HWC_WRAPPER_H_
379 #define MIR_GRAPHICS_ANDROID_HWC_WRAPPER_H_
380
381+#include "mir/graphics/display_configuration.h"
382+#include "mir/geometry/size.h"
383+
384 #include <hardware/hwcomposer.h>
385 #include <memory>
386
387@@ -42,6 +45,16 @@
388 virtual void display_on() const = 0;
389 virtual void display_off() const = 0;
390
391+ virtual std::vector<uint32_t> get_display_configs(DisplayConfigurationOutputId id) const = 0;
392+ struct Attributes
393+ {
394+ geometry::Size size;
395+ uint32_t dpi_x;
396+ uint32_t dpi_y;
397+ double refresh_rate_hz;
398+ };
399+ virtual Attributes get_display_config_attributes(DisplayConfigurationOutputId id, uint32_t config) const = 0;
400+
401 protected:
402 HwcWrapper() = default;
403 HwcWrapper& operator=(HwcWrapper const&) = delete;
404
405=== modified file 'src/platform/graphics/android/real_hwc_wrapper.cpp'
406--- src/platform/graphics/android/real_hwc_wrapper.cpp 2014-10-01 06:25:56 +0000
407+++ src/platform/graphics/android/real_hwc_wrapper.cpp 2014-10-29 12:29:38 +0000
408@@ -111,3 +111,48 @@
409 }
410 logger->log_display_off();
411 }
412+
413+std::vector<uint32_t> mga::RealHwcWrapper::get_display_configs(DisplayConfigurationOutputId id) const
414+{
415+ const int num_configs_to_query = 10;
416+ uint32_t query_results[num_configs_to_query];
417+ size_t configs_received = num_configs_to_query;
418+
419+ if (auto rc = hwc_device->getDisplayConfigs(hwc_device.get(), id.as_value(), query_results, &configs_received))
420+ {
421+ std::stringstream ss;
422+ ss << "error querying display configs for display " << id.as_value() << ". rc = " << std::hex << rc;
423+ BOOST_THROW_EXCEPTION(std::runtime_error(ss.str()));
424+ }
425+
426+ return {query_results, query_results + configs_received};
427+}
428+
429+mga::HwcWrapper::Attributes mga::RealHwcWrapper::get_display_config_attributes(DisplayConfigurationOutputId id, uint32_t config) const
430+{
431+ /* note: some drivers (qcom msm8960) choke if this is not the same size array
432+ as the one surfaceflinger submits */
433+ static uint32_t const display_attribute_request[] =
434+ {
435+ HWC_DISPLAY_WIDTH,
436+ HWC_DISPLAY_HEIGHT,
437+ HWC_DISPLAY_VSYNC_PERIOD,
438+ HWC_DISPLAY_DPI_X,
439+ HWC_DISPLAY_DPI_Y,
440+ HWC_DISPLAY_NO_ATTRIBUTE,
441+ };
442+ int32_t size_values[sizeof(display_attribute_request) / sizeof (display_attribute_request[0])] = {};
443+
444+ if (auto rc = hwc_device->getDisplayAttributes(hwc_device.get(), id.as_value(), config,
445+ display_attribute_request, size_values))
446+ {
447+ std::stringstream ss;
448+ ss << "error querying attributes configs for display " << id.as_value() << ". rc = " << std::hex << rc;
449+ BOOST_THROW_EXCEPTION(std::runtime_error(ss.str()));
450+ }
451+
452+ //HWC_DISPLAY_VSYNC_PERIOD is specified in nanoseconds
453+ double refresh_rate_hz = (size_values[2] > 0 ) ? 1000000000.0/size_values[2] : 0.0;
454+ return {{size_values[0], size_values[1]}, uint32_t(size_values[3]), uint32_t(size_values[4]), refresh_rate_hz};
455+ }
456+
457
458=== modified file 'src/platform/graphics/android/real_hwc_wrapper.h'
459--- src/platform/graphics/android/real_hwc_wrapper.h 2014-10-01 06:25:56 +0000
460+++ src/platform/graphics/android/real_hwc_wrapper.h 2014-10-29 12:29:38 +0000
461@@ -44,6 +44,8 @@
462 void vsync_signal_off() const override;
463 void display_on() const override;
464 void display_off() const override;
465+ std::vector<uint32_t> get_display_configs(DisplayConfigurationOutputId id) const override;
466+ Attributes get_display_config_attributes(DisplayConfigurationOutputId id, uint32_t config) const override;
467 private:
468 static size_t const num_displays{3}; //primary, external, virtual
469 //note: the callbacks have to extend past the lifetime of the hwc_composer_device_1 for some
470
471=== modified file 'tests/include/mir_test_doubles/mock_display_device.h'
472--- tests/include/mir_test_doubles/mock_display_device.h 2014-10-01 06:25:56 +0000
473+++ tests/include/mir_test_doubles/mock_display_device.h 2014-10-29 12:29:38 +0000
474@@ -42,6 +42,7 @@
475 graphics::RenderableList const&,
476 graphics::android::RenderableListCompositor const&));
477 MOCK_CONST_METHOD1(apply_orientation, bool(MirOrientation));
478+ MOCK_CONST_METHOD1(get_output_configuration, graphics::DisplayConfigurationOutput(graphics::DisplayConfigurationOutputId));
479 };
480 }
481 }
482
483=== modified file 'tests/include/mir_test_doubles/mock_fb_hal_device.h'
484--- tests/include/mir_test_doubles/mock_fb_hal_device.h 2014-03-06 06:05:17 +0000
485+++ tests/include/mir_test_doubles/mock_fb_hal_device.h 2014-10-29 12:29:38 +0000
486@@ -34,8 +34,8 @@
487 class MockFBHalDevice : public framebuffer_device_t
488 {
489 public:
490- MockFBHalDevice(unsigned int const width, unsigned int const height,
491- int const pf, int const numfbs)
492+ MockFBHalDevice(unsigned int const width, unsigned int const height, int const pf,
493+ float const xdpi, float const ydpi, float const fps, int const numfbs)
494 : framebuffer_device_t({
495 hw_device_t(),
496 0,
497@@ -43,9 +43,9 @@
498 height,
499 0,
500 pf,
501- 0.0f,
502- 0.0f,
503- 0.0f,
504+ xdpi,
505+ ydpi,
506+ fps,
507 0,
508 1,
509 numfbs,
510@@ -59,6 +59,12 @@
511 enableScreen = hook_enableScreen;
512 }
513
514+ MockFBHalDevice(unsigned int const width, unsigned int const height,
515+ int const pf, int const numfbs)
516+ : MockFBHalDevice(width, height, pf, 1.0f, 1.0f, 2.0f, numfbs)
517+ {
518+ }
519+
520 MockFBHalDevice()
521 : MockFBHalDevice(1,1,1,1)
522 {
523
524=== modified file 'tests/include/mir_test_doubles/mock_hwc_device_wrapper.h'
525--- tests/include/mir_test_doubles/mock_hwc_device_wrapper.h 2014-10-01 06:25:56 +0000
526+++ tests/include/mir_test_doubles/mock_hwc_device_wrapper.h 2014-10-29 12:29:38 +0000
527@@ -39,6 +39,9 @@
528 MOCK_CONST_METHOD0(vsync_signal_off, void());
529 MOCK_CONST_METHOD0(display_on, void());
530 MOCK_CONST_METHOD0(display_off, void());
531+ MOCK_CONST_METHOD1(get_display_configs, std::vector<uint32_t>(graphics::DisplayConfigurationOutputId));
532+ MOCK_CONST_METHOD2(get_display_config_attributes, Attributes(graphics::DisplayConfigurationOutputId, uint32_t));
533+
534 };
535
536 }
537
538=== modified file 'tests/unit-tests/graphics/android/test_fb_device.cpp'
539--- tests/unit-tests/graphics/android/test_fb_device.cpp 2014-10-01 06:25:56 +0000
540+++ tests/unit-tests/graphics/android/test_fb_device.cpp 2014-10-29 12:29:38 +0000
541@@ -47,10 +47,14 @@
542
543 width = 413;
544 height = 516;
545+ dpi_x = 96.0f;
546+ dpi_y = 96.0f;
547+ fps = 120.0f;
548 fbnum = 4;
549 format = HAL_PIXEL_FORMAT_RGBA_8888;
550
551- fb_hal_mock = std::make_shared<NiceMock<mtd::MockFBHalDevice>>(width, height, format, fbnum);
552+ fb_hal_mock = std::make_shared<NiceMock<mtd::MockFBHalDevice>>(width, height, format,
553+ dpi_x, dpi_y, fps, fbnum);
554 mock_buffer = std::make_shared<NiceMock<mtd::MockBuffer>>();
555 native_buffer = std::make_shared<mtd::StubAndroidNativeBuffer>();
556 ON_CALL(*mock_buffer, native_buffer_handle())
557@@ -60,6 +64,7 @@
558 }
559
560 unsigned int width, height, format, fbnum;
561+ float dpi_x, dpi_y, fps;
562 std::shared_ptr<mtd::MockFBHalDevice> fb_hal_mock;
563 std::shared_ptr<mtd::MockBuffer> mock_buffer;
564 std::shared_ptr<mir::graphics::NativeBuffer> native_buffer;
565@@ -140,3 +145,43 @@
566 fbdev.mode(mir_power_mode_off);
567 fbdev.mode(mir_power_mode_on);
568 }
569+
570+TEST_F(FBDevice, throws_on_wrong_display_id)
571+{
572+ mga::FBDevice fbdev(fb_hal_mock);
573+ EXPECT_THROW(
574+ {fbdev.get_output_configuration(mg::DisplayConfigurationOutputId{HWC_DISPLAY_VIRTUAL});},
575+ std::runtime_error);
576+ EXPECT_THROW(
577+ {fbdev.get_output_configuration(mg::DisplayConfigurationOutputId{HWC_DISPLAY_EXTERNAL});},
578+ std::runtime_error);
579+ EXPECT_NO_THROW(
580+ {fbdev.get_output_configuration(mg::DisplayConfigurationOutputId{HWC_DISPLAY_PRIMARY});});
581+}
582+
583+TEST_F(FBDevice, display_output_configuration_matches)
584+{
585+ using namespace testing;
586+ mga::FBDevice fbdev(fb_hal_mock);
587+ EXPECT_THAT(
588+ fbdev.get_output_configuration(mg::DisplayConfigurationOutputId{HWC_DISPLAY_PRIMARY}),
589+ Eq(
590+ mg::DisplayConfigurationOutput
591+ {
592+ mg::DisplayConfigurationOutputId{HWC_DISPLAY_PRIMARY},
593+ mg::DisplayConfigurationCardId{0},
594+ mg::DisplayConfigurationOutputType::lvds,
595+ {mir_pixel_format_argb_8888},
596+ {{{413, 516}, 120.0f}},
597+ 0,
598+ {109, 136},
599+ true,
600+ true,
601+ {0, 0},
602+ 0,
603+ mir_pixel_format_abgr_8888,
604+ mir_power_mode_on,
605+ mir_orientation_normal
606+ }
607+ ));
608+}
609
610=== modified file 'tests/unit-tests/graphics/android/test_hwc_common_device.cpp'
611--- tests/unit-tests/graphics/android/test_hwc_common_device.cpp 2014-10-01 06:25:56 +0000
612+++ tests/unit-tests/graphics/android/test_hwc_common_device.cpp 2014-10-29 12:29:38 +0000
613@@ -36,7 +36,8 @@
614 #include <memory>
615 #include <gtest/gtest.h>
616
617-namespace mga=mir::graphics::android;
618+namespace mg=mir::graphics;
619+namespace mga=mg::android;
620 namespace mtd=mir::test::doubles;
621 namespace geom=mir::geometry;
622
623@@ -65,28 +66,90 @@
624 return std::make_shared<mga::HwcDevice>(hwc_device, coordinator, file_ops);
625 }
626
627-template<typename T>
628-class HWCCommon : public ::testing::Test
629+class HWCCommonFixture : public ::testing::Test
630 {
631 protected:
632- virtual void SetUp()
633+ void setup_display_config()
634+ {
635+ ON_CALL(*this->mock_device, get_display_configs(primary))
636+ .WillByDefault(testing::Return(std::vector<uint32_t>{0}));
637+
638+ ON_CALL(*this->mock_device, get_display_configs(external))
639+ .WillByDefault(testing::Return(std::vector<uint32_t>{1}));
640+
641+ ON_CALL(*this->mock_device, get_display_config_attributes(primary, 0))
642+ .WillByDefault(testing::Return(
643+ mga::HwcWrapper::Attributes{
644+ geom::Size{280,190},
645+ 320, // dpi x
646+ 320, // dpi y
647+ 60 // hz
648+ }));
649+
650+ ON_CALL(*this->mock_device, get_display_config_attributes(external, 1))
651+ .WillByDefault(testing::Return(
652+ mga::HwcWrapper::Attributes{
653+ geom::Size{1920,1200},
654+ 120, // dpi x
655+ 120, // dpi y
656+ 60 // hz
657+ }));
658+ }
659+ void setup_egl_configs()
660 {
661 using namespace testing;
662-
663- mock_fbdev = std::make_shared<mtd::MockFBHalDevice>();
664- mock_device = std::make_shared<testing::NiceMock<mtd::MockHWCDeviceWrapper>>();
665- mock_vsync = std::make_shared<testing::NiceMock<mtd::MockVsyncCoordinator>>();
666+ ON_CALL(mock_egl,eglChooseConfig(_,_,_,_,_))
667+ .WillByDefault(
668+ Invoke([](EGLDisplay, EGLint const *, EGLConfig * configs, EGLint config_size, EGLint * num_config)
669+ {
670+ if (config_size >= 3)
671+ configs[1] = EGLConfig(42);
672+ if (config_size >= 2)
673+ configs[1] = EGLConfig(13);
674+ if (config_size >= 1)
675+ configs[0] = EGLConfig(21);
676+ *num_config = std::min(3,config_size);
677+ return EGL_TRUE;
678+ })
679+ );
680+
681+ ON_CALL(mock_egl,eglGetConfigAttrib(_,_,_,_))
682+ .WillByDefault(
683+ Invoke([](EGLDisplay, EGLConfig config, EGLint attribute, EGLint * value) -> EGLBoolean
684+ {
685+ if (!value) return EGL_FALSE;
686+ if (attribute!=EGL_NATIVE_VISUAL_ID) return EGL_FALSE;
687+
688+ if (config == EGLConfig(42))
689+ *value = 0; // place holder for format that cannot be converted to mir format
690+ if (config == EGLConfig(13))
691+ *value = HAL_PIXEL_FORMAT_RGBA_8888;
692+ if (config == EGLConfig(21))
693+ *value = HAL_PIXEL_FORMAT_RGBX_8888;
694+ return EGL_TRUE;
695+ })
696+ );
697 }
698-
699 testing::NiceMock<mtd::MockEGL> mock_egl;
700- std::shared_ptr<mtd::MockVsyncCoordinator> mock_vsync;
701- std::shared_ptr<mtd::MockHWCDeviceWrapper> mock_device;
702- std::shared_ptr<mtd::MockFBHalDevice> mock_fbdev;
703+ std::shared_ptr<mtd::MockVsyncCoordinator> mock_vsync = std::make_shared<testing::NiceMock<mtd::MockVsyncCoordinator>>();
704+ std::shared_ptr<mtd::MockHWCDeviceWrapper> mock_device = std::make_shared<testing::NiceMock<mtd::MockHWCDeviceWrapper>>();
705+ std::shared_ptr<mtd::MockFBHalDevice> mock_fbdev = std::make_shared<mtd::MockFBHalDevice>(900, 600, HAL_PIXEL_FORMAT_RGBX_8888,
706+ 400.0f, 400.0f, 67.6f, 1);
707+
708+ mg::DisplayConfigurationOutputId primary{HWC_DISPLAY_PRIMARY};
709+ mg::DisplayConfigurationOutputId external{HWC_DISPLAY_EXTERNAL};
710+ mg::DisplayConfigurationOutputId virtual_output{HWC_DISPLAY_VIRTUAL};
711 };
712
713+template<typename T>
714+using HWCCommon = HWCCommonFixture;
715+
716 typedef ::testing::Types<mga::HwcFbDevice, mga::HwcDevice> HWCDeviceTestTypes;
717 TYPED_TEST_CASE(HWCCommon, HWCDeviceTestTypes);
718
719+using PostHWC10Tests = HWCCommonFixture;
720+using HWC10Tests = HWCCommonFixture;
721+
722 TYPED_TEST(HWCCommon, test_proc_registration)
723 {
724 using namespace testing;
725@@ -228,3 +291,174 @@
726 auto device = make_hwc_device<TypeParam>(this->mock_device, this->mock_fbdev, this->mock_vsync);
727 });
728 }
729+
730+TEST_F(HWC10Tests, throws_on_non_primary_display_output_configurations)
731+{
732+ using namespace testing;
733+ auto device = make_hwc_device<mga::HwcFbDevice>(this->mock_device, this->mock_fbdev, this->mock_vsync);
734+
735+ EXPECT_THROW({
736+ device->get_output_configuration(this->external);
737+ }, std::runtime_error);
738+ EXPECT_THROW({
739+ device->get_output_configuration(this->virtual_output);
740+ }, std::runtime_error);
741+}
742+
743+TEST_F(PostHWC10Tests, throws_on_virtual_display_output_configurations)
744+{
745+ using namespace testing;
746+ this->setup_display_config();
747+ auto device = make_hwc_device<mga::HwcDevice>(this->mock_device, this->mock_fbdev, this->mock_vsync);
748+
749+ EXPECT_THROW({device->get_output_configuration(this->virtual_output);}, std::runtime_error);
750+ EXPECT_NO_THROW({device->get_output_configuration(this->external);});
751+ EXPECT_NO_THROW({device->get_output_configuration(this->primary);});
752+}
753+
754+TEST_F(PostHWC10Tests, queries_hwc_device_for_configs)
755+{
756+ using namespace testing;
757+ this->setup_display_config();
758+
759+ auto device = make_hwc_device<mga::HwcDevice>(this->mock_device, this->mock_fbdev, this->mock_vsync);
760+
761+ EXPECT_CALL(*this->mock_device, get_display_configs(this->primary));
762+
763+ device->get_output_configuration(this->primary);
764+}
765+
766+TEST_F(PostHWC10Tests, throws_on_no_available_hwc_configurations)
767+{
768+ using namespace testing;
769+ auto device = make_hwc_device<mga::HwcDevice>(this->mock_device, this->mock_fbdev, this->mock_vsync);
770+
771+ ON_CALL(*this->mock_device, get_display_configs(_))
772+ .WillByDefault(Return(std::vector<uint32_t>{}));
773+ EXPECT_THROW({
774+ device->get_output_configuration(this->primary);
775+ }, std::runtime_error);
776+}
777+
778+TEST_F(PostHWC10Tests, queries_display_config_attributes)
779+{
780+ using namespace testing;
781+ this->setup_display_config();
782+ auto device = make_hwc_device<mga::HwcDevice>(this->mock_device, this->mock_fbdev, this->mock_vsync);
783+
784+ EXPECT_CALL(*this->mock_device, get_display_config_attributes(this->primary, 0));
785+
786+ device->get_output_configuration(this->primary);
787+}
788+
789+TEST_F(PostHWC10Tests, display_configuration_matches_expectations)
790+{
791+ using namespace testing;
792+ this->setup_display_config();
793+ auto device = make_hwc_device<mga::HwcDevice>(this->mock_device, this->mock_fbdev, this->mock_vsync);
794+
795+ EXPECT_THAT(
796+ device->get_output_configuration(this->primary),
797+ Eq(
798+ mg::DisplayConfigurationOutput
799+ {
800+ this->primary,
801+ mg::DisplayConfigurationCardId{0},
802+ mg::DisplayConfigurationOutputType::lvds,
803+ {mir_pixel_format_abgr_8888},
804+ {{{280, 190}, 60}},
805+ 0,
806+ {22, 15},
807+ true,
808+ true,
809+ {0, 0},
810+ 0,
811+ mir_pixel_format_abgr_8888,
812+ mir_power_mode_on,
813+ mir_orientation_normal
814+ }
815+ ));
816+}
817+
818+TEST_F(PostHWC10Tests, display_configuration_matches_expectations_on_external_display)
819+{
820+ using namespace testing;
821+ this->setup_display_config();
822+ auto device = make_hwc_device<mga::HwcDevice>(this->mock_device, this->mock_fbdev, this->mock_vsync);
823+
824+ EXPECT_THAT(
825+ device->get_output_configuration(this->external),
826+ Eq(
827+ mg::DisplayConfigurationOutput
828+ {
829+ this->external,
830+ mg::DisplayConfigurationCardId{0},
831+ mg::DisplayConfigurationOutputType::hdmia,
832+ {mir_pixel_format_abgr_8888},
833+ {{{1920, 1200}, 60}},
834+ 0,
835+ {406, 254},
836+ true,
837+ true,
838+ {0, 0},
839+ 0,
840+ mir_pixel_format_abgr_8888,
841+ mir_power_mode_on,
842+ mir_orientation_normal
843+ }
844+ ));
845+}
846+
847+TEST_F(PostHWC10Tests, queries_egl_configuration)
848+{
849+ using namespace testing;
850+ this->setup_display_config();
851+ this->setup_egl_configs();
852+ auto device = make_hwc_device<mga::HwcDevice>(this->mock_device, this->mock_fbdev, this->mock_vsync);
853+
854+ EXPECT_CALL(mock_egl,eglChooseConfig(_,_,_,_,_)).Times(1);
855+ EXPECT_CALL(mock_egl,eglGetConfigAttrib(_,_,EGL_NATIVE_VISUAL_ID,_)).Times(3);
856+
857+ device->get_output_configuration(this->primary);
858+}
859+
860+TEST_F(PostHWC10Tests, converts_egl_configs_to_mir_pixel_formats)
861+{
862+ using namespace testing;
863+ this->setup_display_config();
864+ this->setup_egl_configs();
865+ auto device = make_hwc_device<mga::HwcDevice>(this->mock_device, this->mock_fbdev, this->mock_vsync);
866+
867+ EXPECT_THAT(
868+ device->get_output_configuration(this->primary).pixel_formats,
869+ Eq(std::vector<MirPixelFormat>({mir_pixel_format_abgr_8888, mir_pixel_format_xbgr_8888}))
870+ );
871+}
872+
873+TEST_F(HWC10Tests, display_configuration_matches_expectations)
874+{
875+ using namespace testing;
876+ auto device = make_hwc_device<mga::HwcFbDevice>(this->mock_device, this->mock_fbdev, this->mock_vsync);
877+
878+ EXPECT_THAT(
879+ device->get_output_configuration(this->primary),
880+ Eq(
881+ mg::DisplayConfigurationOutput
882+ {
883+ this->primary,
884+ mg::DisplayConfigurationCardId{0},
885+ mg::DisplayConfigurationOutputType::lvds,
886+ {mir_pixel_format_xbgr_8888},
887+ {{{900, 600}, 67.6f}},
888+ 0,
889+ {57, 38},
890+ true,
891+ true,
892+ {0, 0},
893+ 0,
894+ mir_pixel_format_xbgr_8888,
895+ mir_power_mode_on,
896+ mir_orientation_normal
897+ })
898+ );
899+}

Subscribers

People subscribed via source and target branches