Merge lp:~raof/mir/factor-out-gbm-output-surface into lp:mir
- factor-out-gbm-output-surface
- Merge into development-branch
Status: | Merged |
---|---|
Approved by: | Daniel van Vugt |
Approved revision: | no longer in the source branch. |
Merged at revision: | 4080 |
Proposed branch: | lp:~raof/mir/factor-out-gbm-output-surface |
Merge into: | lp:mir |
Diff against target: |
1521 lines (+426/-389) 12 files modified
src/platforms/mesa/server/display_helpers.cpp (+25/-0) src/platforms/mesa/server/display_helpers.h (+6/-0) src/platforms/mesa/server/kms/CMakeLists.txt (+4/-0) src/platforms/mesa/server/kms/display.cpp (+13/-6) src/platforms/mesa/server/kms/display_buffer.cpp (+89/-124) src/platforms/mesa/server/kms/display_buffer.h (+53/-34) src/platforms/mesa/server/kms/kms_output.h (+6/-2) src/platforms/mesa/server/kms/real_kms_output.cpp (+82/-4) src/platforms/mesa/server/kms/real_kms_output.h (+4/-2) tests/unit-tests/platforms/mesa/kms/mock_kms_output.h (+23/-2) tests/unit-tests/platforms/mesa/kms/test_display_buffer.cpp (+63/-197) tests/unit-tests/platforms/mesa/kms/test_real_kms_output.cpp (+58/-18) |
To merge this branch: | bzr merge lp:~raof/mir/factor-out-gbm-output-surface |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Daniel van Vugt | Approve | ||
Alan Griffiths | Approve | ||
Mir CI Bot | continuous-integration | Approve | |
Review via email: mp+318062@code.launchpad.net |
Commit message
mesa-kms: Factor out a GBMOutputSurface
This divides up the responsibility of mgm::DisplayBuffer.
mgm::GBMOutputS
mgm::KMSOutput is now responsible for allocating DRMFB objects from gbm_bo*s.
Description of the change
Mir CI Bot (mir-ci-bot) wrote : | # |
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:4055
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:4056
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:4057
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:4057
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Alan Griffiths (alan-griffiths) wrote : | # |
+mgmh::
+ : depth_buffer_
+ stencil_
+ egl_display{
+ egl_config{
+ egl_context{
+ egl_surface{
+ should_
+{
+}
A long way to write "mgmh::
Alan Griffiths (alan-griffiths) wrote : | # |
$ sudo bin/mir_demo_server --vt 4
...
[2017-02-27 12:51:06.476517] mirserver: Mir version 0.27.0
Mir fatal error: Failed to make EGL surface current
Mir fatal error: Failed to make EGL surface current
Aborted (core dumped)
Chris Halse Rogers (raof) wrote : | # |
> +mgmh::
> + : depth_buffer_
> + stencil_
> + egl_display{
> + egl_config{
> + egl_context{
> + egl_surface{
> + should_
> +{
> +}
>
> A long way to write "mgmh::
No, an incomplete move constructor - it doesn't invalidate the moved-from object, resulting in the crash.
/me notes to test *exactly* the code submitted, not just the source of the code that's being copied into the branch.
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:4058
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:4058
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Alan Griffiths (alan-griffiths) wrote : | # |
> > +mgmh::
> > + : depth_buffer_
> > + stencil_
> > + egl_display{
> > + egl_config{
> > + egl_context{
> > + egl_surface{
> > + should_
> > +{
> > +}
> >
> > A long way to write "mgmh::
> default;"?
>
> No, an incomplete move constructor - it doesn't invalidate the moved-from
> object, resulting in the crash.
So why have a move constructor at all?!
A move constructor that promises to behave like a copy constructor is misleading at best.
Alan Griffiths (alan-griffiths) wrote : | # |
> > No, an incomplete move constructor - it doesn't invalidate the moved-from
> > object, resulting in the crash.
>
> So why have a move constructor at all?!
>
> A move constructor that promises to behave like a copy constructor is
> misleading at best.
Ah! I now looked at the final code. That make sense.
Daniel van Vugt (vanvugt) wrote : | # |
Sounds like a sane plan on the surface of it.
I would point out that you've deleted some test cases, but assuming that rotation happens only on construction is an outdated idea. Plus I'm about to change that logic even more soon...
Preview Diff
1 | === modified file 'src/platforms/mesa/server/display_helpers.cpp' |
2 | --- src/platforms/mesa/server/display_helpers.cpp 2017-01-18 02:29:37 +0000 |
3 | +++ src/platforms/mesa/server/display_helpers.cpp 2017-02-28 00:55:32 +0000 |
4 | @@ -321,6 +321,31 @@ |
5 | { |
6 | } |
7 | |
8 | +mgmh::EGLHelper::EGLHelper( |
9 | + GLConfig const& gl_config, |
10 | + GBMHelper const& gbm, |
11 | + gbm_surface* surface, |
12 | + EGLContext shared_context) |
13 | + : EGLHelper(gl_config) |
14 | +{ |
15 | + setup(gbm, surface, shared_context); |
16 | +} |
17 | + |
18 | +mgmh::EGLHelper::EGLHelper(EGLHelper&& from) |
19 | + : depth_buffer_bits{from.depth_buffer_bits}, |
20 | + stencil_buffer_bits{from.stencil_buffer_bits}, |
21 | + egl_display{from.egl_display}, |
22 | + egl_config{from.egl_config}, |
23 | + egl_context{from.egl_context}, |
24 | + egl_surface{from.egl_surface}, |
25 | + should_terminate_egl{from.should_terminate_egl} |
26 | +{ |
27 | + from.should_terminate_egl = false; |
28 | + from.egl_display = EGL_NO_DISPLAY; |
29 | + from.egl_context = EGL_NO_CONTEXT; |
30 | + from.egl_surface = EGL_NO_SURFACE; |
31 | +} |
32 | + |
33 | void mgmh::EGLHelper::setup(GBMHelper const& gbm) |
34 | { |
35 | eglBindAPI(MIR_SERVER_EGL_OPENGL_API); |
36 | |
37 | === modified file 'src/platforms/mesa/server/display_helpers.h' |
38 | --- src/platforms/mesa/server/display_helpers.h 2017-01-18 02:29:37 +0000 |
39 | +++ src/platforms/mesa/server/display_helpers.h 2017-02-28 00:55:32 +0000 |
40 | @@ -102,7 +102,13 @@ |
41 | { |
42 | public: |
43 | EGLHelper(GLConfig const& gl_config); |
44 | + EGLHelper( |
45 | + GLConfig const& gl_config, |
46 | + GBMHelper const& gbm, |
47 | + gbm_surface* surface, |
48 | + EGLContext shared_context); |
49 | ~EGLHelper() noexcept; |
50 | + EGLHelper(EGLHelper&& from); |
51 | |
52 | EGLHelper(const EGLHelper&) = delete; |
53 | EGLHelper& operator=(const EGLHelper&) = delete; |
54 | |
55 | === modified file 'src/platforms/mesa/server/kms/CMakeLists.txt' |
56 | --- src/platforms/mesa/server/kms/CMakeLists.txt 2017-01-18 02:29:37 +0000 |
57 | +++ src/platforms/mesa/server/kms/CMakeLists.txt 2017-02-28 00:55:32 +0000 |
58 | @@ -30,12 +30,16 @@ |
59 | display.cpp |
60 | display_buffer.cpp |
61 | guest_platform.cpp |
62 | + page_flipper.h |
63 | kms_page_flipper.cpp |
64 | linux_virtual_terminal.cpp |
65 | nested_authentication.cpp |
66 | platform.cpp |
67 | + kms_display_configuration.h |
68 | real_kms_display_configuration.cpp |
69 | + kms_output.h |
70 | real_kms_output.cpp |
71 | + kms_output_container.h |
72 | real_kms_output_container.cpp |
73 | ) |
74 | |
75 | |
76 | === modified file 'src/platforms/mesa/server/kms/display.cpp' |
77 | --- src/platforms/mesa/server/kms/display.cpp 2017-02-15 07:38:33 +0000 |
78 | +++ src/platforms/mesa/server/kms/display.cpp 2017-02-28 00:55:32 +0000 |
79 | @@ -414,18 +414,25 @@ |
80 | } |
81 | |
82 | auto surface = gbm->create_scanout_surface(width, height); |
83 | + auto const raw_surface = surface.get(); |
84 | |
85 | std::unique_ptr<DisplayBuffer> db{ |
86 | new DisplayBuffer{bypass_option, |
87 | - drm, |
88 | - gbm, |
89 | listener, |
90 | kms_outputs, |
91 | - std::move(surface), |
92 | + GBMOutputSurface{ |
93 | + drm->fd, |
94 | + std::move(surface), |
95 | + width, height, |
96 | + helpers::EGLHelper{ |
97 | + *gl_config, |
98 | + *gbm, |
99 | + raw_surface, |
100 | + shared_egl.context() |
101 | + } |
102 | + }, |
103 | bounding_rect, |
104 | - orientation, |
105 | - *gl_config, |
106 | - shared_egl.context()}}; |
107 | + orientation}}; |
108 | |
109 | display_buffers_new.push_back(std::move(db)); |
110 | } |
111 | |
112 | === modified file 'src/platforms/mesa/server/kms/display_buffer.cpp' |
113 | --- src/platforms/mesa/server/kms/display_buffer.cpp 2017-02-21 01:04:13 +0000 |
114 | +++ src/platforms/mesa/server/kms/display_buffer.cpp 2017-02-28 00:55:32 +0000 |
115 | @@ -39,13 +39,13 @@ |
116 | namespace mgm = mir::graphics::mesa; |
117 | namespace geom = mir::geometry; |
118 | |
119 | -mgm::GBMFrontBuffer::GBMFrontBuffer() |
120 | +mgm::GBMOutputSurface::FrontBuffer::FrontBuffer() |
121 | : surf{nullptr}, |
122 | bo{nullptr} |
123 | { |
124 | } |
125 | |
126 | -mgm::GBMFrontBuffer::GBMFrontBuffer(gbm_surface* surface) |
127 | +mgm::GBMOutputSurface::FrontBuffer::FrontBuffer(gbm_surface* surface) |
128 | : surf{surface}, |
129 | bo{gbm_surface_lock_front_buffer(surface)} |
130 | { |
131 | @@ -55,7 +55,7 @@ |
132 | } |
133 | } |
134 | |
135 | -mgm::GBMFrontBuffer::~GBMFrontBuffer() |
136 | +mgm::GBMOutputSurface::FrontBuffer::~FrontBuffer() |
137 | { |
138 | if (surf) |
139 | { |
140 | @@ -63,7 +63,7 @@ |
141 | } |
142 | } |
143 | |
144 | -mgm::GBMFrontBuffer::GBMFrontBuffer(GBMFrontBuffer&& from) |
145 | +mgm::GBMOutputSurface::FrontBuffer::FrontBuffer(FrontBuffer&& from) |
146 | : surf{from.surf}, |
147 | bo{from.bo} |
148 | { |
149 | @@ -71,7 +71,7 @@ |
150 | const_cast<gbm_bo*&>(from.bo) = nullptr; |
151 | } |
152 | |
153 | -auto mgm::GBMFrontBuffer::operator=(GBMFrontBuffer&& from) -> GBMFrontBuffer& |
154 | +auto mgm::GBMOutputSurface::FrontBuffer::operator=(FrontBuffer&& from) -> FrontBuffer& |
155 | { |
156 | if (surf) |
157 | { |
158 | @@ -87,57 +87,24 @@ |
159 | return *this; |
160 | } |
161 | |
162 | -auto mgm::GBMFrontBuffer::operator=(std::nullptr_t) -> GBMFrontBuffer& |
163 | +auto mgm::GBMOutputSurface::FrontBuffer::operator=(std::nullptr_t) -> FrontBuffer& |
164 | { |
165 | - return *this = GBMFrontBuffer{}; |
166 | + return *this = FrontBuffer{}; |
167 | } |
168 | |
169 | -mgm::GBMFrontBuffer::operator gbm_bo*() |
170 | +mgm::GBMOutputSurface::FrontBuffer::operator gbm_bo*() |
171 | { |
172 | return bo; |
173 | } |
174 | |
175 | -mgm::GBMFrontBuffer::operator bool() const |
176 | +mgm::GBMOutputSurface::FrontBuffer::operator bool() const |
177 | { |
178 | return (surf != nullptr) && (bo != nullptr); |
179 | } |
180 | |
181 | -class mgm::DRMFB |
182 | -{ |
183 | -public: |
184 | - DRMFB(gbm_bo* bo, uint32_t drm_fb_id) |
185 | - : bo{bo}, drm_fb_id{drm_fb_id} |
186 | - { |
187 | - } |
188 | - |
189 | - ~DRMFB() |
190 | - { |
191 | - if (drm_fb_id) |
192 | - { |
193 | - int drm_fd = gbm_device_get_fd(gbm_bo_get_device(bo)); |
194 | - drmModeRmFB(drm_fd, drm_fb_id); |
195 | - } |
196 | - } |
197 | - |
198 | - uint32_t get_drm_fb_id() const |
199 | - { |
200 | - return drm_fb_id; |
201 | - } |
202 | - |
203 | -private: |
204 | - gbm_bo *bo; |
205 | - uint32_t drm_fb_id; |
206 | -}; |
207 | - |
208 | namespace |
209 | { |
210 | |
211 | -void bo_user_data_destroy(gbm_bo* /*bo*/, void *data) |
212 | -{ |
213 | - auto bufobj = static_cast<mgm::DRMFB*>(data); |
214 | - delete bufobj; |
215 | -} |
216 | - |
217 | void ensure_egl_image_extensions() |
218 | { |
219 | std::string ext_string; |
220 | @@ -153,22 +120,15 @@ |
221 | |
222 | mgm::DisplayBuffer::DisplayBuffer( |
223 | mgm::BypassOption option, |
224 | - std::shared_ptr<helpers::DRMHelper> const& drm, |
225 | - std::shared_ptr<helpers::GBMHelper> const& gbm, |
226 | std::shared_ptr<DisplayReport> const& listener, |
227 | std::vector<std::shared_ptr<KMSOutput>> const& outputs, |
228 | - GBMSurfaceUPtr surface_gbm_param, |
229 | + GBMOutputSurface&& surface_gbm, |
230 | geom::Rectangle const& area, |
231 | - MirOrientation rot, |
232 | - GLConfig const& gl_config, |
233 | - EGLContext shared_context) |
234 | + MirOrientation rot) |
235 | : listener(listener), |
236 | bypass_option(option), |
237 | - drm(drm), |
238 | - gbm(gbm), |
239 | outputs(outputs), |
240 | - egl{gl_config}, |
241 | - surface_gbm{std::move(surface_gbm_param)}, |
242 | + surface{std::move(surface_gbm)}, |
243 | area(area), |
244 | transform{mg::transformation(rot)}, |
245 | needs_set_crtc{false}, |
246 | @@ -187,8 +147,6 @@ |
247 | fb_height = area_height; |
248 | } |
249 | |
250 | - egl.setup(*gbm, surface_gbm.get(), shared_context); |
251 | - |
252 | listener->report_successful_setup_of_native_resources(); |
253 | |
254 | make_current(); |
255 | @@ -199,22 +157,21 @@ |
256 | |
257 | glClear(GL_COLOR_BUFFER_BIT); |
258 | |
259 | - if (!egl.swap_buffers()) |
260 | - fatal_error("Failed to perform initial surface buffer swap"); |
261 | + surface.swap_buffers(); |
262 | |
263 | listener->report_successful_egl_buffer_swap_on_construction(); |
264 | |
265 | - visible_composite_frame = GBMFrontBuffer{surface_gbm.get()}; |
266 | + visible_composite_frame = surface.lock_front(); |
267 | if (!visible_composite_frame) |
268 | fatal_error("Failed to get frontbuffer"); |
269 | |
270 | - set_crtc(get_drm_fb(visible_composite_frame)); |
271 | + set_crtc(*outputs.front()->fb_for(visible_composite_frame, fb_width, fb_height)); |
272 | |
273 | release_current(); |
274 | |
275 | listener->report_successful_drm_mode_set_crtc_on_construction(); |
276 | listener->report_successful_display_construction(); |
277 | - egl.report_egl_configuration( |
278 | + surface.report_egl_configuration( |
279 | [&listener] (EGLDisplay disp, EGLConfig cfg) |
280 | { |
281 | listener->report_egl_configuration(disp, cfg); |
282 | @@ -258,7 +215,7 @@ |
283 | if (native->flags & mir_buffer_flag_can_scanout && |
284 | bypass_buffer->size() == geom::Size{fb_width,fb_height}) |
285 | { |
286 | - if (auto bufobj = get_buffer_object(native->bo)) |
287 | + if (auto bufobj = outputs.front()->fb_for(native->bo, fb_width, fb_height)) |
288 | { |
289 | bypass_buf = bypass_buffer; |
290 | bypass_bufobj = bufobj; |
291 | @@ -281,13 +238,12 @@ |
292 | |
293 | void mgm::DisplayBuffer::swap_buffers() |
294 | { |
295 | - if (!egl.swap_buffers()) |
296 | - fatal_error("Failed to perform buffer swap"); |
297 | + surface.swap_buffers(); |
298 | bypass_buf = nullptr; |
299 | bypass_bufobj = nullptr; |
300 | } |
301 | |
302 | -void mgm::DisplayBuffer::set_crtc(DRMFB const* forced_frame) |
303 | +void mgm::DisplayBuffer::set_crtc(FBHandle const& forced_frame) |
304 | { |
305 | for (auto& output : outputs) |
306 | { |
307 | @@ -298,7 +254,7 @@ |
308 | * sometimes it's really not there). Xorg often reports similar |
309 | * errors, and it's not fatal. |
310 | */ |
311 | - if (!output->set_crtc(forced_frame->get_drm_fb_id())) |
312 | + if (!output->set_crtc(forced_frame)) |
313 | mir::log_error("Failed to set DRM CRTC. " |
314 | "Screen contents may be incomplete. " |
315 | "Try plugging the monitor in again."); |
316 | @@ -315,15 +271,15 @@ |
317 | */ |
318 | wait_for_page_flip(); |
319 | |
320 | - mgm::DRMFB *bufobj; |
321 | + mgm::FBHandle *bufobj; |
322 | if (bypass_buf) |
323 | { |
324 | bufobj = bypass_bufobj; |
325 | } |
326 | else |
327 | { |
328 | - scheduled_composite_frame = GBMFrontBuffer(surface_gbm.get()); |
329 | - bufobj = get_drm_fb(scheduled_composite_frame); |
330 | + scheduled_composite_frame = surface.lock_front(); |
331 | + bufobj = outputs.front()->fb_for(scheduled_composite_frame, fb_width, fb_height); |
332 | if (!bufobj) |
333 | fatal_error("Failed to get front buffer object"); |
334 | } |
335 | @@ -332,7 +288,7 @@ |
336 | * Try to schedule a page flip as first preference to avoid tearing. |
337 | * [will complete in a background thread] |
338 | */ |
339 | - if (!needs_set_crtc && !schedule_page_flip(bufobj)) |
340 | + if (!needs_set_crtc && !schedule_page_flip(*bufobj)) |
341 | needs_set_crtc = true; |
342 | |
343 | /* |
344 | @@ -341,7 +297,7 @@ |
345 | */ |
346 | if (needs_set_crtc) |
347 | { |
348 | - set_crtc(bufobj); |
349 | + set_crtc(*bufobj); |
350 | needs_set_crtc = false; |
351 | } |
352 | |
353 | @@ -406,55 +362,7 @@ |
354 | return recommend_sleep; |
355 | } |
356 | |
357 | -mgm::DRMFB* mgm::DisplayBuffer::get_drm_fb(GBMFrontBuffer& bo) |
358 | -{ |
359 | - return get_buffer_object(bo); |
360 | -} |
361 | - |
362 | -mgm::DRMFB* mgm::DisplayBuffer::get_buffer_object( |
363 | - struct gbm_bo *bo) |
364 | -{ |
365 | - if (!bo) |
366 | - return nullptr; |
367 | - |
368 | - /* |
369 | - * Check if we have already set up this gbm_bo (the gbm implementation is |
370 | - * free to reuse gbm_bos). If so, return the associated DRMFB. |
371 | - */ |
372 | - auto bufobj = static_cast<DRMFB*>(gbm_bo_get_user_data(bo)); |
373 | - if (bufobj) |
374 | - return bufobj; |
375 | - |
376 | - uint32_t fb_id{0}; |
377 | - uint32_t handles[4] = {gbm_bo_get_handle(bo).u32, 0, 0, 0}; |
378 | - uint32_t strides[4] = {gbm_bo_get_stride(bo), 0, 0, 0}; |
379 | - uint32_t offsets[4] = {0, 0, 0, 0}; |
380 | - |
381 | - auto format = gbm_bo_get_format(bo); |
382 | - /* |
383 | - * Mir might use the old GBM_BO_ enum formats, but KMS and the rest of |
384 | - * the world need fourcc formats, so convert... |
385 | - */ |
386 | - if (format == GBM_BO_FORMAT_XRGB8888) |
387 | - format = GBM_FORMAT_XRGB8888; |
388 | - else if (format == GBM_BO_FORMAT_ARGB8888) |
389 | - format = GBM_FORMAT_ARGB8888; |
390 | - |
391 | - /* Create a KMS FB object with the gbm_bo attached to it. */ |
392 | - auto ret = drmModeAddFB2(drm->fd, fb_width, fb_height, format, |
393 | - handles, strides, offsets, &fb_id, 0); |
394 | - if (ret) |
395 | - return nullptr; |
396 | - |
397 | - /* Create a DRMFB and associate it with the gbm_bo */ |
398 | - bufobj = new DRMFB{bo, fb_id}; |
399 | - gbm_bo_set_user_data(bo, bufobj, bo_user_data_destroy); |
400 | - |
401 | - return bufobj; |
402 | -} |
403 | - |
404 | - |
405 | -bool mgm::DisplayBuffer::schedule_page_flip(DRMFB* bufobj) |
406 | +bool mgm::DisplayBuffer::schedule_page_flip(FBHandle const& bufobj) |
407 | { |
408 | /* |
409 | * Schedule the current front buffer object for display. Note that |
410 | @@ -462,7 +370,7 @@ |
411 | */ |
412 | for (auto& output : outputs) |
413 | { |
414 | - if (output->schedule_page_flip(bufobj->get_drm_fb_id())) |
415 | + if (output->schedule_page_flip(bufobj)) |
416 | page_flips_pending = true; |
417 | } |
418 | |
419 | @@ -494,19 +402,17 @@ |
420 | |
421 | void mgm::DisplayBuffer::make_current() |
422 | { |
423 | - if (!egl.make_current()) |
424 | - { |
425 | - fatal_error("Failed to make EGL surface current"); |
426 | - } |
427 | + surface.make_current(); |
428 | } |
429 | |
430 | void mgm::DisplayBuffer::bind() |
431 | { |
432 | + surface.bind(); |
433 | } |
434 | |
435 | void mgm::DisplayBuffer::release_current() |
436 | { |
437 | - egl.release_current(); |
438 | + surface.release_current(); |
439 | } |
440 | |
441 | void mgm::DisplayBuffer::schedule_set_crtc() |
442 | @@ -518,3 +424,62 @@ |
443 | { |
444 | return this; |
445 | } |
446 | + |
447 | +mgm::GBMOutputSurface::GBMOutputSurface( |
448 | + int drm_fd, |
449 | + GBMSurfaceUPtr&& surface, |
450 | + uint32_t width, |
451 | + uint32_t height, |
452 | + helpers::EGLHelper&& egl) |
453 | + : drm_fd{drm_fd}, |
454 | + width{width}, |
455 | + height{height}, |
456 | + egl{std::move(egl)}, |
457 | + surface{std::move(surface)} |
458 | +{ |
459 | +} |
460 | + |
461 | +mgm::GBMOutputSurface::GBMOutputSurface(GBMOutputSurface&& from) |
462 | + : drm_fd{from.drm_fd}, |
463 | + width{from.width}, |
464 | + height{from.height}, |
465 | + egl{std::move(from.egl)}, |
466 | + surface{std::move(from.surface)} |
467 | +{ |
468 | +} |
469 | + |
470 | + |
471 | +void mgm::GBMOutputSurface::make_current() |
472 | +{ |
473 | + if (!egl.make_current()) |
474 | + { |
475 | + fatal_error("Failed to make EGL surface current"); |
476 | + } |
477 | +} |
478 | + |
479 | +void mgm::GBMOutputSurface::release_current() |
480 | +{ |
481 | + egl.release_current(); |
482 | +} |
483 | + |
484 | +void mgm::GBMOutputSurface::swap_buffers() |
485 | +{ |
486 | + if (!egl.swap_buffers()) |
487 | + fatal_error("Failed to perform buffer swap"); |
488 | +} |
489 | + |
490 | +void mgm::GBMOutputSurface::bind() |
491 | +{ |
492 | + |
493 | +} |
494 | + |
495 | +auto mgm::GBMOutputSurface::lock_front() -> FrontBuffer |
496 | +{ |
497 | + return FrontBuffer{surface.get()}; |
498 | +} |
499 | + |
500 | +void mgm::GBMOutputSurface::report_egl_configuration( |
501 | + std::function<void(EGLDisplay, EGLConfig)> const& to) |
502 | +{ |
503 | + egl.report_egl_configuration(to); |
504 | +} |
505 | |
506 | === modified file 'src/platforms/mesa/server/kms/display_buffer.h' |
507 | --- src/platforms/mesa/server/kms/display_buffer.h 2017-02-21 01:04:13 +0000 |
508 | +++ src/platforms/mesa/server/kms/display_buffer.h 2017-02-28 00:55:32 +0000 |
509 | @@ -41,26 +41,55 @@ |
510 | { |
511 | |
512 | class Platform; |
513 | -class DRMFB; |
514 | +class FBHandle; |
515 | class KMSOutput; |
516 | +class NativeBuffer; |
517 | |
518 | -class GBMFrontBuffer |
519 | +class GBMOutputSurface : public renderer::gl::RenderTarget |
520 | { |
521 | public: |
522 | - GBMFrontBuffer(gbm_surface* surface); |
523 | - GBMFrontBuffer(); |
524 | - ~GBMFrontBuffer(); |
525 | - |
526 | - GBMFrontBuffer(GBMFrontBuffer&& from); |
527 | - |
528 | - GBMFrontBuffer& operator=(GBMFrontBuffer&& from); |
529 | - GBMFrontBuffer& operator=(std::nullptr_t); |
530 | - |
531 | - operator gbm_bo*(); |
532 | - operator bool() const; |
533 | + class FrontBuffer |
534 | + { |
535 | + public: |
536 | + FrontBuffer(); |
537 | + ~FrontBuffer(); |
538 | + |
539 | + FrontBuffer(FrontBuffer&& from); |
540 | + |
541 | + FrontBuffer& operator=(FrontBuffer&& from); |
542 | + FrontBuffer& operator=(std::nullptr_t); |
543 | + |
544 | + operator gbm_bo*(); |
545 | + operator bool() const; |
546 | + private: |
547 | + friend class GBMOutputSurface; |
548 | + FrontBuffer(gbm_surface* surface); |
549 | + |
550 | + gbm_surface* const surf; |
551 | + gbm_bo* const bo; |
552 | + }; |
553 | + |
554 | + GBMOutputSurface( |
555 | + int drm_fd, |
556 | + GBMSurfaceUPtr&& surface, |
557 | + uint32_t width, |
558 | + uint32_t height, |
559 | + helpers::EGLHelper&& egl); |
560 | + GBMOutputSurface(GBMOutputSurface&& from); |
561 | + |
562 | + // gl::RenderTarget |
563 | + void make_current() override; |
564 | + void release_current() override; |
565 | + void swap_buffers() override; |
566 | + void bind() override; |
567 | + |
568 | + FrontBuffer lock_front(); |
569 | + void report_egl_configuration(std::function<void(EGLDisplay, EGLConfig)> const& to); |
570 | private: |
571 | - gbm_surface* const surf; |
572 | - gbm_bo* const bo; |
573 | + int const drm_fd; |
574 | + uint32_t width, height; |
575 | + helpers::EGLHelper egl; |
576 | + GBMSurfaceUPtr surface; |
577 | }; |
578 | |
579 | class DisplayBuffer : public graphics::DisplayBuffer, |
580 | @@ -70,15 +99,11 @@ |
581 | { |
582 | public: |
583 | DisplayBuffer(BypassOption bypass_options, |
584 | - std::shared_ptr<helpers::DRMHelper> const& drm, |
585 | - std::shared_ptr<helpers::GBMHelper> const& gbm, |
586 | std::shared_ptr<DisplayReport> const& listener, |
587 | std::vector<std::shared_ptr<KMSOutput>> const& outputs, |
588 | - GBMSurfaceUPtr surface_gbm, |
589 | + GBMOutputSurface&& surface_gbm, |
590 | geometry::Rectangle const& area, |
591 | - MirOrientation rot, |
592 | - GLConfig const& gl_config, |
593 | - EGLContext shared_context); |
594 | + MirOrientation rot); |
595 | ~DisplayBuffer(); |
596 | |
597 | geometry::Rectangle view_area() const override; |
598 | @@ -101,30 +126,24 @@ |
599 | void wait_for_page_flip(); |
600 | |
601 | private: |
602 | - DRMFB* get_drm_fb(GBMFrontBuffer& bo); |
603 | - DRMFB* get_buffer_object(struct gbm_bo *bo); |
604 | - bool schedule_page_flip(DRMFB* bufobj); |
605 | - void set_crtc(DRMFB const*); |
606 | + bool schedule_page_flip(FBHandle const& bufobj); |
607 | + void set_crtc(FBHandle const&); |
608 | |
609 | std::shared_ptr<graphics::Buffer> visible_bypass_frame, scheduled_bypass_frame; |
610 | std::shared_ptr<Buffer> bypass_buf{nullptr}; |
611 | - DRMFB* bypass_bufobj{nullptr}; |
612 | + FBHandle* bypass_bufobj{nullptr}; |
613 | std::shared_ptr<DisplayReport> const listener; |
614 | BypassOption bypass_option; |
615 | - /* DRM helper from mgm::Platform */ |
616 | - std::shared_ptr<helpers::DRMHelper> const drm; |
617 | - std::shared_ptr<helpers::GBMHelper> const gbm; |
618 | + |
619 | std::vector<std::shared_ptr<KMSOutput>> outputs; |
620 | |
621 | /* |
622 | * Destruction order is important here: |
623 | - * - The GBM surface depends on EGL |
624 | * - The GBMFrontBuffers depend on the GBM surface |
625 | */ |
626 | - helpers::EGLHelper egl; |
627 | - GBMSurfaceUPtr surface_gbm; |
628 | - GBMFrontBuffer visible_composite_frame; |
629 | - GBMFrontBuffer scheduled_composite_frame; |
630 | + GBMOutputSurface surface; |
631 | + GBMOutputSurface::FrontBuffer visible_composite_frame; |
632 | + GBMOutputSurface::FrontBuffer scheduled_composite_frame; |
633 | |
634 | geometry::Rectangle area; |
635 | uint32_t fb_width, fb_height; |
636 | |
637 | === modified file 'src/platforms/mesa/server/kms/kms_output.h' |
638 | --- src/platforms/mesa/server/kms/kms_output.h 2017-02-15 07:38:33 +0000 |
639 | +++ src/platforms/mesa/server/kms/kms_output.h 2017-02-28 00:55:32 +0000 |
640 | @@ -35,6 +35,8 @@ |
641 | namespace mesa |
642 | { |
643 | |
644 | +class FBHandle; |
645 | + |
646 | class KMSOutput |
647 | { |
648 | public: |
649 | @@ -52,9 +54,9 @@ |
650 | */ |
651 | virtual int max_refresh_rate() const = 0; |
652 | |
653 | - virtual bool set_crtc(uint32_t fb_id) = 0; |
654 | + virtual bool set_crtc(FBHandle const& fb) = 0; |
655 | virtual void clear_crtc() = 0; |
656 | - virtual bool schedule_page_flip(uint32_t fb_id) = 0; |
657 | + virtual bool schedule_page_flip(FBHandle const& fb) = 0; |
658 | virtual void wait_for_page_flip() = 0; |
659 | |
660 | virtual bool set_cursor(gbm_bo* buffer) = 0; |
661 | @@ -66,6 +68,8 @@ |
662 | virtual void set_gamma(GammaCurves const& gamma) = 0; |
663 | virtual Frame last_frame() const = 0; |
664 | |
665 | + virtual FBHandle* fb_for(gbm_bo* bo, uint32_t width, uint32_t height) const = 0; |
666 | + |
667 | protected: |
668 | KMSOutput() = default; |
669 | KMSOutput(const KMSOutput&) = delete; |
670 | |
671 | === modified file 'src/platforms/mesa/server/kms/real_kms_output.cpp' |
672 | --- src/platforms/mesa/server/kms/real_kms_output.cpp 2017-02-15 07:38:33 +0000 |
673 | +++ src/platforms/mesa/server/kms/real_kms_output.cpp 2017-02-28 00:55:32 +0000 |
674 | @@ -31,6 +31,43 @@ |
675 | namespace mgk = mg::kms; |
676 | namespace geom = mir::geometry; |
677 | |
678 | +class mgm::FBHandle |
679 | +{ |
680 | +public: |
681 | + FBHandle(gbm_bo* bo, uint32_t drm_fb_id) |
682 | + : bo{bo}, drm_fb_id{drm_fb_id} |
683 | + { |
684 | + } |
685 | + |
686 | + ~FBHandle() |
687 | + { |
688 | + if (drm_fb_id) |
689 | + { |
690 | + int drm_fd = gbm_device_get_fd(gbm_bo_get_device(bo)); |
691 | + drmModeRmFB(drm_fd, drm_fb_id); |
692 | + } |
693 | + } |
694 | + |
695 | + uint32_t get_drm_fb_id() const |
696 | + { |
697 | + return drm_fb_id; |
698 | + } |
699 | + |
700 | +private: |
701 | + gbm_bo *bo; |
702 | + uint32_t drm_fb_id; |
703 | +}; |
704 | + |
705 | +namespace |
706 | +{ |
707 | +void bo_user_data_destroy(gbm_bo* /*bo*/, void *data) |
708 | +{ |
709 | + auto bufobj = static_cast<mgm::FBHandle*>(data); |
710 | + delete bufobj; |
711 | +} |
712 | + |
713 | +} |
714 | + |
715 | mgm::RealKMSOutput::RealKMSOutput(int drm_fd, uint32_t connector_id, |
716 | std::shared_ptr<PageFlipper> const& page_flipper) |
717 | : drm_fd{drm_fd}, connector_id{connector_id}, page_flipper{page_flipper}, |
718 | @@ -108,7 +145,7 @@ |
719 | mode_index = kms_mode_index; |
720 | } |
721 | |
722 | -bool mgm::RealKMSOutput::set_crtc(uint32_t fb_id) |
723 | +bool mgm::RealKMSOutput::set_crtc(FBHandle const& fb) |
724 | { |
725 | if (!ensure_crtc()) |
726 | { |
727 | @@ -118,7 +155,7 @@ |
728 | } |
729 | |
730 | auto ret = drmModeSetCrtc(drm_fd, current_crtc->crtc_id, |
731 | - fb_id, fb_offset.dx.as_int(), fb_offset.dy.as_int(), |
732 | + fb.get_drm_fb_id(), fb_offset.dx.as_int(), fb_offset.dy.as_int(), |
733 | &connector->connector_id, 1, |
734 | &connector->modes[mode_index]); |
735 | if (ret) |
736 | @@ -159,7 +196,7 @@ |
737 | current_crtc = nullptr; |
738 | } |
739 | |
740 | -bool mgm::RealKMSOutput::schedule_page_flip(uint32_t fb_id) |
741 | +bool mgm::RealKMSOutput::schedule_page_flip(FBHandle const& fb) |
742 | { |
743 | std::unique_lock<std::mutex> lg(power_mutex); |
744 | if (power_mode != mir_power_mode_on) |
745 | @@ -170,7 +207,7 @@ |
746 | mgk::connector_name(connector).c_str()); |
747 | return false; |
748 | } |
749 | - return page_flipper->schedule_flip(current_crtc->crtc_id, fb_id, connector_id); |
750 | + return page_flipper->schedule_flip(current_crtc->crtc_id, fb.get_drm_fb_id(), connector_id); |
751 | } |
752 | |
753 | void mgm::RealKMSOutput::wait_for_page_flip() |
754 | @@ -319,3 +356,44 @@ |
755 | |
756 | // TODO: return bool in future? Then do what with it? |
757 | } |
758 | + |
759 | +mgm::FBHandle* mgm::RealKMSOutput::fb_for(gbm_bo* bo, uint32_t width, uint32_t height) const |
760 | +{ |
761 | + if (!bo) |
762 | + return nullptr; |
763 | + |
764 | + /* |
765 | + * Check if we have already set up this gbm_bo (the gbm implementation is |
766 | + * free to reuse gbm_bos). If so, return the associated FBHandle. |
767 | + */ |
768 | + auto bufobj = static_cast<FBHandle*>(gbm_bo_get_user_data(bo)); |
769 | + if (bufobj) |
770 | + return bufobj; |
771 | + |
772 | + uint32_t fb_id{0}; |
773 | + uint32_t handles[4] = {gbm_bo_get_handle(bo).u32, 0, 0, 0}; |
774 | + uint32_t strides[4] = {gbm_bo_get_stride(bo), 0, 0, 0}; |
775 | + uint32_t offsets[4] = {0, 0, 0, 0}; |
776 | + |
777 | + auto format = gbm_bo_get_format(bo); |
778 | + /* |
779 | + * Mir might use the old GBM_BO_ enum formats, but KMS and the rest of |
780 | + * the world need fourcc formats, so convert... |
781 | + */ |
782 | + if (format == GBM_BO_FORMAT_XRGB8888) |
783 | + format = GBM_FORMAT_XRGB8888; |
784 | + else if (format == GBM_BO_FORMAT_ARGB8888) |
785 | + format = GBM_FORMAT_ARGB8888; |
786 | + |
787 | + /* Create a KMS FB object with the gbm_bo attached to it. */ |
788 | + auto ret = drmModeAddFB2(drm_fd, width, height, format, |
789 | + handles, strides, offsets, &fb_id, 0); |
790 | + if (ret) |
791 | + return nullptr; |
792 | + |
793 | + /* Create a FBHandle and associate it with the gbm_bo */ |
794 | + bufobj = new FBHandle{bo, fb_id}; |
795 | + gbm_bo_set_user_data(bo, bufobj, bo_user_data_destroy); |
796 | + |
797 | + return bufobj; |
798 | +} |
799 | |
800 | === modified file 'src/platforms/mesa/server/kms/real_kms_output.h' |
801 | --- src/platforms/mesa/server/kms/real_kms_output.h 2017-02-15 07:38:33 +0000 |
802 | +++ src/platforms/mesa/server/kms/real_kms_output.h 2017-02-28 00:55:32 +0000 |
803 | @@ -47,9 +47,9 @@ |
804 | geometry::Size size() const override; |
805 | int max_refresh_rate() const override; |
806 | |
807 | - bool set_crtc(uint32_t fb_id) override; |
808 | + bool set_crtc(FBHandle const& fb) override; |
809 | void clear_crtc() override; |
810 | - bool schedule_page_flip(uint32_t fb_id) override; |
811 | + bool schedule_page_flip(FBHandle const& fb) override; |
812 | void wait_for_page_flip() override; |
813 | |
814 | bool set_cursor(gbm_bo* buffer) override; |
815 | @@ -62,6 +62,8 @@ |
816 | |
817 | Frame last_frame() const override; |
818 | |
819 | + FBHandle* fb_for(gbm_bo* bo, uint32_t width, uint32_t height) const override; |
820 | + |
821 | private: |
822 | bool ensure_crtc(); |
823 | void restore_saved_crtc(); |
824 | |
825 | === modified file 'tests/unit-tests/platforms/mesa/kms/mock_kms_output.h' |
826 | --- tests/unit-tests/platforms/mesa/kms/mock_kms_output.h 2017-02-15 07:38:33 +0000 |
827 | +++ tests/unit-tests/platforms/mesa/kms/mock_kms_output.h 2017-02-28 00:55:32 +0000 |
828 | @@ -24,6 +24,15 @@ |
829 | |
830 | namespace mir |
831 | { |
832 | + |
833 | +namespace graphics |
834 | +{ |
835 | +namespace mesa |
836 | +{ |
837 | +class DRMFB; |
838 | +} |
839 | +} |
840 | + |
841 | namespace test |
842 | { |
843 | |
844 | @@ -34,9 +43,19 @@ |
845 | MOCK_CONST_METHOD0(size, geometry::Size()); |
846 | MOCK_CONST_METHOD0(max_refresh_rate, int()); |
847 | |
848 | - MOCK_METHOD1(set_crtc, bool(uint32_t)); |
849 | + bool set_crtc(graphics::mesa::FBHandle const& fb) override |
850 | + { |
851 | + return set_crtc_thunk(&fb); |
852 | + } |
853 | + |
854 | + MOCK_METHOD1(set_crtc_thunk, bool(graphics::mesa::FBHandle const*)); |
855 | MOCK_METHOD0(clear_crtc, void()); |
856 | - MOCK_METHOD1(schedule_page_flip, bool(uint32_t)); |
857 | + |
858 | + bool schedule_page_flip(graphics::mesa::FBHandle const& fb) override |
859 | + { |
860 | + return schedule_page_flip_thunk(&fb); |
861 | + } |
862 | + MOCK_METHOD1(schedule_page_flip_thunk, bool(graphics::mesa::FBHandle const*)); |
863 | MOCK_METHOD0(wait_for_page_flip, void()); |
864 | |
865 | MOCK_CONST_METHOD0(last_frame, graphics::Frame()); |
866 | @@ -48,6 +67,8 @@ |
867 | |
868 | MOCK_METHOD1(set_power_mode, void(MirPowerMode)); |
869 | MOCK_METHOD1(set_gamma, void(mir::graphics::GammaCurves const&)); |
870 | + |
871 | + MOCK_CONST_METHOD3(fb_for, graphics::mesa::FBHandle*(gbm_bo*, uint32_t, uint32_t)); |
872 | }; |
873 | |
874 | } // namespace test |
875 | |
876 | === modified file 'tests/unit-tests/platforms/mesa/kms/test_display_buffer.cpp' |
877 | --- tests/unit-tests/platforms/mesa/kms/test_display_buffer.cpp 2017-01-27 08:13:36 +0000 |
878 | +++ tests/unit-tests/platforms/mesa/kms/test_display_buffer.cpp 2017-02-28 00:55:32 +0000 |
879 | @@ -85,12 +85,14 @@ |
880 | fake_devices.add_standard_device("standard-drm-devices"); |
881 | |
882 | mock_kms_output = std::make_shared<NiceMock<MockKMSOutput>>(); |
883 | - ON_CALL(*mock_kms_output, set_crtc(_)) |
884 | + ON_CALL(*mock_kms_output, set_crtc_thunk(_)) |
885 | .WillByDefault(Return(true)); |
886 | - ON_CALL(*mock_kms_output, schedule_page_flip(_)) |
887 | + ON_CALL(*mock_kms_output, schedule_page_flip_thunk(_)) |
888 | .WillByDefault(Return(true)); |
889 | ON_CALL(*mock_kms_output, max_refresh_rate()) |
890 | .WillByDefault(Return(mock_refresh_rate)); |
891 | + ON_CALL(*mock_kms_output, fb_for(_,_,_)) |
892 | + .WillByDefault(Return(reinterpret_cast<FBHandle*>(0x12ad))); |
893 | |
894 | ON_CALL(*mock_bypassable_buffer, size()) |
895 | .WillByDefault(Return(display_area.size)); |
896 | @@ -108,6 +110,18 @@ |
897 | } |
898 | |
899 | protected: |
900 | + GBMOutputSurface make_output_surface() |
901 | + { |
902 | + helpers::EGLHelper egl{gl_config}; |
903 | + return GBMOutputSurface{ |
904 | + drm->fd, |
905 | + GBMSurfaceUPtr{nullptr}, |
906 | + static_cast<uint32_t>(width), |
907 | + static_cast<uint32_t>(height), |
908 | + std::move(egl) |
909 | + }; |
910 | + } |
911 | + |
912 | int const width{56}; |
913 | int const height{78}; |
914 | mir::geometry::Rectangle const display_area{{12,34}, {width,height}}; |
915 | @@ -135,15 +149,11 @@ |
916 | { |
917 | graphics::mesa::DisplayBuffer db( |
918 | graphics::mesa::BypassOption::allowed, |
919 | - drm, |
920 | - gbm, |
921 | null_display_report(), |
922 | - {}, |
923 | - nullptr, |
924 | + {mock_kms_output}, |
925 | + make_output_surface(), |
926 | display_area, |
927 | - mir_orientation_normal, |
928 | - gl_config, |
929 | - mock_egl.fake_egl_context); |
930 | + mir_orientation_normal); |
931 | |
932 | EXPECT_EQ(display_area, db.view_area()); |
933 | } |
934 | @@ -152,15 +162,11 @@ |
935 | { |
936 | graphics::mesa::DisplayBuffer db( |
937 | graphics::mesa::BypassOption::allowed, |
938 | - drm, |
939 | - gbm, |
940 | null_display_report(), |
941 | {mock_kms_output}, |
942 | - nullptr, |
943 | + make_output_surface(), |
944 | display_area, |
945 | - mir_orientation_normal, |
946 | - gl_config, |
947 | - mock_egl.fake_egl_context); |
948 | + mir_orientation_normal); |
949 | |
950 | auto original_count = mock_bypassable_buffer.use_count(); |
951 | |
952 | @@ -180,15 +186,11 @@ |
953 | { |
954 | graphics::mesa::DisplayBuffer db( |
955 | graphics::mesa::BypassOption::allowed, |
956 | - drm, |
957 | - gbm, |
958 | null_display_report(), |
959 | {mock_kms_output}, |
960 | - nullptr, |
961 | + make_output_surface(), |
962 | display_area, |
963 | - mir_orientation_normal, |
964 | - gl_config, |
965 | - mock_egl.fake_egl_context); |
966 | + mir_orientation_normal); |
967 | |
968 | for (int frame = 0; frame < 5; ++frame) |
969 | { |
970 | @@ -210,15 +212,11 @@ |
971 | |
972 | graphics::mesa::DisplayBuffer db( |
973 | graphics::mesa::BypassOption::allowed, |
974 | - drm, |
975 | - gbm, |
976 | null_display_report(), |
977 | {mock_kms_output}, |
978 | - nullptr, |
979 | + make_output_surface(), |
980 | display_area, |
981 | - mir_orientation_normal, |
982 | - gl_config, |
983 | - mock_egl.fake_egl_context); |
984 | + mir_orientation_normal); |
985 | |
986 | for (int frame = 0; frame < 5; ++frame) |
987 | { |
988 | @@ -234,15 +232,11 @@ |
989 | { |
990 | graphics::mesa::DisplayBuffer db( |
991 | graphics::mesa::BypassOption::allowed, |
992 | - drm, |
993 | - gbm, |
994 | null_display_report(), |
995 | {mock_kms_output}, |
996 | - nullptr, |
997 | + make_output_surface(), |
998 | display_area, |
999 | - mir_orientation_normal, |
1000 | - gl_config, |
1001 | - mock_egl.fake_egl_context); |
1002 | + mir_orientation_normal); |
1003 | |
1004 | auto original_count = mock_bypassable_buffer.use_count(); |
1005 | |
1006 | @@ -259,37 +253,29 @@ |
1007 | { |
1008 | graphics::mesa::DisplayBuffer db( |
1009 | graphics::mesa::BypassOption::allowed, |
1010 | - drm, |
1011 | - gbm, |
1012 | null_display_report(), |
1013 | {mock_kms_output}, |
1014 | - nullptr, |
1015 | + make_output_surface(), |
1016 | display_area, |
1017 | - mir_orientation_normal, |
1018 | - gl_config, |
1019 | - mock_egl.fake_egl_context); |
1020 | + mir_orientation_normal); |
1021 | |
1022 | EXPECT_TRUE(db.overlay(bypassable_list)); |
1023 | } |
1024 | |
1025 | TEST_F(MesaDisplayBufferTest, failed_bypass_falls_back_gracefully) |
1026 | { // Regression test for LP: #1398296 |
1027 | - EXPECT_CALL(mock_drm, drmModeAddFB2(_, _, _, _, _, _, _, _, _)) |
1028 | - .WillOnce(Return(0)) // During the DisplayBuffer constructor |
1029 | - .WillOnce(Return(-22)) // Fail first bypass attempt |
1030 | - .WillOnce(Return(0)); // Succeed second bypass attempt |
1031 | + EXPECT_CALL(*mock_kms_output, fb_for(_,_,_)) |
1032 | + .WillOnce(Return(reinterpret_cast<FBHandle*>(0xaabb))) // During the DisplayBuffer constructor |
1033 | + .WillOnce(Return(nullptr)) // Fail first bypass attempt |
1034 | + .WillOnce(Return(reinterpret_cast<FBHandle*>(0xbbcc))); // Succeed second bypass attempt |
1035 | |
1036 | graphics::mesa::DisplayBuffer db( |
1037 | graphics::mesa::BypassOption::allowed, |
1038 | - drm, |
1039 | - gbm, |
1040 | null_display_report(), |
1041 | {mock_kms_output}, |
1042 | - nullptr, |
1043 | + make_output_surface(), |
1044 | display_area, |
1045 | - mir_orientation_normal, |
1046 | - gl_config, |
1047 | - mock_egl.fake_egl_context); |
1048 | + mir_orientation_normal); |
1049 | |
1050 | EXPECT_FALSE(db.overlay(bypassable_list)); |
1051 | // And then we recover. DRM finds enough resources to AddFB ... |
1052 | @@ -310,15 +296,11 @@ |
1053 | |
1054 | graphics::mesa::DisplayBuffer db( |
1055 | graphics::mesa::BypassOption::allowed, |
1056 | - drm, |
1057 | - gbm, |
1058 | null_display_report(), |
1059 | {mock_kms_output}, |
1060 | - nullptr, |
1061 | + make_output_surface(), |
1062 | display_area, |
1063 | - mir_orientation_normal, |
1064 | - gl_config, |
1065 | - mock_egl.fake_egl_context); |
1066 | + mir_orientation_normal); |
1067 | |
1068 | EXPECT_FALSE(db.overlay(list)); |
1069 | } |
1070 | @@ -327,15 +309,11 @@ |
1071 | { |
1072 | graphics::mesa::DisplayBuffer db( |
1073 | graphics::mesa::BypassOption::allowed, |
1074 | - drm, |
1075 | - gbm, |
1076 | null_display_report(), |
1077 | - {}, |
1078 | - nullptr, |
1079 | + {mock_kms_output}, |
1080 | + make_output_surface(), |
1081 | display_area, |
1082 | - mir_orientation_right, |
1083 | - gl_config, |
1084 | - mock_egl.fake_egl_context); |
1085 | + mir_orientation_right); |
1086 | |
1087 | EXPECT_FALSE(db.overlay(bypassable_list)); |
1088 | } |
1089 | @@ -349,15 +327,11 @@ |
1090 | |
1091 | graphics::mesa::DisplayBuffer db( |
1092 | graphics::mesa::BypassOption::allowed, |
1093 | - drm, |
1094 | - gbm, |
1095 | null_display_report(), |
1096 | - {}, |
1097 | - nullptr, |
1098 | + {mock_kms_output}, |
1099 | + make_output_surface(), |
1100 | display_area, |
1101 | - mir_orientation_normal, |
1102 | - gl_config, |
1103 | - mock_egl.fake_egl_context); |
1104 | + mir_orientation_normal); |
1105 | |
1106 | EXPECT_FALSE(db.overlay(list)); |
1107 | } |
1108 | @@ -371,15 +345,11 @@ |
1109 | |
1110 | graphics::mesa::DisplayBuffer db( |
1111 | graphics::mesa::BypassOption::allowed, |
1112 | - drm, |
1113 | - gbm, |
1114 | null_display_report(), |
1115 | - {}, |
1116 | - nullptr, |
1117 | + {mock_kms_output}, |
1118 | + make_output_surface(), |
1119 | display_area, |
1120 | - mir_orientation_normal, |
1121 | - gl_config, |
1122 | - mock_egl.fake_egl_context); |
1123 | + mir_orientation_normal); |
1124 | |
1125 | // If you find yourself using gbm_ functions on a Shm buffer then you're |
1126 | // asking for a crash (LP: #1493721) ... |
1127 | @@ -394,119 +364,31 @@ |
1128 | |
1129 | graphics::mesa::DisplayBuffer db( |
1130 | graphics::mesa::BypassOption::allowed, |
1131 | - drm, |
1132 | - gbm, |
1133 | null_display_report(), |
1134 | - {}, |
1135 | - nullptr, |
1136 | + {mock_kms_output}, |
1137 | + make_output_surface(), |
1138 | display_area, |
1139 | - mir_orientation_left, |
1140 | - gl_config, |
1141 | - mock_egl.fake_egl_context); |
1142 | + mir_orientation_left); |
1143 | |
1144 | EXPECT_EQ(rotate_left, db.transformation()); |
1145 | } |
1146 | |
1147 | -TEST_F(MesaDisplayBufferTest, normal_rotation_constructs_normal_fb) |
1148 | -{ |
1149 | - EXPECT_CALL(mock_gbm, gbm_bo_get_user_data(_)) |
1150 | - .WillOnce(Return((void*)0)); |
1151 | - EXPECT_CALL(mock_drm, drmModeAddFB2(_, width, height, _, _, _, _, _, _)) |
1152 | - .Times(1); |
1153 | - |
1154 | - graphics::mesa::DisplayBuffer db( |
1155 | - graphics::mesa::BypassOption::allowed, |
1156 | - drm, |
1157 | - gbm, |
1158 | - null_display_report(), |
1159 | - {}, |
1160 | - nullptr, |
1161 | - display_area, |
1162 | - mir_orientation_normal, |
1163 | - gl_config, |
1164 | - mock_egl.fake_egl_context); |
1165 | -} |
1166 | - |
1167 | -TEST_F(MesaDisplayBufferTest, left_rotation_constructs_transposed_fb) |
1168 | -{ |
1169 | - EXPECT_CALL(mock_gbm, gbm_bo_get_user_data(_)) |
1170 | - .WillOnce(Return((void*)0)); |
1171 | - EXPECT_CALL(mock_drm, drmModeAddFB2(_, height, width, _, _, _, _, _, _)) |
1172 | - .Times(1); |
1173 | - |
1174 | - graphics::mesa::DisplayBuffer db( |
1175 | - graphics::mesa::BypassOption::allowed, |
1176 | - drm, |
1177 | - gbm, |
1178 | - null_display_report(), |
1179 | - {}, |
1180 | - nullptr, |
1181 | - display_area, |
1182 | - mir_orientation_left, |
1183 | - gl_config, |
1184 | - mock_egl.fake_egl_context); |
1185 | -} |
1186 | - |
1187 | -TEST_F(MesaDisplayBufferTest, inverted_rotation_constructs_normal_fb) |
1188 | -{ |
1189 | - EXPECT_CALL(mock_gbm, gbm_bo_get_user_data(_)) |
1190 | - .WillOnce(Return((void*)0)); |
1191 | - EXPECT_CALL(mock_drm, drmModeAddFB2(_, width, height, _, _, _, _, _, _)) |
1192 | - .Times(1); |
1193 | - |
1194 | - graphics::mesa::DisplayBuffer db( |
1195 | - graphics::mesa::BypassOption::allowed, |
1196 | - drm, |
1197 | - gbm, |
1198 | - null_display_report(), |
1199 | - {}, |
1200 | - nullptr, |
1201 | - display_area, |
1202 | - mir_orientation_inverted, |
1203 | - gl_config, |
1204 | - mock_egl.fake_egl_context); |
1205 | -} |
1206 | - |
1207 | -TEST_F(MesaDisplayBufferTest, right_rotation_constructs_transposed_fb) |
1208 | -{ |
1209 | - EXPECT_CALL(mock_gbm, gbm_bo_get_user_data(_)) |
1210 | - .WillOnce(Return((void*)0)); |
1211 | - EXPECT_CALL(mock_drm, drmModeAddFB2(_, height, width, _, _, _, _, _, _)) |
1212 | - .Times(1); |
1213 | - |
1214 | - graphics::mesa::DisplayBuffer db( |
1215 | - graphics::mesa::BypassOption::allowed, |
1216 | - drm, |
1217 | - gbm, |
1218 | - null_display_report(), |
1219 | - {}, |
1220 | - nullptr, |
1221 | - display_area, |
1222 | - mir_orientation_right, |
1223 | - gl_config, |
1224 | - mock_egl.fake_egl_context); |
1225 | -} |
1226 | - |
1227 | TEST_F(MesaDisplayBufferTest, clone_mode_first_flip_flips_but_no_wait) |
1228 | { |
1229 | // Ensure clone mode can do multiple page flips in parallel without |
1230 | // blocking on either (at least till the second post) |
1231 | - EXPECT_CALL(*mock_kms_output, schedule_page_flip(_)) |
1232 | + EXPECT_CALL(*mock_kms_output, schedule_page_flip_thunk(_)) |
1233 | .Times(2); |
1234 | EXPECT_CALL(*mock_kms_output, wait_for_page_flip()) |
1235 | .Times(0); |
1236 | |
1237 | graphics::mesa::DisplayBuffer db( |
1238 | graphics::mesa::BypassOption::allowed, |
1239 | - drm, |
1240 | - gbm, |
1241 | null_display_report(), |
1242 | {mock_kms_output, mock_kms_output}, |
1243 | - nullptr, |
1244 | + make_output_surface(), |
1245 | display_area, |
1246 | - mir_orientation_normal, |
1247 | - gl_config, |
1248 | - mock_egl.fake_egl_context); |
1249 | + mir_orientation_normal); |
1250 | |
1251 | db.swap_buffers(); |
1252 | db.post(); |
1253 | @@ -514,22 +396,18 @@ |
1254 | |
1255 | TEST_F(MesaDisplayBufferTest, single_mode_first_post_flips_with_wait) |
1256 | { |
1257 | - EXPECT_CALL(*mock_kms_output, schedule_page_flip(_)) |
1258 | + EXPECT_CALL(*mock_kms_output, schedule_page_flip_thunk(_)) |
1259 | .Times(1); |
1260 | EXPECT_CALL(*mock_kms_output, wait_for_page_flip()) |
1261 | .Times(1); |
1262 | |
1263 | graphics::mesa::DisplayBuffer db( |
1264 | graphics::mesa::BypassOption::allowed, |
1265 | - drm, |
1266 | - gbm, |
1267 | null_display_report(), |
1268 | {mock_kms_output}, |
1269 | - nullptr, |
1270 | + make_output_surface(), |
1271 | display_area, |
1272 | - mir_orientation_normal, |
1273 | - gl_config, |
1274 | - mock_egl.fake_egl_context); |
1275 | + mir_orientation_normal); |
1276 | |
1277 | db.swap_buffers(); |
1278 | db.post(); |
1279 | @@ -541,26 +419,22 @@ |
1280 | |
1281 | EXPECT_CALL(*mock_kms_output, wait_for_page_flip()) |
1282 | .Times(0); |
1283 | - EXPECT_CALL(*mock_kms_output, schedule_page_flip(_)) |
1284 | + EXPECT_CALL(*mock_kms_output, schedule_page_flip_thunk(_)) |
1285 | .Times(2); |
1286 | EXPECT_CALL(*mock_kms_output, wait_for_page_flip()) |
1287 | .Times(2); |
1288 | - EXPECT_CALL(*mock_kms_output, schedule_page_flip(_)) |
1289 | + EXPECT_CALL(*mock_kms_output, schedule_page_flip_thunk(_)) |
1290 | .Times(2); |
1291 | EXPECT_CALL(*mock_kms_output, wait_for_page_flip()) |
1292 | .Times(0); |
1293 | |
1294 | graphics::mesa::DisplayBuffer db( |
1295 | graphics::mesa::BypassOption::allowed, |
1296 | - drm, |
1297 | - gbm, |
1298 | null_display_report(), |
1299 | {mock_kms_output, mock_kms_output}, |
1300 | - nullptr, |
1301 | + make_output_surface(), |
1302 | display_area, |
1303 | - mir_orientation_normal, |
1304 | - gl_config, |
1305 | - mock_egl.fake_egl_context); |
1306 | + mir_orientation_normal); |
1307 | |
1308 | db.swap_buffers(); |
1309 | db.post(); |
1310 | @@ -578,15 +452,11 @@ |
1311 | |
1312 | graphics::mesa::DisplayBuffer db( |
1313 | graphics::mesa::BypassOption::allowed, |
1314 | - drm, |
1315 | - gbm, |
1316 | null_display_report(), |
1317 | {mock_kms_output}, |
1318 | - nullptr, |
1319 | + make_output_surface(), |
1320 | display_area, |
1321 | - mir_orientation_normal, |
1322 | - gl_config, |
1323 | - mock_egl.fake_egl_context); |
1324 | + mir_orientation_normal); |
1325 | |
1326 | EXPECT_FALSE(db.overlay(list)); |
1327 | } |
1328 | @@ -607,15 +477,11 @@ |
1329 | |
1330 | graphics::mesa::DisplayBuffer db( |
1331 | graphics::mesa::BypassOption::allowed, |
1332 | - drm, |
1333 | - gbm, |
1334 | null_display_report(), |
1335 | {mock_kms_output}, |
1336 | - nullptr, |
1337 | + make_output_surface(), |
1338 | display_area, |
1339 | - mir_orientation_normal, |
1340 | - gl_config, |
1341 | - mock_egl.fake_egl_context); |
1342 | + mir_orientation_normal); |
1343 | |
1344 | EXPECT_FALSE(db.overlay(list)); |
1345 | } |
1346 | |
1347 | === modified file 'tests/unit-tests/platforms/mesa/kms/test_real_kms_output.cpp' |
1348 | --- tests/unit-tests/platforms/mesa/kms/test_real_kms_output.cpp 2017-01-18 02:29:37 +0000 |
1349 | +++ tests/unit-tests/platforms/mesa/kms/test_real_kms_output.cpp 2017-02-28 00:55:32 +0000 |
1350 | @@ -66,6 +66,9 @@ |
1351 | { |
1352 | ON_CALL(mock_page_flipper, wait_for_flip(_)) |
1353 | .WillByDefault(Return(mg::Frame{})); |
1354 | + |
1355 | + ON_CALL(mock_gbm, gbm_bo_get_handle(_)) |
1356 | + .WillByDefault(Return(gbm_bo_handle{0})); |
1357 | } |
1358 | |
1359 | void setup_outputs_connected_crtc() |
1360 | @@ -106,12 +109,22 @@ |
1361 | resources.prepare(); |
1362 | } |
1363 | |
1364 | + void append_fb_id(uint32_t fb_id) |
1365 | + { |
1366 | + EXPECT_CALL(mock_drm, drmModeAddFB2(_,_,_,_,_,_,_,_,_)) |
1367 | + .WillOnce( |
1368 | + DoAll( |
1369 | + SetArgPointee<7>(fb_id), |
1370 | + Return(0))); |
1371 | + } |
1372 | + |
1373 | testing::NiceMock<mtd::MockDRM> mock_drm; |
1374 | testing::NiceMock<mtd::MockGBM> mock_gbm; |
1375 | MockPageFlipper mock_page_flipper; |
1376 | NullPageFlipper null_page_flipper; |
1377 | |
1378 | std::vector<drmModeModeInfo> modes_empty; |
1379 | + gbm_bo* const fake_bo{reinterpret_cast<gbm_bo*>(0x123ba)}; |
1380 | uint32_t const invalid_id; |
1381 | std::vector<uint32_t> const crtc_ids; |
1382 | std::vector<uint32_t> const encoder_ids; |
1383 | @@ -139,10 +152,11 @@ |
1384 | { |
1385 | using namespace testing; |
1386 | |
1387 | - uint32_t const fb_id{67}; |
1388 | - |
1389 | setup_outputs_connected_crtc(); |
1390 | |
1391 | + uint32_t const fb_id{42}; |
1392 | + append_fb_id(fb_id); |
1393 | + |
1394 | { |
1395 | InSequence s; |
1396 | |
1397 | @@ -166,8 +180,10 @@ |
1398 | mgm::RealKMSOutput output{mock_drm.fake_drm.fd(), connector_ids[0], |
1399 | mt::fake_shared(mock_page_flipper)}; |
1400 | |
1401 | - EXPECT_TRUE(output.set_crtc(fb_id)); |
1402 | - EXPECT_TRUE(output.schedule_page_flip(fb_id)); |
1403 | + auto fb = output.fb_for(fake_bo, 1920, 1024); |
1404 | + |
1405 | + EXPECT_TRUE(output.set_crtc(*fb)); |
1406 | + EXPECT_TRUE(output.schedule_page_flip(*fb)); |
1407 | output.wait_for_page_flip(); |
1408 | } |
1409 | |
1410 | @@ -199,11 +215,15 @@ |
1411 | .Times(1); |
1412 | } |
1413 | |
1414 | + append_fb_id(fb_id); |
1415 | + |
1416 | mgm::RealKMSOutput output{mock_drm.fake_drm.fd(), connector_ids[0], |
1417 | mt::fake_shared(mock_page_flipper)}; |
1418 | |
1419 | - EXPECT_TRUE(output.set_crtc(fb_id)); |
1420 | - EXPECT_TRUE(output.schedule_page_flip(fb_id)); |
1421 | + auto fb = output.fb_for(fake_bo, 1920, 756); |
1422 | + |
1423 | + EXPECT_TRUE(output.set_crtc(*fb)); |
1424 | + EXPECT_TRUE(output.schedule_page_flip(*fb)); |
1425 | output.wait_for_page_flip(); |
1426 | } |
1427 | |
1428 | @@ -219,7 +239,7 @@ |
1429 | { |
1430 | InSequence s; |
1431 | |
1432 | - EXPECT_CALL(mock_drm, drmModeSetCrtc(_, crtc_ids[0], fb_id, _, _, _, _, _)) |
1433 | + EXPECT_CALL(mock_drm, drmModeSetCrtc(_, crtc_ids[0], _, _, _, _, _, _)) |
1434 | .Times(1) |
1435 | .WillOnce(Return(1)); |
1436 | |
1437 | @@ -232,13 +252,18 @@ |
1438 | EXPECT_CALL(mock_drm, drmModeSetCrtc(_, _, _, _, _, _, _, _)) |
1439 | .Times(0); |
1440 | } |
1441 | - |
1442 | - mgm::RealKMSOutput output{mock_drm.fake_drm.fd(), connector_ids[0], |
1443 | - mt::fake_shared(mock_page_flipper)}; |
1444 | - |
1445 | - EXPECT_FALSE(output.set_crtc(fb_id)); |
1446 | + append_fb_id(fb_id); |
1447 | + |
1448 | + mgm::RealKMSOutput output{ |
1449 | + mock_drm.fake_drm.fd(), |
1450 | + connector_ids[0], |
1451 | + mt::fake_shared(mock_page_flipper)}; |
1452 | + |
1453 | + auto fb = output.fb_for(fake_bo, 1280, 1024); |
1454 | + |
1455 | + EXPECT_FALSE(output.set_crtc(*fb)); |
1456 | EXPECT_NO_THROW({ |
1457 | - EXPECT_FALSE(output.schedule_page_flip(fb_id)); |
1458 | + EXPECT_FALSE(output.schedule_page_flip(*fb)); |
1459 | }); |
1460 | EXPECT_THROW({ // schedule failed. It's programmer error if you then wait. |
1461 | output.wait_for_page_flip(); |
1462 | @@ -299,7 +324,9 @@ |
1463 | mgm::RealKMSOutput output{mock_drm.fake_drm.fd(), connector_ids[0], |
1464 | mt::fake_shared(mock_page_flipper)}; |
1465 | |
1466 | - EXPECT_TRUE(output.set_crtc(987)); |
1467 | + auto fb = output.fb_for(fake_bo, 1292, 222); |
1468 | + |
1469 | + EXPECT_TRUE(output.set_crtc(*fb)); |
1470 | EXPECT_NO_THROW({ |
1471 | output.move_cursor({123, 456}); |
1472 | }); |
1473 | @@ -323,7 +350,9 @@ |
1474 | mgm::RealKMSOutput output{mock_drm.fake_drm.fd(), connector_ids[0], |
1475 | mt::fake_shared(mock_page_flipper)}; |
1476 | |
1477 | - EXPECT_TRUE(output.set_crtc(987)); |
1478 | + auto fb = output.fb_for(fake_bo, 1292, 222); |
1479 | + |
1480 | + EXPECT_TRUE(output.set_crtc(*fb)); |
1481 | struct gbm_bo *dummy = reinterpret_cast<struct gbm_bo*>(0x1234567); |
1482 | EXPECT_NO_THROW({ |
1483 | output.set_cursor(dummy); |
1484 | @@ -348,7 +377,9 @@ |
1485 | mgm::RealKMSOutput output{mock_drm.fake_drm.fd(), connector_ids[0], |
1486 | mt::fake_shared(mock_page_flipper)}; |
1487 | |
1488 | - EXPECT_TRUE(output.set_crtc(987)); |
1489 | + auto fb = output.fb_for(fake_bo, 1292, 222); |
1490 | + |
1491 | + EXPECT_TRUE(output.set_crtc(*fb)); |
1492 | struct gbm_bo *dummy = reinterpret_cast<struct gbm_bo*>(0x1234567); |
1493 | output.set_cursor(dummy); |
1494 | EXPECT_FALSE(output.has_cursor()); |
1495 | @@ -394,7 +425,12 @@ |
1496 | const_cast<uint16_t*>(gamma.blue.data()))) |
1497 | .Times(1); |
1498 | |
1499 | - EXPECT_TRUE(output.set_crtc(fb_id)); |
1500 | + append_fb_id(fb_id); |
1501 | + |
1502 | + auto fb = output.fb_for(fake_bo, 1292, 222); |
1503 | + |
1504 | + EXPECT_TRUE(output.set_crtc(*fb)); |
1505 | + |
1506 | output.set_gamma(gamma); |
1507 | } |
1508 | |
1509 | @@ -418,7 +454,11 @@ |
1510 | const_cast<uint16_t*>(gamma.blue.data()))) |
1511 | .WillOnce(Return(-ENOSYS)); |
1512 | |
1513 | - EXPECT_TRUE(output.set_crtc(fb_id)); |
1514 | + append_fb_id(fb_id); |
1515 | + |
1516 | + auto fb = output.fb_for(fake_bo, 1292, 222); |
1517 | + |
1518 | + EXPECT_TRUE(output.set_crtc(*fb)); |
1519 | |
1520 | EXPECT_NO_THROW(output.set_gamma(gamma);); |
1521 | } |
FAILED: Continuous integration, rev:4053 /mir-jenkins. ubuntu. com/job/ mir-ci/ 3043/ /mir-jenkins. ubuntu. com/job/ build-mir/ 4067/console /mir-jenkins. ubuntu. com/job/ build-0- fetch/4154 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= vivid+overlay/ 4144 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= xenial+ overlay/ 4144 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= zesty/4144 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= clang,platform= mesa,release= zesty/4094 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= clang,platform= mesa,release= zesty/4094/ artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= xenial+ overlay/ 4094/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= zesty/4094 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= zesty/4094/ artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= android, release= vivid+overlay/ 4094 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= android, release= vivid+overlay/ 4094/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= android, release= vivid+overlay/ 4094/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= mesa,release= xenial+ overlay/ 4094/console
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild: /mir-jenkins. ubuntu. com/job/ mir-ci/ 3043/rebuild
https:/