Mir

Merge lp:~raof/mir/plumb-through-edid into lp:mir

Proposed by Chris Halse Rogers on 2016-11-29
Status: Merged
Approved by: Alan Griffiths on 2016-11-30
Approved revision: 3860
Merged at revision: 3855
Proposed branch: lp:~raof/mir/plumb-through-edid
Merge into: lp:mir
Diff against target: 958 lines (+380/-55)
29 files modified
include/client/mir_toolkit/mir_display_configuration.h (+16/-0)
include/platform/mir/graphics/display_configuration.h (+4/-0)
src/client/display_configuration_api.cpp (+9/-0)
src/client/symbols.map (+1/-0)
src/platform/graphics/display_configuration.cpp (+2/-1)
src/platforms/android/server/display_configuration.cpp (+2/-1)
src/platforms/android/server/fb_device.cpp (+2/-1)
src/platforms/android/server/hwc_blanking_control.cpp (+2/-1)
src/platforms/common/server/kms-utils/drm_mode_resources.cpp (+5/-0)
src/platforms/common/server/kms-utils/drm_mode_resources.h (+1/-0)
src/platforms/mesa/server/kms/real_kms_display_configuration.cpp (+90/-1)
src/platforms/mesa/server/x11/graphics/display_configuration.cpp (+2/-1)
src/protobuf/mir_protobuf.proto (+1/-0)
src/server/frontend/protobuf_buffer_packer.cpp (+10/-0)
src/server/graphics/nested/nested_display_configuration.cpp (+4/-2)
src/utils/out.c (+16/-0)
tests/acceptance-tests/test_new_display_configuration.cpp (+157/-22)
tests/include/mir/test/doubles/mock_drm.h (+3/-0)
tests/mir_test/display_config_matchers.cpp (+6/-3)
tests/mir_test_doubles/mock_drm.cpp (+5/-0)
tests/mir_test_doubles/stub_display_configuration.cpp (+8/-4)
tests/unit-tests/graphics/test_default_display_configuration_policy.cpp (+2/-1)
tests/unit-tests/graphics/test_display_configuration.cpp (+2/-1)
tests/unit-tests/graphics/test_overlapping_output_grouping.cpp (+2/-1)
tests/unit-tests/input/android/test_android_input_lexicon.cpp (+1/-1)
tests/unit-tests/input/test_input_event.cpp (+1/-1)
tests/unit-tests/platforms/mesa/kms/test_cursor.cpp (+6/-3)
tests/unit-tests/platforms/mesa/kms/test_display_configuration.cpp (+18/-9)
tests/unit-tests/scene/test_mediating_display_changer.cpp (+2/-1)
To merge this branch: bzr merge lp:~raof/mir/plumb-through-edid
Reviewer Review Type Date Requested Status
Alan Griffiths 2016-11-29 Approve on 2016-11-30
Daniel van Vugt Approve on 2016-11-30
Mir CI Bot continuous-integration Approve on 2016-11-30
Gerry Boland Needs Information on 2016-11-29
Review via email: mp+312008@code.launchpad.net

Commit Message

Add an EDID accessor to client and server display configuration.

This will likely want to be augmented with some structured data extracted
from the EDID, so that clients and servers don't have to include an EDID
parser to get output display name, unique IDs, and so on, and we can
provide some sensible values in cases where the output doesn't have an
EDID.

There are potentially interesting things in the EDID that we don't need
to provide a separate facility for, so providing the EDID is still useful
even once we have structured data available for those users that want it.

