Merge lp:~vanvugt/mir/rotate-display-buffer into lp:mir
- rotate-display-buffer
- Merge into development-branch
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Chris Halse Rogers | ||||
Approved revision: | no longer in the source branch. | ||||
Merged at revision: | 1341 | ||||
Proposed branch: | lp:~vanvugt/mir/rotate-display-buffer | ||||
Merge into: | lp:mir | ||||
Diff against target: |
719 lines (+434/-9) 17 files modified
include/platform/mir/graphics/display_buffer.h (+10/-0) include/test/mir_test_doubles/mock_display_buffer.h (+1/-0) include/test/mir_test_doubles/null_display_buffer.h (+1/-0) src/platform/graphics/android/android_display.cpp (+13/-0) src/platform/graphics/android/display_buffer.cpp (+27/-2) src/platform/graphics/android/display_buffer.h (+3/-0) src/platform/graphics/mesa/display.cpp (+18/-3) src/platform/graphics/mesa/display_buffer.cpp (+25/-2) src/platform/graphics/mesa/display_buffer.h (+4/-0) src/server/graphics/nested/nested_output.cpp (+10/-1) src/server/graphics/nested/nested_output.h (+1/-0) src/server/graphics/offscreen/display_buffer.cpp (+10/-1) src/server/graphics/offscreen/display_buffer.h (+1/-0) tests/unit-tests/graphics/android/test_hwc_display.cpp (+50/-0) tests/unit-tests/graphics/mesa/CMakeLists.txt (+1/-0) tests/unit-tests/graphics/mesa/test_display_buffer.cpp (+236/-0) tests/unit-tests/graphics/offscreen/test_offscreen_display.cpp (+23/-0) |
||||
To merge this branch: | bzr merge lp:~vanvugt/mir/rotate-display-buffer | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Chris Halse Rogers | Approve | ||
Kevin DuBois (community) | ok for now | Approve | |
Alan Griffiths | Approve | ||
PS Jenkins bot (community) | continuous-integration | Approve | |
Review via email: mp+202277@code.launchpad.net |
Commit message
Add DisplayBuffer:
screen rotation in GL (for platforms which don't implement rotation natively)
Description of the change
Another stepping stone on the path to screen rotation. The aforementioned Renderer work will be proposed separately, to keep reviews simple. Although some of this proposal may not make sense to the reader without it, so if you really desperately want me to then I will merge the Renderer work into this.
PS Jenkins bot (ps-jenkins) wrote : | # |
Andreas Pokorny (andreas-pokorny) wrote : | # |
I have only two minor changes of improvement that would make the intent clearer and be less verbose:
168 + std::swap(
204 + fb_width = area.size.
205 + fb_height = area.size.
206 + if (rotation == mir_orientation
207 + std::swap(fb_width, fb_height);
But no blocker compared to the unit test issues on mesa.
Kevin DuBois (kdub) wrote : | # |
I'd like to avoid the dynamic_cast in l75 if possible...
Perhaps we could just keep the state of the orientation in mga::AndroidDisplay (and the android display configuration class). Seems a bit more palatable until the android classes improve here. Don't want to block though, abstaining.
Daniel van Vugt (vanvugt) wrote : | # |
All fixed.
Kevin:
I prototyped orient() in the DisplayBuffer interface to avoid the dynamic cast. Unfortunately that creates a bigger problem of then "contractually" having to implement orient() for the more complex mesa::DisplayBu
Also, putting orientation() in AndroidDisplay would not work. The Renderer only has access to the DisplayBuffer interface. Which is clean and I'd like to keep it that way.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1374
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1376
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alan Griffiths (alan-griffiths) wrote : | # |
7 #include <mir/geometry/
8 +#include <mir_toolkit/
This include style is in a small minority:
$ grep "#include <mir" `find include -name \*.h` | wc -l
15
$ grep "#include \"mir" `find include -name \*.h` | wc -l
212
Kevin DuBois (kdub) wrote : | # |
> All fixed.
>
> Kevin:
> I prototyped orient() in the DisplayBuffer interface to avoid the dynamic
> cast. Unfortunately that creates a bigger problem of then "contractually"
> having to implement orient() for the more complex mesa::DisplayBu
> is otherwise unnecessary. The problem only exists because AndroidDisplay
> refuses to admit its display_buffer is android:
> purposes of stubbing in tests. Though you can see AndroidDisplay already
> employs dynamic_cast...
> Also, putting orientation() in AndroidDisplay would not work. The Renderer
> only has access to the DisplayBuffer interface. Which is clean and I'd like to
> keep it that way.
After seeing the other MP's today, I see why it wouldn't work.
In as far as reconfiguring the display goes, the android classes need a bit of work with the already-in-place mode() function, so I don't object to doing this with the orientation. (although I might redo the orientation and mode state to live solely within the DisplayDevice classes in the future.)
Chris Halse Rogers (raof) wrote : | # |
Looks fine to me
Preview Diff
1 | === modified file 'include/platform/mir/graphics/display_buffer.h' |
2 | --- include/platform/mir/graphics/display_buffer.h 2014-01-17 23:07:03 +0000 |
3 | +++ include/platform/mir/graphics/display_buffer.h 2014-01-21 07:20:58 +0000 |
4 | @@ -21,6 +21,7 @@ |
5 | |
6 | #include "renderable.h" |
7 | #include <mir/geometry/rectangle.h> |
8 | +#include <mir_toolkit/common.h> |
9 | |
10 | #include <memory> |
11 | #include <functional> |
12 | @@ -63,6 +64,15 @@ |
13 | virtual bool can_bypass() const = 0; |
14 | virtual void post_update(std::shared_ptr<Buffer> /* bypass_buf */) {} |
15 | |
16 | + /** Returns the orientation of the display buffer relative to how the |
17 | + * user should see it (the orientation of the output). |
18 | + * This tells us how much (if any) rotation the renderer needs to do. |
19 | + * If your DisplayBuffer can do the rotation itself then this will |
20 | + * always return mir_orientation_normal. If the DisplayBuffer does not |
21 | + * implement the rotation itself then this function will return the |
22 | + * amount of rotation the renderer must do to make things "look right". |
23 | + */ |
24 | + virtual MirOrientation orientation() const = 0; |
25 | |
26 | protected: |
27 | DisplayBuffer() = default; |
28 | |
29 | === modified file 'include/test/mir_test_doubles/mock_display_buffer.h' |
30 | --- include/test/mir_test_doubles/mock_display_buffer.h 2014-01-17 19:42:09 +0000 |
31 | +++ include/test/mir_test_doubles/mock_display_buffer.h 2014-01-21 07:20:58 +0000 |
32 | @@ -40,6 +40,7 @@ |
33 | MOCK_CONST_METHOD0(can_bypass, bool()); |
34 | MOCK_METHOD2(render_and_post_update, void(std::list<graphics::Renderable> const&, |
35 | std::function<void(graphics::Renderable const&)> const&)); |
36 | + MOCK_CONST_METHOD0(orientation, MirOrientation()); |
37 | }; |
38 | |
39 | } |
40 | |
41 | === modified file 'include/test/mir_test_doubles/null_display_buffer.h' |
42 | --- include/test/mir_test_doubles/null_display_buffer.h 2014-01-17 19:42:09 +0000 |
43 | +++ include/test/mir_test_doubles/null_display_buffer.h 2014-01-21 07:20:58 +0000 |
44 | @@ -39,6 +39,7 @@ |
45 | void render_and_post_update( |
46 | std::list<graphics::Renderable> const&, |
47 | std::function<void(graphics::Renderable const&)> const&) {} |
48 | + MirOrientation orientation() const override { return mir_orientation_normal; } |
49 | }; |
50 | |
51 | } |
52 | |
53 | === modified file 'src/platform/graphics/android/android_display.cpp' |
54 | --- src/platform/graphics/android/android_display.cpp 2014-01-13 06:12:33 +0000 |
55 | +++ src/platform/graphics/android/android_display.cpp 2014-01-21 07:20:58 +0000 |
56 | @@ -59,12 +59,25 @@ |
57 | |
58 | void mga::AndroidDisplay::configure(mg::DisplayConfiguration const& configuration) |
59 | { |
60 | + MirOrientation orientation = mir_orientation_normal; |
61 | + |
62 | configuration.for_each_output([&](mg::DisplayConfigurationOutput const& output) |
63 | { |
64 | // TODO: Properly support multiple outputs |
65 | display_device->mode(output.power_mode); |
66 | + orientation = output.orientation; |
67 | }); |
68 | current_configuration = dynamic_cast<mga::AndroidDisplayConfiguration const&>(configuration); |
69 | + |
70 | + /* |
71 | + * It's tempting to put orient() into the base class and so avoid this |
72 | + * cast, but we only need it in the Android implementation right now. |
73 | + */ |
74 | + if (android::DisplayBuffer* db = |
75 | + dynamic_cast<mga::DisplayBuffer*>(display_buffer.get())) |
76 | + { |
77 | + db->orient(orientation); |
78 | + } |
79 | } |
80 | |
81 | void mga::AndroidDisplay::register_configuration_change_handler( |
82 | |
83 | === modified file 'src/platform/graphics/android/display_buffer.cpp' |
84 | --- src/platform/graphics/android/display_buffer.cpp 2014-01-20 16:38:54 +0000 |
85 | +++ src/platform/graphics/android/display_buffer.cpp 2014-01-21 07:20:58 +0000 |
86 | @@ -23,6 +23,7 @@ |
87 | #include <functional> |
88 | #include <boost/throw_exception.hpp> |
89 | #include <stdexcept> |
90 | +#include <algorithm> |
91 | |
92 | namespace mga=mir::graphics::android; |
93 | namespace geom=mir::geometry; |
94 | @@ -35,13 +36,21 @@ |
95 | : fb_bundle{fb_bundle}, |
96 | display_device{display_device}, |
97 | native_window{native_window}, |
98 | - gl_context{shared_gl_context, std::bind(mga::create_window_surface, std::placeholders::_1, std::placeholders::_2, native_window.get())} |
99 | + gl_context{shared_gl_context, std::bind(mga::create_window_surface, std::placeholders::_1, std::placeholders::_2, native_window.get())}, |
100 | + rotation{mir_orientation_normal} |
101 | { |
102 | } |
103 | |
104 | geom::Rectangle mga::DisplayBuffer::view_area() const |
105 | { |
106 | - return {geom::Point{}, fb_bundle->fb_size()}; |
107 | + auto const& size = fb_bundle->fb_size(); |
108 | + int width = size.width.as_int(); |
109 | + int height = size.height.as_int(); |
110 | + |
111 | + if (rotation == mir_orientation_left || rotation == mir_orientation_right) |
112 | + std::swap(width, height); |
113 | + |
114 | + return {{0,0}, {width,height}}; |
115 | } |
116 | |
117 | void mga::DisplayBuffer::make_current() |
118 | @@ -92,3 +101,19 @@ |
119 | { |
120 | return false; |
121 | } |
122 | + |
123 | +MirOrientation mga::DisplayBuffer::orientation() const |
124 | +{ |
125 | + /* |
126 | + * android::DisplayBuffer is aways created with physical width/height |
127 | + * (not rotated). So we just need to pass through the desired rotation |
128 | + * and let the renderer do it. |
129 | + * If and when we choose to implement HWC rotation, this may change. |
130 | + */ |
131 | + return rotation; |
132 | +} |
133 | + |
134 | +void mga::DisplayBuffer::orient(MirOrientation rot) |
135 | +{ |
136 | + rotation = rot; |
137 | +} |
138 | |
139 | === modified file 'src/platform/graphics/android/display_buffer.h' |
140 | --- src/platform/graphics/android/display_buffer.h 2014-01-20 16:38:54 +0000 |
141 | +++ src/platform/graphics/android/display_buffer.h 2014-01-21 07:20:58 +0000 |
142 | @@ -50,6 +50,8 @@ |
143 | void render_and_post_update( |
144 | std::list<Renderable> const& renderlist, |
145 | std::function<void(Renderable const&)> const& render_fn); |
146 | + MirOrientation orientation() const override; |
147 | + void orient(MirOrientation); |
148 | |
149 | private: |
150 | void render_and_post(); |
151 | @@ -59,6 +61,7 @@ |
152 | std::shared_ptr<ANativeWindow> const native_window; |
153 | GLContext gl_context; |
154 | bool prepared; |
155 | + MirOrientation rotation; |
156 | }; |
157 | |
158 | } |
159 | |
160 | === modified file 'src/platform/graphics/mesa/display.cpp' |
161 | --- src/platform/graphics/mesa/display.cpp 2014-01-13 06:12:33 +0000 |
162 | +++ src/platform/graphics/mesa/display.cpp 2014-01-21 07:20:58 +0000 |
163 | @@ -36,6 +36,7 @@ |
164 | #include <boost/exception/errinfo_errno.hpp> |
165 | |
166 | #include <stdexcept> |
167 | +#include <algorithm> |
168 | |
169 | namespace mgm = mir::graphics::mesa; |
170 | namespace mg = mir::graphics; |
171 | @@ -147,6 +148,7 @@ |
172 | { |
173 | auto bounding_rect = group.bounding_rectangle(); |
174 | std::vector<std::shared_ptr<KMSOutput>> kms_outputs; |
175 | + MirOrientation orientation = mir_orientation_normal; |
176 | |
177 | group.for_each_output([&](DisplayConfigurationOutput const& conf_output) |
178 | { |
179 | @@ -158,17 +160,30 @@ |
180 | kms_output->configure(conf_output.top_left - bounding_rect.top_left, mode_index); |
181 | kms_output->set_power_mode(conf_output.power_mode); |
182 | kms_outputs.push_back(kms_output); |
183 | + |
184 | + /* |
185 | + * Presently OverlappingOutputGroup guarantees all grouped |
186 | + * outputs have the same orientation. |
187 | + */ |
188 | + orientation = conf_output.orientation; |
189 | }); |
190 | |
191 | - auto surface = |
192 | - platform->gbm.create_scanout_surface(bounding_rect.size.width.as_uint32_t(), |
193 | - bounding_rect.size.height.as_uint32_t()); |
194 | + uint32_t width = bounding_rect.size.width.as_uint32_t(); |
195 | + uint32_t height = bounding_rect.size.height.as_uint32_t(); |
196 | + if (orientation == mir_orientation_left || |
197 | + orientation == mir_orientation_right) |
198 | + { |
199 | + std::swap(width, height); |
200 | + } |
201 | + |
202 | + auto surface = platform->gbm.create_scanout_surface(width, height); |
203 | |
204 | std::unique_ptr<DisplayBuffer> db{ |
205 | new DisplayBuffer{platform, listener, |
206 | kms_outputs, |
207 | std::move(surface), |
208 | bounding_rect, |
209 | + orientation, |
210 | shared_egl.context()}}; |
211 | |
212 | display_buffers_new.push_back(std::move(db)); |
213 | |
214 | === modified file 'src/platform/graphics/mesa/display_buffer.cpp' |
215 | --- src/platform/graphics/mesa/display_buffer.cpp 2014-01-20 16:38:54 +0000 |
216 | +++ src/platform/graphics/mesa/display_buffer.cpp 2014-01-21 07:20:58 +0000 |
217 | @@ -100,6 +100,7 @@ |
218 | std::vector<std::shared_ptr<KMSOutput>> const& outputs, |
219 | GBMSurfaceUPtr surface_gbm_param, |
220 | geom::Rectangle const& area, |
221 | + MirOrientation rot, |
222 | EGLContext shared_context) |
223 | : last_flipped_bufobj{nullptr}, |
224 | platform(platform), |
225 | @@ -108,8 +109,22 @@ |
226 | outputs(outputs), |
227 | surface_gbm{std::move(surface_gbm_param)}, |
228 | area(area), |
229 | + rotation(rot), |
230 | needs_set_crtc{false} |
231 | { |
232 | + uint32_t area_width = area.size.width.as_uint32_t(); |
233 | + uint32_t area_height = area.size.height.as_uint32_t(); |
234 | + if (rotation == mir_orientation_left || rotation == mir_orientation_right) |
235 | + { |
236 | + fb_width = area_height; |
237 | + fb_height = area_width; |
238 | + } |
239 | + else |
240 | + { |
241 | + fb_width = area_width; |
242 | + fb_height = area_height; |
243 | + } |
244 | + |
245 | egl.setup(platform->gbm, surface_gbm.get(), shared_context); |
246 | |
247 | listener->report_successful_setup_of_native_resources(); |
248 | @@ -165,7 +180,14 @@ |
249 | |
250 | bool mgm::DisplayBuffer::can_bypass() const |
251 | { |
252 | - return true; |
253 | + return (rotation == mir_orientation_normal); |
254 | +} |
255 | + |
256 | + |
257 | +MirOrientation mgm::DisplayBuffer::orientation() const |
258 | +{ |
259 | + // Tell the renderer to do the rotation, since we're not doing it here. |
260 | + return rotation; |
261 | } |
262 | |
263 | void mgm::DisplayBuffer::render_and_post_update( |
264 | @@ -276,7 +298,7 @@ |
265 | auto stride = gbm_bo_get_stride(bo); |
266 | |
267 | /* Create a KMS FB object with the gbm_bo attached to it. */ |
268 | - auto ret = drmModeAddFB(drm.fd, area.size.width.as_uint32_t(), area.size.height.as_uint32_t(), |
269 | + auto ret = drmModeAddFB(drm.fd, fb_width, fb_height, |
270 | 24, 32, stride, handle, &fb_id); |
271 | if (ret) |
272 | return nullptr; |
273 | @@ -331,3 +353,4 @@ |
274 | { |
275 | needs_set_crtc = true; |
276 | } |
277 | + |
278 | |
279 | === modified file 'src/platform/graphics/mesa/display_buffer.h' |
280 | --- src/platform/graphics/mesa/display_buffer.h 2014-01-20 16:38:54 +0000 |
281 | +++ src/platform/graphics/mesa/display_buffer.h 2014-01-21 07:20:58 +0000 |
282 | @@ -48,6 +48,7 @@ |
283 | std::vector<std::shared_ptr<KMSOutput>> const& outputs, |
284 | GBMSurfaceUPtr surface_gbm, |
285 | geometry::Rectangle const& area, |
286 | + MirOrientation rot, |
287 | EGLContext shared_context); |
288 | ~DisplayBuffer(); |
289 | |
290 | @@ -60,6 +61,7 @@ |
291 | void post_update(std::shared_ptr<graphics::Buffer> bypass_buf) override; |
292 | void render_and_post_update(std::list<Renderable> const& renderlist, |
293 | std::function<void(Renderable const&)> const& render_fn); |
294 | + MirOrientation orientation() const override; |
295 | void schedule_set_crtc(); |
296 | |
297 | private: |
298 | @@ -77,6 +79,8 @@ |
299 | GBMSurfaceUPtr surface_gbm; |
300 | helpers::EGLHelper egl; |
301 | geometry::Rectangle area; |
302 | + uint32_t fb_width, fb_height; |
303 | + MirOrientation rotation; |
304 | std::atomic<bool> needs_set_crtc; |
305 | }; |
306 | |
307 | |
308 | === modified file 'src/server/graphics/nested/nested_output.cpp' |
309 | --- src/server/graphics/nested/nested_output.cpp 2014-01-20 16:38:54 +0000 |
310 | +++ src/server/graphics/nested/nested_output.cpp 2014-01-21 07:20:58 +0000 |
311 | @@ -86,7 +86,16 @@ |
312 | std::list<Renderable> const&, |
313 | std::function<void(Renderable const&)> const&) |
314 | { |
315 | -} |
316 | +} |
317 | + |
318 | +MirOrientation mgn::detail::NestedOutput::orientation() const |
319 | +{ |
320 | + /* |
321 | + * Always normal orientation. The real rotation is handled by the |
322 | + * native display. |
323 | + */ |
324 | + return mir_orientation_normal; |
325 | +} |
326 | |
327 | mgn::detail::NestedOutput::~NestedOutput() noexcept |
328 | { |
329 | |
330 | === modified file 'src/server/graphics/nested/nested_output.h' |
331 | --- src/server/graphics/nested/nested_output.h 2014-01-20 16:38:54 +0000 |
332 | +++ src/server/graphics/nested/nested_output.h 2014-01-21 07:20:58 +0000 |
333 | @@ -64,6 +64,7 @@ |
334 | void release_current() override; |
335 | void post_update() override; |
336 | virtual bool can_bypass() const override; |
337 | + MirOrientation orientation() const override; |
338 | |
339 | void render_and_post_update( |
340 | std::list<Renderable> const& renderlist, |
341 | |
342 | === modified file 'src/server/graphics/offscreen/display_buffer.cpp' |
343 | --- src/server/graphics/offscreen/display_buffer.cpp 2014-01-20 16:38:54 +0000 |
344 | +++ src/server/graphics/offscreen/display_buffer.cpp 2014-01-21 07:20:58 +0000 |
345 | @@ -153,4 +153,13 @@ |
346 | std::list<Renderable> const&, |
347 | std::function<void(Renderable const&)> const&) |
348 | { |
349 | -} |
350 | +} |
351 | + |
352 | +MirOrientation mgo::DisplayBuffer::orientation() const |
353 | +{ |
354 | + /* |
355 | + * The display buffer's already constructed with rotated dimensions, |
356 | + * so nothing more to do. |
357 | + */ |
358 | + return mir_orientation_normal; |
359 | +} |
360 | |
361 | === modified file 'src/server/graphics/offscreen/display_buffer.h' |
362 | --- src/server/graphics/offscreen/display_buffer.h 2014-01-17 19:42:09 +0000 |
363 | +++ src/server/graphics/offscreen/display_buffer.h 2014-01-21 07:20:58 +0000 |
364 | @@ -68,6 +68,7 @@ |
365 | void post_update(); |
366 | |
367 | bool can_bypass() const; |
368 | + MirOrientation orientation() const override; |
369 | |
370 | void render_and_post_update( |
371 | std::list<Renderable> const& renderlist, |
372 | |
373 | === modified file 'tests/unit-tests/graphics/android/test_hwc_display.cpp' |
374 | --- tests/unit-tests/graphics/android/test_hwc_display.cpp 2014-01-20 16:38:54 +0000 |
375 | +++ tests/unit-tests/graphics/android/test_hwc_display.cpp 2014-01-21 07:20:58 +0000 |
376 | @@ -142,6 +142,56 @@ |
377 | }); |
378 | } |
379 | |
380 | +TEST_F(AndroidDisplayBufferTest, defaults_to_normal_orientation) |
381 | +{ |
382 | + mga::DisplayBuffer db(mock_fb_bundle, mock_display_device, native_window, |
383 | + *gl_context); |
384 | + |
385 | + EXPECT_EQ(mir_orientation_normal, db.orientation()); |
386 | +} |
387 | + |
388 | +TEST_F(AndroidDisplayBufferTest, orientation_is_passed_through) |
389 | +{ |
390 | + mga::DisplayBuffer db(mock_fb_bundle, mock_display_device, native_window, |
391 | + *gl_context); |
392 | + |
393 | + for (auto const& ori : {mir_orientation_normal, |
394 | + mir_orientation_left, |
395 | + mir_orientation_right, |
396 | + mir_orientation_inverted}) |
397 | + { |
398 | + db.orient(ori); |
399 | + EXPECT_EQ(ori, db.orientation()); |
400 | + } |
401 | +} |
402 | + |
403 | +TEST_F(AndroidDisplayBufferTest, rotation_transposes_dimensions) |
404 | +{ |
405 | + using namespace testing; |
406 | + |
407 | + int const width = 123; |
408 | + int const height = 456; |
409 | + geom::Size const normal{width, height}; |
410 | + geom::Size const transposed{height, width}; |
411 | + |
412 | + EXPECT_CALL(*mock_fb_bundle, fb_size()) |
413 | + .WillRepeatedly(Return(normal)); |
414 | + |
415 | + mga::DisplayBuffer db(mock_fb_bundle, mock_display_device, native_window, |
416 | + *gl_context); |
417 | + |
418 | + EXPECT_EQ(normal, db.view_area().size); |
419 | + |
420 | + db.orient(mir_orientation_right); |
421 | + EXPECT_EQ(transposed, db.view_area().size); |
422 | + |
423 | + db.orient(mir_orientation_inverted); |
424 | + EXPECT_EQ(normal, db.view_area().size); |
425 | + |
426 | + db.orient(mir_orientation_left); |
427 | + EXPECT_EQ(transposed, db.view_area().size); |
428 | +} |
429 | + |
430 | TEST_F(AndroidDisplayBufferTest, test_db_forwards_size_along) |
431 | { |
432 | using namespace testing; |
433 | |
434 | === modified file 'tests/unit-tests/graphics/mesa/CMakeLists.txt' |
435 | --- tests/unit-tests/graphics/mesa/CMakeLists.txt 2014-01-13 06:12:33 +0000 |
436 | +++ tests/unit-tests/graphics/mesa/CMakeLists.txt 2014-01-21 07:20:58 +0000 |
437 | @@ -3,6 +3,7 @@ |
438 | ${CMAKE_CURRENT_SOURCE_DIR}/test_gbm_buffer.cpp |
439 | ${CMAKE_CURRENT_SOURCE_DIR}/test_buffer_allocator.cpp |
440 | ${CMAKE_CURRENT_SOURCE_DIR}/test_display.cpp |
441 | + ${CMAKE_CURRENT_SOURCE_DIR}/test_display_buffer.cpp |
442 | ${CMAKE_CURRENT_SOURCE_DIR}/test_display_multi_monitor.cpp |
443 | ${CMAKE_CURRENT_SOURCE_DIR}/test_display_configuration.cpp |
444 | ${CMAKE_CURRENT_SOURCE_DIR}/test_internal_client.cpp |
445 | |
446 | === added file 'tests/unit-tests/graphics/mesa/test_display_buffer.cpp' |
447 | --- tests/unit-tests/graphics/mesa/test_display_buffer.cpp 1970-01-01 00:00:00 +0000 |
448 | +++ tests/unit-tests/graphics/mesa/test_display_buffer.cpp 2014-01-21 07:20:58 +0000 |
449 | @@ -0,0 +1,236 @@ |
450 | +/* |
451 | + * Copyright © 2014 Canonical Ltd. |
452 | + * |
453 | + * This program is free software: you can redistribute it and/or modify |
454 | + * it under the terms of the GNU General Public License version 3 as |
455 | + * published by the Free Software Foundation. |
456 | + * |
457 | + * This program is distributed in the hope that it will be useful, |
458 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
459 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
460 | + * GNU General Public License for more details. |
461 | + * |
462 | + * You should have received a copy of the GNU General Public License |
463 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
464 | + * |
465 | + * Authored by: Daniel van Vugt <daniel.van.vugt@canonical.com> |
466 | + */ |
467 | +#include "src/platform/graphics/mesa/platform.h" |
468 | +#include "src/platform/graphics/mesa/display_buffer.h" |
469 | +#include "mir/graphics/null_display_report.h" |
470 | +#include "mir_test_doubles/mock_egl.h" |
471 | +#include "mir_test_doubles/mock_gl.h" |
472 | +#include "mir_test_doubles/null_platform.h" |
473 | +#include "mir_test_doubles/null_virtual_terminal.h" |
474 | +#include "mir_test_doubles/mock_drm.h" |
475 | +#include "mir_test_doubles/mock_gbm.h" |
476 | +#include "mir_test_framework/udev_environment.h" |
477 | + |
478 | +#include <gtest/gtest.h> |
479 | +#include <gmock/gmock.h> |
480 | +#include <gbm.h> |
481 | + |
482 | +using namespace testing; |
483 | +using namespace mir; |
484 | +using namespace std; |
485 | +using namespace mir::test::doubles; |
486 | +using namespace mir::mir_test_framework; |
487 | + |
488 | +class MesaDisplayBufferTest : public Test |
489 | +{ |
490 | +public: |
491 | + MesaDisplayBufferTest() |
492 | + { |
493 | + ON_CALL(mock_egl, eglChooseConfig(_,_,_,1,_)) |
494 | + .WillByDefault(DoAll(SetArgPointee<2>(mock_egl.fake_configs[0]), |
495 | + SetArgPointee<4>(1), |
496 | + Return(EGL_TRUE))); |
497 | + |
498 | + ON_CALL(mock_egl, eglQueryString(_,EGL_EXTENSIONS)) |
499 | + .WillByDefault(Return("EGL_KHR_image " |
500 | + "EGL_KHR_image_base " |
501 | + "EGL_MESA_drm_image")); |
502 | + |
503 | + ON_CALL(mock_gl, glGetString(GL_EXTENSIONS)) |
504 | + .WillByDefault(Return(reinterpret_cast<const GLubyte*>( |
505 | + "GL_OES_texture_npot " |
506 | + "GL_OES_EGL_image"))); |
507 | + |
508 | + fake_bo = reinterpret_cast<gbm_bo*>(123); |
509 | + ON_CALL(mock_gbm, gbm_surface_lock_front_buffer(_)) |
510 | + .WillByDefault(Return(fake_bo)); |
511 | + fake_handle.u32 = 123; |
512 | + ON_CALL(mock_gbm, gbm_bo_get_handle(_)) |
513 | + .WillByDefault(Return(fake_handle)); |
514 | + ON_CALL(mock_gbm, gbm_bo_get_stride(_)) |
515 | + .WillByDefault(Return(456)); |
516 | + |
517 | + fake_devices.add_standard_drm_devices(); |
518 | + } |
519 | + |
520 | + // The platform has an implicit dependency on mock_gbm etc so must be |
521 | + // reconstructed locally to ensure its lifetime is shorter than mock_gbm. |
522 | + shared_ptr<graphics::mesa::Platform> create_platform() |
523 | + { |
524 | + return make_shared<graphics::mesa::Platform>( |
525 | + make_shared<graphics::NullDisplayReport>(), |
526 | + make_shared<NullVirtualTerminal>()); |
527 | + } |
528 | + |
529 | +protected: |
530 | + NiceMock<MockGBM> mock_gbm; |
531 | + NiceMock<MockEGL> mock_egl; |
532 | + NiceMock<MockGL> mock_gl; |
533 | + NiceMock<MockDRM> mock_drm; |
534 | + gbm_bo* fake_bo; |
535 | + gbm_bo_handle fake_handle; |
536 | + UdevEnvironment fake_devices; |
537 | +}; |
538 | + |
539 | +TEST_F(MesaDisplayBufferTest, unrotated_view_area_is_untouched) |
540 | +{ |
541 | + geometry::Rectangle const area{{12,34}, {56,78}}; |
542 | + |
543 | + graphics::mesa::DisplayBuffer db( |
544 | + create_platform(), |
545 | + make_shared<graphics::NullDisplayReport>(), |
546 | + {}, |
547 | + nullptr, |
548 | + area, |
549 | + mir_orientation_normal, |
550 | + mock_egl.fake_egl_context); |
551 | + |
552 | + EXPECT_EQ(area, db.view_area()); |
553 | +} |
554 | + |
555 | +TEST_F(MesaDisplayBufferTest, normal_orientation_can_bypass) |
556 | +{ |
557 | + geometry::Rectangle const area{{12,34}, {56,78}}; |
558 | + |
559 | + graphics::mesa::DisplayBuffer db( |
560 | + create_platform(), |
561 | + make_shared<graphics::NullDisplayReport>(), |
562 | + {}, |
563 | + nullptr, |
564 | + area, |
565 | + mir_orientation_normal, |
566 | + mock_egl.fake_egl_context); |
567 | + |
568 | + EXPECT_TRUE(db.can_bypass()); |
569 | +} |
570 | + |
571 | +TEST_F(MesaDisplayBufferTest, rotated_cannot_bypass) |
572 | +{ |
573 | + geometry::Rectangle const area{{12,34}, {56,78}}; |
574 | + |
575 | + graphics::mesa::DisplayBuffer db( |
576 | + create_platform(), |
577 | + make_shared<graphics::NullDisplayReport>(), |
578 | + {}, |
579 | + nullptr, |
580 | + area, |
581 | + mir_orientation_right, |
582 | + mock_egl.fake_egl_context); |
583 | + |
584 | + EXPECT_FALSE(db.can_bypass()); |
585 | +} |
586 | + |
587 | +TEST_F(MesaDisplayBufferTest, orientation_not_implemented_internally) |
588 | +{ |
589 | + geometry::Rectangle const area{{12,34}, {56,78}}; |
590 | + |
591 | + graphics::mesa::DisplayBuffer db( |
592 | + create_platform(), |
593 | + make_shared<graphics::NullDisplayReport>(), |
594 | + {}, |
595 | + nullptr, |
596 | + area, |
597 | + mir_orientation_left, |
598 | + mock_egl.fake_egl_context); |
599 | + |
600 | + EXPECT_EQ(mir_orientation_left, db.orientation()); |
601 | +} |
602 | + |
603 | +TEST_F(MesaDisplayBufferTest, normal_rotation_constructs_normal_fb) |
604 | +{ |
605 | + int const width = 56; |
606 | + int const height = 78; |
607 | + geometry::Rectangle const area{{12,34}, {width,height}}; |
608 | + |
609 | + EXPECT_CALL(mock_gbm, gbm_bo_get_user_data(_)) |
610 | + .WillOnce(Return((void*)0)); |
611 | + EXPECT_CALL(mock_drm, drmModeAddFB(_, width, height, _, _, _, _, _)) |
612 | + .Times(1); |
613 | + |
614 | + graphics::mesa::DisplayBuffer db( |
615 | + create_platform(), |
616 | + make_shared<graphics::NullDisplayReport>(), |
617 | + {}, |
618 | + nullptr, |
619 | + area, |
620 | + mir_orientation_normal, |
621 | + mock_egl.fake_egl_context); |
622 | +} |
623 | + |
624 | +TEST_F(MesaDisplayBufferTest, left_rotation_constructs_transposed_fb) |
625 | +{ |
626 | + int const width = 56; |
627 | + int const height = 78; |
628 | + geometry::Rectangle const area{{12,34}, {width,height}}; |
629 | + |
630 | + EXPECT_CALL(mock_gbm, gbm_bo_get_user_data(_)) |
631 | + .WillOnce(Return((void*)0)); |
632 | + EXPECT_CALL(mock_drm, drmModeAddFB(_, height, width, _, _, _, _, _)) |
633 | + .Times(1); |
634 | + |
635 | + graphics::mesa::DisplayBuffer db( |
636 | + create_platform(), |
637 | + make_shared<graphics::NullDisplayReport>(), |
638 | + {}, |
639 | + nullptr, |
640 | + area, |
641 | + mir_orientation_left, |
642 | + mock_egl.fake_egl_context); |
643 | +} |
644 | + |
645 | +TEST_F(MesaDisplayBufferTest, inverted_rotation_constructs_normal_fb) |
646 | +{ |
647 | + int const width = 56; |
648 | + int const height = 78; |
649 | + geometry::Rectangle const area{{12,34}, {width,height}}; |
650 | + |
651 | + EXPECT_CALL(mock_gbm, gbm_bo_get_user_data(_)) |
652 | + .WillOnce(Return((void*)0)); |
653 | + EXPECT_CALL(mock_drm, drmModeAddFB(_, width, height, _, _, _, _, _)) |
654 | + .Times(1); |
655 | + |
656 | + graphics::mesa::DisplayBuffer db( |
657 | + create_platform(), |
658 | + make_shared<graphics::NullDisplayReport>(), |
659 | + {}, |
660 | + nullptr, |
661 | + area, |
662 | + mir_orientation_inverted, |
663 | + mock_egl.fake_egl_context); |
664 | +} |
665 | + |
666 | +TEST_F(MesaDisplayBufferTest, right_rotation_constructs_transposed_fb) |
667 | +{ |
668 | + int const width = 56; |
669 | + int const height = 78; |
670 | + geometry::Rectangle const area{{12,34}, {width,height}}; |
671 | + |
672 | + EXPECT_CALL(mock_gbm, gbm_bo_get_user_data(_)) |
673 | + .WillOnce(Return((void*)0)); |
674 | + EXPECT_CALL(mock_drm, drmModeAddFB(_, height, width, _, _, _, _, _)) |
675 | + .Times(1); |
676 | + |
677 | + graphics::mesa::DisplayBuffer db( |
678 | + create_platform(), |
679 | + make_shared<graphics::NullDisplayReport>(), |
680 | + {}, |
681 | + nullptr, |
682 | + area, |
683 | + mir_orientation_right, |
684 | + mock_egl.fake_egl_context); |
685 | +} |
686 | |
687 | === modified file 'tests/unit-tests/graphics/offscreen/test_offscreen_display.cpp' |
688 | --- tests/unit-tests/graphics/offscreen/test_offscreen_display.cpp 2013-11-18 12:35:14 +0000 |
689 | +++ tests/unit-tests/graphics/offscreen/test_offscreen_display.cpp 2014-01-21 07:20:58 +0000 |
690 | @@ -83,6 +83,29 @@ |
691 | std::make_shared<mg::NullDisplayReport>()}; |
692 | } |
693 | |
694 | +TEST_F(OffscreenDisplayTest, orientation_normal) |
695 | +{ |
696 | + using namespace ::testing; |
697 | + |
698 | + EGLNativeDisplayType const native_display{ |
699 | + reinterpret_cast<EGLNativeDisplayType>(0x12345)}; |
700 | + |
701 | + mgo::Display display{ |
702 | + std::make_shared<StubBasicPlatform>(native_display), |
703 | + std::make_shared<mg::DefaultDisplayConfigurationPolicy>(), |
704 | + std::make_shared<mg::NullDisplayReport>()}; |
705 | + |
706 | + int count = 0; |
707 | + display.for_each_display_buffer( |
708 | + [&](mg::DisplayBuffer& db) |
709 | + { |
710 | + ++count; |
711 | + EXPECT_EQ(mir_orientation_normal, db.orientation()); |
712 | + }); |
713 | + |
714 | + EXPECT_TRUE(count); |
715 | +} |
716 | + |
717 | TEST_F(OffscreenDisplayTest, makes_fbo_current_rendering_target) |
718 | { |
719 | using namespace ::testing; |
FAILED: Continuous integration, rev:1370 jenkins. qa.ubuntu. com/job/ mir-team- mir-development -branch- ci/686/ jenkins. qa.ubuntu. com/job/ mir-android- trusty- i386-build/ 673 jenkins. qa.ubuntu. com/job/ mir-clang- trusty- amd64-build/ 669 jenkins. qa.ubuntu. com/job/ mir-mediumtests -trusty- touch/275 jenkins. qa.ubuntu. com/job/ mir-team- mir-development -branch- trusty- amd64-ci/ 416/console jenkins. qa.ubuntu. com/job/ mir-team- mir-development -branch- trusty- armhf-ci/ 420 jenkins. qa.ubuntu. com/job/ mir-team- mir-development -branch- trusty- armhf-ci/ 420/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ mir-mediumtests -builder- trusty- armhf/275 jenkins. qa.ubuntu. com/job/ mir-mediumtests -builder- trusty- armhf/275/ artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ mir-mediumtests -runner- mako/291 s-jenkins. ubuntu- ci:8080/ job/touch- flash-device/ 3201
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/mir- team-mir- development- branch- ci/686/ rebuild
http://