To post a comment you must log in.
Mir CI Bot (mir-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
lp:~raof/mir/plumb-through-edid updated on 2016-11-29
3859. By Chris Halse Rogers on 2016-11-29

Don't leak the MirDisplayConfig in the tests

Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:3859
https://mir-jenkins.ubuntu.com/job/mir-ci/2279/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/2957/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/3022
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/3014
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/3014
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/3014
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2986
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2986/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2986
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2986/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2986
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2986/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2986/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2986/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2986
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2986/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://mir-jenkins.ubuntu.com/job/mir-ci/2279/rebuild

review: Needs Fixing (continuous-integration)
Alan Griffiths (alan-griffiths) wrote :

06:38:42 /<<BUILDDIR>>/mir-0.25.0+vivid3014bzr3859/tests/acceptance-tests/test_new_display_configuration.cpp:108:38: error: missing initializer for member ���DisplayConfigurationTest::NotifyingConfigurationObserver::Expectation::notifier��� [-Werror=missing-field-initializers]
06:38:42 expectations.push_back({});
06:38:42 ^
06:38:42 /<<BUILDDIR>>/mir-0.25.0+vivid3014bzr3859/tests/acceptance-tests/test_new_display_configuration.cpp:108:38: error: missing initializer for member ���DisplayConfigurationTest::NotifyingConfigurationObserver::Expectation::value��� [-Werror=missing-field-initializers]

I guess this belongs.

Otherwise mostly looks OK

review: Needs Fixing
Alan Griffiths (alan-griffiths) wrote :

+ size_t const min_edid_size = 128;

could be static constexpr

Gerry Boland (gerboland) wrote :

+uint8_t const* mir_output_get_edid(MirOutput const* output);
+ * \returns A pointer to the start of the raw EDID data.
Stupid question, but how do I as an api user know where the end of the raw EDIT output is?

review: Needs Information
Gerry Boland (gerboland) wrote :

> +uint8_t const* mir_output_get_edid(MirOutput const* output);
> + * \returns A pointer to the start of the raw EDID data.
> Stupid question, but how do I as an api user know where the end of the raw
> EDIT output is?
I safe assume it is 128 bytes long, and then a parser can read more if it knows about extensions?

Alan Griffiths (alan-griffiths) wrote :

> > +uint8_t const* mir_output_get_edid(MirOutput const* output);
> > + * \returns A pointer to the start of the raw EDID data.
> > Stupid question, but how do I as an api user know where the end of the raw
> > EDIT output is?
> I safe assume it is 128 bytes long, and then a parser can read more if it
> knows about extensions?

That's my reading.

Chris Halse Rogers (raof) wrote :

On Tue, Nov 29, 2016 at 10:16 PM, Gerry Boland
<email address hidden> wrote:
>> +uint8_t const* mir_output_get_edid(MirOutput const* output);
>> + * \returns A pointer to the start of the raw EDID data.
>> Stupid question, but how do I as an api user know where the end of
>> the raw
>> EDIT output is?
> I safe assume it is 128 bytes long, and then a parser can read more
> if it knows about extensions?

Yes. Byte 127 of the EDID is the number of subsequent extensions.

It is safe to assume the EDID is 128 bytes. Do you have any suggestions
for how the comment could be made clearer?

lp:~raof/mir/plumb-through-edid updated on 2016-11-30
3860. By Chris Halse Rogers on 2016-11-30

Hand-hold Vivid-era compilers

Mir CI Bot (mir-ci-bot) wrote :

PASSED: Continuous integration, rev:3860
https://mir-jenkins.ubuntu.com/job/mir-ci/2283/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/2966
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/3031
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/3023
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/3023
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/3023
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2995
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2995/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2995
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2995/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2995
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2995/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2995
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2995/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2995
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2995/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2995
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2995/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://mir-jenkins.ubuntu.com/job/mir-ci/2283/rebuild

review: Approve (continuous-integration)
Daniel van Vugt (vanvugt) wrote :

Cool.

Week needs fixing:
* Platform ABI break needs bumping due to include/platform/mir/graphics/display_configuration.h
* mir_output_get_edid should in future be accompanied by some nice string helper functions like mir_output_get_vendor / mir_output_get_model. That frees most toolkits from needing to decode the EDID and also frees us to implement non-EDID lookups for such strings.

review: Approve
Daniel van Vugt (vanvugt) wrote :

*Weak needs fixing*

Alan Griffiths (alan-griffiths) wrote :

Nice

review: Approve
Gerry Boland (gerboland) wrote :

> Yes. Byte 127 of the EDID is the number of subsequent extensions.
>
> It is safe to assume the EDID is 128 bytes. Do you have any suggestions
> for how the comment could be made clearer?

No it's ok.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'include/client/mir_toolkit/mir_display_configuration.h'
2--- include/client/mir_toolkit/mir_display_configuration.h 2016-10-31 02:37:31 +0000
3+++ include/client/mir_toolkit/mir_display_configuration.h 2016-11-30 01:53:28 +0000
4@@ -520,6 +520,22 @@
5 uint32_t size);
6
7 /**
8+ * Get the raw EDID data of a display.
9+ *
10+ * This returns a pointer to the start of the raw, unparsed EDID data.
11+ * Some displays or connection types may not provide EDID data. In that case,
12+ * this returns NULL.
13+ *
14+ * An EDID is always at least 128 bytes, but may be longer in the presence of extensions.
15+ *
16+ * \param [in] output The MirOutput to query
17+ * \returns A pointer to the start of the raw EDID data.
18+ * This pointer remains valid as long as the MirOutput remains valid.
19+ * Returns NULL if there is no EDID available.
20+ */
21+uint8_t const* mir_output_get_edid(MirOutput const* output);
22+
23+/**
24 * Get the width, in pixels, of a MirOutputMode
25 *
26 * \note This is unaffected by the orientation of the output
27
28=== modified file 'include/platform/mir/graphics/display_configuration.h'
29--- include/platform/mir/graphics/display_configuration.h 2016-11-11 07:56:09 +0000
30+++ include/platform/mir/graphics/display_configuration.h 2016-11-30 01:53:28 +0000
31@@ -127,6 +127,9 @@
32 GammaCurves gamma;
33 MirOutputGammaSupported gamma_supported;
34
35+ /** EDID of the display, if non-empty */
36+ std::vector<uint8_t> edid;
37+
38 /** The logical rectangle occupied by the output, based on its position,
39 current mode and orientation (rotation) */
40 geometry::Rectangle extents() const;
41@@ -158,6 +161,7 @@
42 MirSubpixelArrangement& subpixel_arrangement;
43 GammaCurves& gamma;
44 MirOutputGammaSupported const& gamma_supported;
45+ std::vector<uint8_t const> const& edid;
46
47 UserDisplayConfigurationOutput(DisplayConfigurationOutput& master);
48 geometry::Rectangle extents() const;
49
50=== modified file 'src/client/display_configuration_api.cpp'
51--- src/client/display_configuration_api.cpp 2016-11-24 11:31:05 +0000
52+++ src/client/display_configuration_api.cpp 2016-11-30 01:53:28 +0000
53@@ -357,3 +357,12 @@
54
55 return mode->refresh_rate();
56 }
57+
58+uint8_t const* mir_output_get_edid(MirOutput const* output)
59+{
60+ if (output->has_edid())
61+ {
62+ return reinterpret_cast<uint8_t const*>(output->edid().data());
63+ }
64+ return nullptr;
65+}
66
67=== modified file 'src/client/symbols.map'
68--- src/client/symbols.map 2016-11-28 21:14:43 +0000
69+++ src/client/symbols.map 2016-11-30 01:53:28 +0000
70@@ -472,6 +472,7 @@
71 mir_input_device_get_mutable_touchpad_configuration;
72 mir_input_device_get_pointer_configuration;
73 mir_input_device_get_touchpad_configuration;
74+ mir_output_get_edid;
75 mir_pointer_configuration_get_acceleration;
76 mir_pointer_configuration_get_acceleration_bias;
77 mir_pointer_configuration_get_handedness;
78
79=== modified file 'src/platform/graphics/display_configuration.cpp'
80--- src/platform/graphics/display_configuration.cpp 2016-10-31 02:37:31 +0000
81+++ src/platform/graphics/display_configuration.cpp 2016-11-30 01:53:28 +0000
82@@ -296,7 +296,8 @@
83 form_factor(master.form_factor),
84 subpixel_arrangement(master.subpixel_arrangement),
85 gamma(master.gamma),
86- gamma_supported(master.gamma_supported)
87+ gamma_supported(master.gamma_supported),
88+ edid(*reinterpret_cast<std::vector<uint8_t const>*>(&master.edid))
89 {
90 }
91
92
93=== modified file 'src/platforms/android/server/display_configuration.cpp'
94--- src/platforms/android/server/display_configuration.cpp 2016-11-11 07:56:09 +0000
95+++ src/platforms/android/server/display_configuration.cpp 2016-11-30 01:53:28 +0000
96@@ -68,7 +68,8 @@
97 form_factor,
98 subpixel_arrangement,
99 {},
100- mir_output_gamma_unsupported
101+ mir_output_gamma_unsupported,
102+ {}
103 };
104 }
105 }
106
107=== modified file 'src/platforms/android/server/fb_device.cpp'
108--- src/platforms/android/server/fb_device.cpp 2016-10-31 02:37:31 +0000
109+++ src/platforms/android/server/fb_device.cpp 2016-11-30 01:53:28 +0000
110@@ -91,7 +91,8 @@
111 mir_form_factor_phone,
112 mir_subpixel_arrangement_unknown,
113 {},
114- mir_output_gamma_unsupported
115+ mir_output_gamma_unsupported,
116+ {}
117 };
118 }
119
120
121=== modified file 'src/platforms/android/server/hwc_blanking_control.cpp'
122--- src/platforms/android/server/hwc_blanking_control.cpp 2016-11-11 07:56:09 +0000
123+++ src/platforms/android/server/hwc_blanking_control.cpp 2016-11-30 01:53:28 +0000
124@@ -178,7 +178,8 @@
125 form_factor,
126 mir_subpixel_arrangement_unknown,
127 {},
128- mir_output_gamma_unsupported
129+ mir_output_gamma_unsupported,
130+ {}
131 };
132 }
133
134
135=== modified file 'src/platforms/common/server/kms-utils/drm_mode_resources.cpp'
136--- src/platforms/common/server/kms-utils/drm_mode_resources.cpp 2016-07-18 07:38:38 +0000
137+++ src/platforms/common/server/kms-utils/drm_mode_resources.cpp 2016-11-30 01:53:28 +0000
138@@ -291,6 +291,11 @@
139 return properties_table.at(property_name).id;
140 }
141
142+bool mgk::ObjectProperties::has_property(char const* property_name) const
143+{
144+ return properties_table.count(property_name) > 0;
145+}
146+
147 auto mgk::ObjectProperties::begin() const -> std::unordered_map<std::string, Prop>::const_iterator
148 {
149 return properties_table.begin();
150
151=== modified file 'src/platforms/common/server/kms-utils/drm_mode_resources.h'
152--- src/platforms/common/server/kms-utils/drm_mode_resources.h 2016-07-18 07:38:38 +0000
153+++ src/platforms/common/server/kms-utils/drm_mode_resources.h 2016-11-30 01:53:28 +0000
154@@ -110,6 +110,7 @@
155
156 uint64_t operator[](char const* name) const;
157 uint32_t id_for(char const* property_name) const;
158+ bool has_property(char const* property_name) const;
159
160 std::unordered_map<std::string, Prop>::const_iterator begin() const;
161 std::unordered_map<std::string, Prop>::const_iterator end() const;
162
163=== modified file 'src/platforms/mesa/server/kms/real_kms_display_configuration.cpp'
164--- src/platforms/mesa/server/kms/real_kms_display_configuration.cpp 2016-11-11 06:59:42 +0000
165+++ src/platforms/mesa/server/kms/real_kms_display_configuration.cpp 2016-11-30 01:53:28 +0000
166@@ -19,6 +19,7 @@
167 #include "real_kms_display_configuration.h"
168 #include "kms-utils/drm_mode_resources.h"
169 #include "mir/graphics/pixel_format_utils.h"
170+#include "mir/log.h"
171
172 #include <cmath>
173 #include <limits>
174@@ -27,9 +28,11 @@
175 #include <stdexcept>
176 #include <algorithm>
177 #include <system_error>
178+#include <cstring>
179
180 namespace mg = mir::graphics;
181 namespace mgm = mir::graphics::mesa;
182+namespace mgk = mir::graphics::kms;
183 namespace geom = mir::geometry;
184
185 namespace
186@@ -209,6 +212,83 @@
187 });
188 }
189
190+namespace
191+{
192+std::vector<uint8_t> edid_for_connector(int drm_fd, uint32_t connector_id)
193+{
194+ std::vector<uint8_t> edid;
195+
196+ mgk::ObjectProperties connector_props{
197+ drm_fd, connector_id, DRM_MODE_OBJECT_CONNECTOR};
198+
199+ if (connector_props.has_property("EDID"))
200+ {
201+ /*
202+ * We don't technically need the property information here, but query it
203+ * anyway so we can detect if our assumptions about DRM behaviour
204+ * become invalid.
205+ */
206+ auto property = mgk::DRMModePropertyUPtr{
207+ drmModeGetProperty(drm_fd, connector_props.id_for("EDID")),
208+ &drmModeFreeProperty};
209+
210+ if (!property)
211+ {
212+ mir::log_warning(
213+ "Failed to get EDID property for connector %u: %i (%s)",
214+ connector_id,
215+ errno,
216+ ::strerror(errno));
217+ return edid;
218+ }
219+
220+ if (!drm_property_type_is(property.get(), DRM_MODE_PROP_BLOB))
221+ {
222+ mir::log_warning(
223+ "EDID property on connector %u has unexpected type %u",
224+ connector_id,
225+ property->flags);
226+ return edid;
227+ }
228+
229+ // A property ID of 0 means invalid.
230+ if (connector_props["EDID"] == 0)
231+ {
232+ /*
233+ * Log a debug message only. This will trigger for broken monitors which
234+ * don't provide an EDID, which is not as unusual as you might think...
235+ */
236+ mir::log_debug("No EDID data available on connector %u", connector_id);
237+ return edid;
238+ }
239+
240+ auto blob = drmModeGetPropertyBlob(drm_fd, connector_props["EDID"]);
241+
242+ if (!blob)
243+ {
244+ mir::log_warning(
245+ "Failed to get EDID property blob for connector %u: %i (%s)",
246+ connector_id,
247+ errno,
248+ ::strerror(errno));
249+
250+ return edid;
251+ }
252+
253+ edid.reserve(blob->length);
254+ edid.insert(edid.begin(),
255+ reinterpret_cast<uint8_t*>(blob->data),
256+ reinterpret_cast<uint8_t*>(blob->data) + blob->length);
257+
258+ drmModeFreePropertyBlob(blob);
259+
260+ edid.shrink_to_fit();
261+ }
262+
263+ return edid;
264+}
265+}
266+
267 void mgm::RealKMSDisplayConfiguration::add_or_update_output(
268 kms::DRMModeResources const& resources,
269 drmModeConnector const& connector)
270@@ -226,6 +306,15 @@
271 std::vector<MirPixelFormat> formats {mir_pixel_format_argb_8888,
272 mir_pixel_format_xrgb_8888};
273
274+ std::vector<uint8_t> edid;
275+ if (connected)
276+ {
277+ /* Only ask for the EDID on connected outputs. There's obviously no monitor EDID
278+ * when there is no monitor connected!
279+ */
280+ edid = edid_for_connector(drm_fd, connector.connector_id);
281+ }
282+
283 drmModeModeInfo current_mode_info = drmModeModeInfo();
284 GammaCurves gamma;
285
286@@ -271,7 +360,7 @@
287 mir_power_mode_on, mir_orientation_normal,
288 1.0f, mir_form_factor_monitor,
289 kms_subpixel_to_mir_subpixel(connector.subpixel),
290- gamma, mir_output_gamma_supported});
291+ gamma, mir_output_gamma_supported, std::move(edid)});
292 }
293 else
294 {
295
296=== modified file 'src/platforms/mesa/server/x11/graphics/display_configuration.cpp'
297--- src/platforms/mesa/server/x11/graphics/display_configuration.cpp 2016-10-31 02:37:31 +0000
298+++ src/platforms/mesa/server/x11/graphics/display_configuration.cpp 2016-11-30 01:53:28 +0000
299@@ -47,7 +47,8 @@
300 mir_form_factor_monitor,
301 mir_subpixel_arrangement_unknown,
302 {},
303- mir_output_gamma_unsupported},
304+ mir_output_gamma_unsupported,
305+ {}},
306 card{mg::DisplayConfigurationCardId{0}, 1}
307 {
308 }
309
310=== modified file 'src/protobuf/mir_protobuf.proto'
311--- src/protobuf/mir_protobuf.proto 2016-11-15 20:53:57 +0000
312+++ src/protobuf/mir_protobuf.proto 2016-11-30 01:53:28 +0000
313@@ -235,6 +235,7 @@
314 optional bytes gamma_green = 21;
315 optional bytes gamma_blue = 22;
316 optional uint32 gamma_supported = 23;
317+ optional bytes edid = 24;
318 }
319
320 message Connection {
321
322=== modified file 'src/server/frontend/protobuf_buffer_packer.cpp'
323--- src/server/frontend/protobuf_buffer_packer.cpp 2016-10-31 02:37:31 +0000
324+++ src/server/frontend/protobuf_buffer_packer.cpp 2016-11-30 01:53:28 +0000
325@@ -77,6 +77,16 @@
326 display_output.gamma.green.size() * sizeof(uint16_t) / sizeof(char));
327 protobuf_output.set_gamma_blue(reinterpret_cast<int8_t const*>(display_output.gamma.blue.data()),
328 display_output.gamma.blue.size() * sizeof(uint16_t) / sizeof(char));
329+
330+ /*
331+ * Extra sanity check; the EDID header is 128 bytes, so a valid EDID must be
332+ * at least that big.
333+ */
334+ size_t const min_edid_size = 128;
335+ if (display_output.edid.size() >= min_edid_size)
336+ {
337+ protobuf_output.set_edid(display_output.edid.data(), display_output.edid.size());
338+ }
339 }
340
341 }
342
343=== modified file 'src/server/graphics/nested/nested_display_configuration.cpp'
344--- src/server/graphics/nested/nested_display_configuration.cpp 2016-10-31 02:37:31 +0000
345+++ src/server/graphics/nested/nested_display_configuration.cpp 2016-11-30 01:53:28 +0000
346@@ -113,7 +113,8 @@
347 local_config.form_factor,
348 local_config.subpixel_arrangement,
349 local_config.gamma,
350- local_config.gamma_supported
351+ local_config.gamma_supported,
352+ {}
353 };
354
355 f(output);
356@@ -174,7 +175,8 @@
357 local_config.form_factor,
358 local_config.subpixel_arrangement,
359 local_config.gamma,
360- local_config.gamma_supported
361+ local_config.gamma_supported,
362+ {}
363 };
364 UserDisplayConfigurationOutput user(output);
365
366
367=== modified file 'src/utils/out.c'
368--- src/utils/out.c 2016-11-22 04:18:38 +0000
369+++ src/utils/out.c 2016-11-30 01:53:28 +0000
370@@ -456,6 +456,22 @@
371 }
372 printf("\n");
373
374+ uint8_t const* edid = mir_output_get_edid(out);
375+ if (edid)
376+ {
377+ printf("EDID:");
378+ /* The EDID is guaranteed to be at least 128 bytes */
379+ for (int i = 0; i < 128 ; ++i)
380+ {
381+ if ((i % 16) == 0)
382+ {
383+ printf("\n\t");
384+ }
385+ printf("%.2hhx", edid[i]);
386+ }
387+ printf("\n");
388+ }
389+
390 int const num_modes = mir_output_get_num_modes(out);
391 int const current_mode_index =
392 mir_output_get_current_mode_index(out);
393
394=== modified file 'tests/acceptance-tests/test_new_display_configuration.cpp'
395--- tests/acceptance-tests/test_new_display_configuration.cpp 2016-11-24 10:04:35 +0000
396+++ tests/acceptance-tests/test_new_display_configuration.cpp 2016-11-30 01:53:28 +0000
397@@ -22,6 +22,8 @@
398 #include "mir/frontend/session_authorizer.h"
399 #include "mir/graphics/event_handler_register.h"
400 #include "mir/shell/display_configuration_controller.h"
401+#include "mir/graphics/display_configuration_observer.h"
402+#include "mir/observer_registrar.h"
403
404 #include "mir_test_framework/connected_client_with_a_surface.h"
405 #include "mir/test/doubles/null_platform.h"
406@@ -34,7 +36,6 @@
407 #include "mir/test/fake_shared.h"
408 #include "mir/test/pipe.h"
409 #include "mir/test/signal.h"
410-#include "mir/test/signal.h"
411
412 #include "mir_toolkit/mir_client_library.h"
413
414@@ -43,6 +44,7 @@
415
416 #include <gmock/gmock.h>
417 #include <gtest/gtest.h>
418+#include <future>
419
420 namespace mg = mir::graphics;
421 namespace geom = mir::geometry;
422@@ -92,39 +94,98 @@
423 std::atomic<bool> allow_configure_display{true};
424 std::atomic<bool> allow_set_base_display_configuration{true};
425 };
426-
427-void wait_for_server_actions_to_finish(mir::ServerActionQueue& server_action_queue)
428-{
429- mt::Signal last_action_done;
430- server_action_queue.enqueue(
431- &last_action_done,
432- [&] { last_action_done.raise(); });
433-
434- last_action_done.wait_for(std::chrono::seconds{5});
435-}
436 }
437
438 struct DisplayConfigurationTest : mtf::ConnectedClientWithASurface
439 {
440+ class NotifyingConfigurationObserver : public mg::DisplayConfigurationObserver
441+ {
442+ public:
443+ std::future<void> expect_configuration_change(
444+ std::shared_ptr<mg::DisplayConfiguration const> const& configuration)
445+ {
446+ std::lock_guard<decltype(guard)> lock{guard};
447+ expectations.push_back({{}, configuration});
448+ return expectations.back().notifier.get_future();
449+ }
450+
451+ protected:
452+ void initial_configuration(
453+ std::shared_ptr<mg::DisplayConfiguration const> const&) override
454+ {
455+ }
456+
457+ void configuration_applied(
458+ std::shared_ptr<mg::DisplayConfiguration const> const& config) override
459+ {
460+ std::lock_guard<decltype(guard)> lock{guard};
461+ auto match = std::find_if(
462+ expectations.begin(),
463+ expectations.end(),
464+ [config](auto const& candidate)
465+ {
466+ return *config == *candidate.value;
467+ });
468+
469+ if (match != expectations.end())
470+ {
471+ match->notifier.set_value();
472+ expectations.erase(match);
473+ }
474+ }
475+
476+ void base_configuration_updated(
477+ std::shared_ptr<mg::DisplayConfiguration const> const&) override
478+ {
479+ }
480+
481+ void configuration_failed(
482+ std::shared_ptr<mg::DisplayConfiguration const> const&,
483+ std::exception const&) override
484+ {
485+ }
486+
487+ void catastrophic_configuration_error(
488+ std::shared_ptr<mg::DisplayConfiguration const> const&,
489+ std::exception const&) override
490+ {
491+ }
492+
493+ private:
494+ struct Expectation
495+ {
496+ std::promise<void> notifier;
497+ std::shared_ptr<mg::DisplayConfiguration const> value;
498+ };
499+
500+ std::mutex mutable guard;
501+ std::vector<Expectation> expectations;
502+ };
503+
504 void SetUp() override
505 {
506 server.override_the_session_authorizer([this] { return mt::fake_shared(stub_authorizer); });
507 preset_display(mt::fake_shared(mock_display));
508 mtf::ConnectedClientWithASurface::SetUp();
509+
510+ server.the_display_configuration_observer_registrar()->register_interest(observer);
511 }
512
513 void apply_config_change_and_wait_for_propagation(
514 std::shared_ptr<mg::DisplayConfiguration> const& new_config)
515 {
516- mock_display.emit_configuration_change_event(new_config);
517- // This waits until the configuration change event has propagated to MediatingDisplayChanger...
518- mock_display.wait_for_configuration_change_handler();
519- // ...and MediatingDisplayChanger will defer *actually* processing this to the mainloop,
520- // so wait until that has been processed before returning.
521- wait_for_server_actions_to_finish(*server.the_main_loop());
522+ auto future = observer->expect_configuration_change(new_config);
523+
524+ server.the_display_configuration_controller()->set_base_configuration(new_config);
525+
526+ if (future.wait_for(std::chrono::seconds{10}) != std::future_status::ready)
527+ {
528+ BOOST_THROW_EXCEPTION(std::runtime_error{"Timeout waiting for display configuration to apply"});
529+ }
530 }
531
532 testing::NiceMock<MockDisplay> mock_display;
533+ std::shared_ptr<NotifyingConfigurationObserver> observer{std::make_shared<NotifyingConfigurationObserver>()};
534 StubAuthorizer stub_authorizer;
535 };
536
537@@ -311,11 +372,7 @@
538 output.power_mode = mode;
539 });
540
541- // We don't use apply_config_change_and_wait_for_propagation() here as
542- // that simulates a hardware change to which the default configuration policy
543- // will be applied... and that switches all the enabled monitors on!
544- server.the_display_configuration_controller()->set_base_configuration(server_config);
545- wait_for_server_actions_to_finish(*server.the_main_loop());
546+ apply_config_change_and_wait_for_propagation(server_config);
547
548 DisplayClient client{new_connection()};
549
550@@ -952,6 +1009,84 @@
551
552 namespace
553 {
554+MATCHER_P(PointsToIdenticalData, data, "")
555+{
556+ return arg == nullptr ? false : memcmp(arg, data.data(), data.size()) == 0;
557+}
558+}
559+
560+TEST_F(DisplayConfigurationTest, client_receives_null_for_empty_edid)
561+{
562+ mtd::StubDisplayConfigurationOutput monitor{
563+ mg::DisplayConfigurationOutputId{2},
564+ {{{3210, 2800}, 60.0}},
565+ {mir_pixel_format_abgr_8888}};
566+ monitor.edid = {};
567+
568+ auto config = std::make_shared<mtd::StubDisplayConfig>(std::vector<mg::DisplayConfigurationOutput>{monitor});
569+
570+ apply_config_change_and_wait_for_propagation(config);
571+
572+ DisplayClient client{new_connection()};
573+ client.connect();
574+
575+ auto configuration = client.get_base_config();
576+
577+ auto output = mir_display_config_get_output(configuration.get(), 0);
578+
579+ EXPECT_THAT(mir_output_get_edid(output), IsNull());
580+
581+ client.disconnect();
582+}
583+
584+TEST_F(DisplayConfigurationTest, client_receives_edid)
585+{
586+ /*
587+ * Valid EDID block in case we later do some parsing/quirking/validation.
588+ */
589+ std::vector<uint8_t> edid{
590+ 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff,
591+ 0xaf, 0x06, 0x11, 0x3d, 0x00, 0x00, 0x00, 0x00,
592+ 0x16, 0x00, 0x04, 0x01, 0x1f, 0x95, 0x78, 0x11,
593+ 0x87, 0x02, 0xa4, 0xe5, 0x50, 0x56, 0x26, 0x9e,
594+ 0x50, 0x0d, 0x00, 0x54, 0x00, 0x00, 0x01, 0x01,
595+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
596+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x37, 0x14,
597+ 0xb8, 0x80, 0x38, 0x70, 0x40, 0x24, 0x10, 0x10,
598+ 0x00, 0x3e, 0xad, 0x35, 0x00, 0x10, 0x18, 0x00,
599+ 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
600+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
601+ 0x20, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x41, 0x00,
602+ 0x4f, 0x55, 0x20, 0x0a, 0x20, 0x20, 0x20, 0x20,
603+ 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0xfe, 0x00,
604+ 0x42, 0x00, 0x34, 0x31, 0x48, 0x30, 0x4e, 0x41,
605+ 0x31, 0x30, 0x31, 0x2e, 0x0a, 0x20, 0xa5, 0x00
606+ };
607+
608+ mtd::StubDisplayConfigurationOutput monitor{
609+ mg::DisplayConfigurationOutputId{2},
610+ {{{3210, 2800}, 60.0}},
611+ {mir_pixel_format_abgr_8888}};
612+ monitor.edid = edid;
613+
614+ auto config = std::make_shared<mtd::StubDisplayConfig>(std::vector<mg::DisplayConfigurationOutput>{monitor});
615+
616+ apply_config_change_and_wait_for_propagation(config);
617+
618+ DisplayClient client{new_connection()};
619+ client.connect();
620+
621+ auto configuration = client.get_base_config();
622+
623+ auto output = mir_display_config_get_output(configuration.get(), 0);
624+
625+ EXPECT_THAT(mir_output_get_edid(output), PointsToIdenticalData(edid));
626+
627+ client.disconnect();
628+}
629+
630+namespace
631+{
632 MATCHER_P(IsSameModeAs, mode, "")
633 {
634 return mir_output_mode_get_height(arg) == mir_output_mode_get_height(mode) &&
635
636=== modified file 'tests/include/mir/test/doubles/mock_drm.h'
637--- tests/include/mir/test/doubles/mock_drm.h 2016-09-08 02:58:56 +0000
638+++ tests/include/mir/test/doubles/mock_drm.h 2016-11-30 01:53:28 +0000
639@@ -155,6 +155,9 @@
640 uint16_t* red, uint16_t* green, uint16_t* blue));
641
642 FakeDRMResources fake_drm;
643+
644+private:
645+ drmModeObjectProperties empty_object_props;
646 };
647
648 }
649
650=== modified file 'tests/mir_test/display_config_matchers.cpp'
651--- tests/mir_test/display_config_matchers.cpp 2016-10-31 02:37:31 +0000
652+++ tests/mir_test/display_config_matchers.cpp 2016-11-30 01:53:28 +0000
653@@ -87,7 +87,8 @@
654 mir_form_factor_monitor,
655 mir_subpixel_arrangement_unknown,
656 {},
657- mir_output_gamma_unsupported
658+ mir_output_gamma_unsupported,
659+ {}
660 };
661
662 /* Modes */
663@@ -158,7 +159,8 @@
664 mir_form_factor_monitor,
665 mir_subpixel_arrangement_unknown,
666 {},
667- mir_output_gamma_unsupported
668+ mir_output_gamma_unsupported,
669+ {}
670 };
671
672 /* Modes */
673@@ -222,7 +224,8 @@
674 mir_form_factor_monitor,
675 mir_subpixel_arrangement_unknown,
676 {},
677- mir_output_gamma_unsupported
678+ mir_output_gamma_unsupported,
679+ {}
680 };
681
682 /* Modes */
683
684=== modified file 'tests/mir_test_doubles/mock_drm.cpp'
685--- tests/mir_test_doubles/mock_drm.cpp 2016-09-08 02:58:56 +0000
686+++ tests/mir_test_doubles/mock_drm.cpp 2016-11-30 01:53:28 +0000
687@@ -236,6 +236,8 @@
688
689 global_mock = this;
690
691+ memset(&empty_object_props, 0, sizeof(empty_object_props));
692+
693 ON_CALL(*this, open(_,_,_))
694 .WillByDefault(Return(fake_drm.fd()));
695
696@@ -257,6 +259,9 @@
697 ON_CALL(*this, drmModeGetConnector(_, _))
698 .WillByDefault(WithArgs<1>(Invoke(&fake_drm, &FakeDRMResources::find_connector)));
699
700+ ON_CALL(*this, drmModeObjectGetProperties(_, _, _))
701+ .WillByDefault(Return(&empty_object_props));
702+
703 ON_CALL(*this, drmSetInterfaceVersion(_, _))
704 .WillByDefault(Return(0));
705
706
707=== modified file 'tests/mir_test_doubles/stub_display_configuration.cpp'
708--- tests/mir_test_doubles/stub_display_configuration.cpp 2016-10-31 02:37:31 +0000
709+++ tests/mir_test_doubles/stub_display_configuration.cpp 2016-11-30 01:53:28 +0000
710@@ -92,7 +92,8 @@
711 mir_form_factor_monitor,
712 subpixel_arrangement,
713 {},
714- mir_output_gamma_unsupported
715+ mir_output_gamma_unsupported,
716+ {}
717 }
718 {
719 }
720@@ -120,7 +121,8 @@
721 mir_form_factor_monitor,
722 mir_subpixel_arrangement_unknown,
723 {},
724- mir_output_gamma_unsupported
725+ mir_output_gamma_unsupported,
726+ {}
727 }
728 {
729 if (modes.empty())
730@@ -224,7 +226,8 @@
731 mir_form_factor_monitor,
732 mir_subpixel_arrangement_unknown,
733 {},
734- mir_output_gamma_unsupported
735+ mir_output_gamma_unsupported,
736+ {}
737 };
738
739 outputs.push_back(output);
740@@ -256,7 +259,8 @@
741 mir_form_factor_monitor,
742 mir_subpixel_arrangement_unknown,
743 {},
744- mir_output_gamma_unsupported
745+ mir_output_gamma_unsupported,
746+ {}
747 };
748
749 outputs.push_back(output);
750
751=== modified file 'tests/unit-tests/graphics/test_default_display_configuration_policy.cpp'
752--- tests/unit-tests/graphics/test_default_display_configuration_policy.cpp 2016-10-31 02:37:31 +0000
753+++ tests/unit-tests/graphics/test_default_display_configuration_policy.cpp 2016-11-30 01:53:28 +0000
754@@ -67,7 +67,8 @@
755 mir_form_factor_monitor,
756 mir_subpixel_arrangement_unknown,
757 {},
758- mir_output_gamma_unsupported
759+ mir_output_gamma_unsupported,
760+ {}
761 };
762 }
763
764
765=== modified file 'tests/unit-tests/graphics/test_display_configuration.cpp'
766--- tests/unit-tests/graphics/test_display_configuration.cpp 2016-10-31 02:37:31 +0000
767+++ tests/unit-tests/graphics/test_display_configuration.cpp 2016-11-30 01:53:28 +0000
768@@ -52,7 +52,8 @@
769 mir_form_factor_monitor,
770 mir_subpixel_arrangement_unknown,
771 {},
772- mir_output_gamma_unsupported
773+ mir_output_gamma_unsupported,
774+ {}
775 };
776
777 }
778
779=== modified file 'tests/unit-tests/graphics/test_overlapping_output_grouping.cpp'
780--- tests/unit-tests/graphics/test_overlapping_output_grouping.cpp 2016-10-31 02:37:31 +0000
781+++ tests/unit-tests/graphics/test_overlapping_output_grouping.cpp 2016-11-30 01:53:28 +0000
782@@ -99,7 +99,8 @@
783 mir_form_factor_monitor,
784 mir_subpixel_arrangement_unknown,
785 {},
786- mir_output_gamma_unsupported
787+ mir_output_gamma_unsupported,
788+ {}
789 };
790
791 f(output);
792
793=== modified file 'tests/unit-tests/input/android/test_android_input_lexicon.cpp'
794--- tests/unit-tests/input/android/test_android_input_lexicon.cpp 2016-09-22 14:36:49 +0000
795+++ tests/unit-tests/input/android/test_android_input_lexicon.cpp 2016-11-30 01:53:28 +0000
796@@ -36,7 +36,7 @@
797 const int32_t source_id = AINPUT_SOURCE_KEYBOARD;
798 const int32_t action = AKEY_EVENT_ACTION_DOWN;
799 const int32_t flags = 4;
800- const int32_t key_code = 5;
801+ const uint32_t key_code = 5;
802 const int32_t scan_code = 6;
803 const int32_t meta_state = AMETA_ALT_ON;
804 const int32_t repeat_count = 0;
805
806=== modified file 'tests/unit-tests/input/test_input_event.cpp'
807--- tests/unit-tests/input/test_input_event.cpp 2016-10-21 09:00:18 +0000
808+++ tests/unit-tests/input/test_input_event.cpp 2016-11-30 01:53:28 +0000
809@@ -145,7 +145,7 @@
810
811 TEST(TouchEventProperties, touch_id_comes_from_pointer_coordinates)
812 {
813- unsigned const touch_id = 31;
814+ int const touch_id = 31;
815 MirTouchEvent old_ev;
816
817 old_ev.set_pointer_count(1);
818
819=== modified file 'tests/unit-tests/platforms/mesa/kms/test_cursor.cpp'
820--- tests/unit-tests/platforms/mesa/kms/test_cursor.cpp 2016-10-31 02:37:31 +0000
821+++ tests/unit-tests/platforms/mesa/kms/test_cursor.cpp 2016-11-30 01:53:28 +0000
822@@ -116,7 +116,8 @@
823 mir_form_factor_monitor,
824 mir_subpixel_arrangement_unknown,
825 {},
826- mir_output_gamma_unsupported
827+ mir_output_gamma_unsupported,
828+ {}
829 },
830 {
831 mg::DisplayConfigurationOutputId{11},
832@@ -140,7 +141,8 @@
833 mir_form_factor_monitor,
834 mir_subpixel_arrangement_unknown,
835 {},
836- mir_output_gamma_unsupported
837+ mir_output_gamma_unsupported,
838+ {}
839 },
840 {
841 mg::DisplayConfigurationOutputId{12},
842@@ -164,7 +166,8 @@
843 mir_form_factor_monitor,
844 mir_subpixel_arrangement_unknown,
845 {},
846- mir_output_gamma_unsupported
847+ mir_output_gamma_unsupported,
848+ {}
849 }}}
850 {
851 }
852
853=== modified file 'tests/unit-tests/platforms/mesa/kms/test_display_configuration.cpp'
854--- tests/unit-tests/platforms/mesa/kms/test_display_configuration.cpp 2016-11-24 08:19:47 +0000
855+++ tests/unit-tests/platforms/mesa/kms/test_display_configuration.cpp 2016-11-30 01:53:28 +0000
856@@ -237,7 +237,8 @@
857 mir_form_factor_monitor,
858 mir_subpixel_arrangement_unknown,
859 {},
860- mir_output_gamma_unsupported
861+ mir_output_gamma_unsupported,
862+ {}
863 },
864 {
865 mg::DisplayConfigurationOutputId{connector1_id},
866@@ -258,7 +259,8 @@
867 mir_form_factor_monitor,
868 mir_subpixel_arrangement_unknown,
869 {},
870- mir_output_gamma_unsupported
871+ mir_output_gamma_unsupported,
872+ {}
873 },
874 {
875 mg::DisplayConfigurationOutputId{connector2_id},
876@@ -279,7 +281,8 @@
877 mir_form_factor_monitor,
878 mir_subpixel_arrangement_unknown,
879 {},
880- mir_output_gamma_unsupported
881+ mir_output_gamma_unsupported,
882+ {}
883 }
884 };
885
886@@ -589,7 +592,8 @@
887 mir_form_factor_monitor,
888 mir_subpixel_arrangement_unknown,
889 {},
890- mir_output_gamma_unsupported
891+ mir_output_gamma_unsupported,
892+ {}
893 },
894 {
895 mg::DisplayConfigurationOutputId(connector_ids[1]),
896@@ -610,7 +614,8 @@
897 mir_form_factor_monitor,
898 mir_subpixel_arrangement_unknown,
899 {},
900- mir_output_gamma_unsupported
901+ mir_output_gamma_unsupported,
902+ {}
903 },
904 };
905
906@@ -635,7 +640,8 @@
907 mir_form_factor_monitor,
908 mir_subpixel_arrangement_unknown,
909 {},
910- mir_output_gamma_unsupported
911+ mir_output_gamma_unsupported,
912+ {}
913 },
914 {
915 mg::DisplayConfigurationOutputId(connector_ids[1]),
916@@ -656,7 +662,8 @@
917 mir_form_factor_monitor,
918 mir_subpixel_arrangement_unknown,
919 {},
920- mir_output_gamma_unsupported
921+ mir_output_gamma_unsupported,
922+ {}
923 },
924 };
925
926@@ -790,7 +797,8 @@
927 mir_form_factor_monitor,
928 mir_subpixel_arrangement_unknown,
929 {},
930- mir_output_gamma_unsupported
931+ mir_output_gamma_unsupported,
932+ {}
933 },
934 };
935
936@@ -816,7 +824,8 @@
937 mir_form_factor_monitor,
938 mir_subpixel_arrangement_unknown,
939 {},
940- mir_output_gamma_unsupported
941+ mir_output_gamma_unsupported,
942+ {}
943 },
944 };
945
946
947=== modified file 'tests/unit-tests/scene/test_mediating_display_changer.cpp'
948--- tests/unit-tests/scene/test_mediating_display_changer.cpp 2016-11-25 11:34:32 +0000
949+++ tests/unit-tests/scene/test_mediating_display_changer.cpp 2016-11-30 01:53:28 +0000
950@@ -75,7 +75,8 @@
951 mir_form_factor_phone,
952 mir_subpixel_arrangement_unknown,
953 {},
954- mir_output_gamma_unsupported
955+ mir_output_gamma_unsupported,
956+ {}
957 };
958 }
959

Subscribers

People subscribed via source and target branches