Merge lp:~alan-griffiths/mir/fix-1706718 into lp:mir
- fix-1706718
- Merge into development-branch
Status: | Merged |
---|---|
Approved by: | Gerry Boland |
Approved revision: | no longer in the source branch. |
Merged at revision: | 4216 |
Proposed branch: | lp:~alan-griffiths/mir/fix-1706718 |
Merge into: | lp:mir |
Diff against target: |
419 lines (+146/-69) 4 files modified
src/platforms/mesa/server/kms/cursor.cpp (+109/-47) src/platforms/mesa/server/kms/cursor.h (+11/-4) src/platforms/mesa/server/kms/display.cpp (+11/-5) tests/unit-tests/platforms/mesa/kms/test_cursor.cpp (+15/-13) |
To merge this branch: | bzr merge lp:~alan-griffiths/mir/fix-1706718 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mir CI Bot | continuous-integration | Approve | |
Gerry Boland (community) | Approve | ||
Review via email: mp+328171@code.launchpad.net |
Commit message
[mesa-kms] Respect display orientation when painting cursor. (LP: #1610078)
Description of the change
[mesa-kms] Respect display orientation when painting cursor
The test changes are for three reasons:
1. they can no longer assume that the image data is not referenced and the pointer passed "straight through".
2. Throwing for "oversized image" isn't useful behaviour.
3. the hotspot should also rotate, so the expectations were wrong by the image size (64) in assorted directions.
Mir CI Bot (mir-ci-bot) wrote : | # |
Alan Griffiths (alan-griffiths) wrote : | # |
Guess who forgot to run the tests. :(
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:4221
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:4223
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:4224
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:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Gerry Boland (gerboland) wrote : | # |
Bug: changing display orientation doesn't cause cursor redraw (but does redraw scene). Only moving the mouse triggers the cursor redraw.
Testing directly on hardware, mir_demo_server and mir_demo_
Alan Griffiths (alan-griffiths) wrote : | # |
> Bug: changing display orientation doesn't cause cursor redraw (but does redraw
> scene). Only moving the mouse triggers the cursor redraw.
>
> Testing directly on hardware, mir_demo_server and
> mir_demo_
Fixed
Gerry Boland (gerboland) wrote : | # |
LGTM
Though the --x-cursor-theme arg doesn't seem to be doing anything when I try it..
Mir CI Bot (mir-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:4225
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:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Preview Diff
1 | === modified file 'src/platforms/mesa/server/kms/cursor.cpp' | |||
2 | --- src/platforms/mesa/server/kms/cursor.cpp 2017-07-20 14:11:27 +0000 | |||
3 | +++ src/platforms/mesa/server/kms/cursor.cpp 2017-07-28 15:12:01 +0000 | |||
4 | @@ -100,7 +100,7 @@ | |||
5 | 100 | } | 100 | } |
6 | 101 | } | 101 | } |
7 | 102 | 102 | ||
9 | 103 | mgm::Cursor::GBMBOWrapper::GBMBOWrapper(int fd) : | 103 | mgm::Cursor::GBMBOWrapper::GBMBOWrapper(int fd, MirOrientation orientation) : |
10 | 104 | device{gbm_create_device_checked(fd)}, | 104 | device{gbm_create_device_checked(fd)}, |
11 | 105 | buffer{ | 105 | buffer{ |
12 | 106 | gbm_bo_create( | 106 | gbm_bo_create( |
13 | @@ -108,7 +108,8 @@ | |||
14 | 108 | get_drm_cursor_width(fd), | 108 | get_drm_cursor_width(fd), |
15 | 109 | get_drm_cursor_height(fd), | 109 | get_drm_cursor_height(fd), |
16 | 110 | GBM_FORMAT_ARGB8888, | 110 | GBM_FORMAT_ARGB8888, |
18 | 111 | GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE)} | 111 | GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE)}, |
19 | 112 | current_orientation{orientation} | ||
20 | 112 | { | 113 | { |
21 | 113 | if (!buffer) BOOST_THROW_EXCEPTION(std::runtime_error("failed to create gbm buffer")); | 114 | if (!buffer) BOOST_THROW_EXCEPTION(std::runtime_error("failed to create gbm buffer")); |
22 | 114 | } | 115 | } |
23 | @@ -128,12 +129,22 @@ | |||
24 | 128 | 129 | ||
25 | 129 | mgm::Cursor::GBMBOWrapper::GBMBOWrapper(GBMBOWrapper&& from) | 130 | mgm::Cursor::GBMBOWrapper::GBMBOWrapper(GBMBOWrapper&& from) |
26 | 130 | : device{from.device}, | 131 | : device{from.device}, |
28 | 131 | buffer{from.buffer} | 132 | buffer{from.buffer}, |
29 | 133 | current_orientation{from.current_orientation} | ||
30 | 132 | { | 134 | { |
31 | 133 | from.buffer = nullptr; | 135 | from.buffer = nullptr; |
32 | 134 | from.device = nullptr; | 136 | from.device = nullptr; |
33 | 135 | } | 137 | } |
34 | 136 | 138 | ||
35 | 139 | auto mir::graphics::mesa::Cursor::GBMBOWrapper::change_orientation(MirOrientation new_orientation) -> bool | ||
36 | 140 | { | ||
37 | 141 | if (current_orientation == new_orientation) | ||
38 | 142 | return false; | ||
39 | 143 | |||
40 | 144 | current_orientation = new_orientation; | ||
41 | 145 | return true; | ||
42 | 146 | } | ||
43 | 147 | |||
44 | 137 | mgm::Cursor::Cursor( | 148 | mgm::Cursor::Cursor( |
45 | 138 | KMSOutputContainer& output_container, | 149 | KMSOutputContainer& output_container, |
46 | 139 | std::shared_ptr<CurrentConfiguration> const& current_configuration) : | 150 | std::shared_ptr<CurrentConfiguration> const& current_configuration) : |
47 | @@ -182,37 +193,86 @@ | |||
48 | 182 | 193 | ||
49 | 183 | void mgm::Cursor::pad_and_write_image_data_locked( | 194 | void mgm::Cursor::pad_and_write_image_data_locked( |
50 | 184 | std::lock_guard<std::mutex> const& lg, | 195 | std::lock_guard<std::mutex> const& lg, |
53 | 185 | gbm_bo* buffer, | 196 | GBMBOWrapper& buffer) |
52 | 186 | CursorImage const& image) | ||
54 | 187 | { | 197 | { |
67 | 188 | auto image_argb = static_cast<uint8_t const*>(image.as_argb_8888()); | 198 | auto const orientation = buffer.orientation(); |
68 | 189 | auto image_width = image.size().width.as_uint32_t(); | 199 | bool const sideways = orientation == mir_orientation_left || orientation == mir_orientation_right; |
69 | 190 | auto image_height = image.size().height.as_uint32_t(); | 200 | |
70 | 191 | auto image_stride = image_width * 4; | 201 | auto const min_width = sideways ? min_buffer_width : min_buffer_height; |
71 | 192 | 202 | auto const min_height = sideways ? min_buffer_height : min_buffer_width; | |
72 | 193 | if (image_width > min_buffer_width || image_height > min_buffer_height) | 203 | |
73 | 194 | { | 204 | auto const image_width = std::min(min_width, size.width.as_uint32_t()); |
74 | 195 | BOOST_THROW_EXCEPTION(std::logic_error("Image is too big for GBM cursor buffer")); | 205 | auto const image_height = std::min(min_height, size.height.as_uint32_t()); |
75 | 196 | } | 206 | auto const image_stride = size.width.as_uint32_t() * 4; |
76 | 197 | 207 | ||
77 | 198 | size_t buffer_stride = gbm_bo_get_stride(buffer); // in bytes | 208 | auto const buffer_stride = std::max(min_width*4, gbm_bo_get_stride(buffer)); // in bytes |
78 | 199 | size_t padded_size = buffer_stride * gbm_bo_get_height(buffer); | 209 | auto const buffer_height = std::max(min_height, gbm_bo_get_height(buffer)); |
79 | 210 | size_t const padded_size = buffer_stride * buffer_height; | ||
80 | 211 | |||
81 | 200 | auto padded = std::unique_ptr<uint8_t[]>(new uint8_t[padded_size]); | 212 | auto padded = std::unique_ptr<uint8_t[]>(new uint8_t[padded_size]); |
83 | 201 | size_t rhs_padding = buffer_stride - image_stride; | 213 | size_t rhs_padding = buffer_stride - 4*image_width; |
84 | 202 | 214 | ||
85 | 215 | auto const filler = 0; // 0x3f; is useful to make buffer visible for debugging | ||
86 | 216 | uint8_t const* src = argb8888.data(); | ||
87 | 203 | uint8_t* dest = &padded[0]; | 217 | uint8_t* dest = &padded[0]; |
88 | 204 | uint8_t const* src = image_argb; | ||
89 | 205 | 218 | ||
91 | 206 | for (unsigned int y = 0; y < image_height; y++) | 219 | switch (orientation) |
92 | 207 | { | 220 | { |
97 | 208 | memcpy(dest, src, image_stride); | 221 | case mir_orientation_normal: |
98 | 209 | memset(dest + image_stride, 0, rhs_padding); | 222 | for (unsigned int y = 0; y < image_height; y++) |
99 | 210 | dest += buffer_stride; | 223 | { |
100 | 211 | src += image_stride; | 224 | memcpy(dest, src, 4*image_width); |
101 | 225 | memset(dest + 4*image_width, filler, rhs_padding); | ||
102 | 226 | dest += buffer_stride; | ||
103 | 227 | src += image_stride; | ||
104 | 228 | } | ||
105 | 229 | |||
106 | 230 | memset(dest, 0, buffer_stride * (buffer_height - image_height)); | ||
107 | 231 | break; | ||
108 | 232 | |||
109 | 233 | case mir_orientation_inverted: | ||
110 | 234 | for (unsigned int row = 0; row != image_height; ++row) | ||
111 | 235 | { | ||
112 | 236 | memset(dest+row*buffer_stride+4*image_width, filler, rhs_padding); | ||
113 | 237 | |||
114 | 238 | for (unsigned int col = 0; col != image_width; ++col) | ||
115 | 239 | { | ||
116 | 240 | memcpy(dest+row*buffer_stride+4*col, src + ((image_height-1)-row)*image_stride + 4*((image_width-1)-col), 4); | ||
117 | 241 | } | ||
118 | 242 | } | ||
119 | 243 | |||
120 | 244 | memset(dest+image_height*buffer_stride, filler, buffer_stride * (buffer_height - image_height)); | ||
121 | 245 | break; | ||
122 | 246 | |||
123 | 247 | case mir_orientation_left: | ||
124 | 248 | for (unsigned int row = 0; row != image_width; ++row) | ||
125 | 249 | { | ||
126 | 250 | memset(dest+row*buffer_stride+4*image_height, filler, rhs_padding); | ||
127 | 251 | |||
128 | 252 | for (unsigned int col = 0; col != image_height; ++col) | ||
129 | 253 | { | ||
130 | 254 | memcpy(dest+row*buffer_stride+4*col, src + ((image_width-1)-row)*4 + image_stride*col, 4); | ||
131 | 255 | } | ||
132 | 256 | } | ||
133 | 257 | |||
134 | 258 | memset(dest+image_width*buffer_stride, filler, buffer_stride * (buffer_height - image_width)); | ||
135 | 259 | break; | ||
136 | 260 | |||
137 | 261 | case mir_orientation_right: | ||
138 | 262 | for (unsigned int row = 0; row != image_width; ++row) | ||
139 | 263 | { | ||
140 | 264 | memset(dest+row*buffer_stride+4*image_height, filler, rhs_padding); | ||
141 | 265 | |||
142 | 266 | for (unsigned int col = 0; col != image_height; ++col) | ||
143 | 267 | { | ||
144 | 268 | memcpy(dest+row*buffer_stride+4*col, src + row*4 + image_stride*((image_height-1)-col), 4); | ||
145 | 269 | } | ||
146 | 270 | } | ||
147 | 271 | |||
148 | 272 | memset(dest+image_width*buffer_stride, filler, buffer_stride * (buffer_height - image_width)); | ||
149 | 273 | break; | ||
150 | 212 | } | 274 | } |
151 | 213 | 275 | ||
152 | 214 | memset(dest, 0, buffer_stride * (gbm_bo_get_height(buffer) - image_height)); | ||
153 | 215 | |||
154 | 216 | write_buffer_data_locked(lg, buffer, &padded[0], padded_size); | 276 | write_buffer_data_locked(lg, buffer, &padded[0], padded_size); |
155 | 217 | } | 277 | } |
156 | 218 | 278 | ||
157 | @@ -231,23 +291,17 @@ | |||
158 | 231 | { | 291 | { |
159 | 232 | std::lock_guard<std::mutex> lg(guard); | 292 | std::lock_guard<std::mutex> lg(guard); |
160 | 233 | 293 | ||
162 | 234 | auto const& size = cursor_image.size(); | 294 | size = cursor_image.size(); |
163 | 295 | |||
164 | 296 | argb8888.resize(size.width.as_uint32_t() * size.height.as_uint32_t() * 4); | ||
165 | 297 | memcpy(argb8888.data(), cursor_image.as_argb_8888(), argb8888.size()); | ||
166 | 235 | 298 | ||
167 | 236 | hotspot = cursor_image.hotspot(); | 299 | hotspot = cursor_image.hotspot(); |
168 | 237 | { | 300 | { |
169 | 238 | auto locked_buffers = buffers.lock(); | 301 | auto locked_buffers = buffers.lock(); |
170 | 239 | for (auto& pair : *locked_buffers) | 302 | for (auto& pair : *locked_buffers) |
171 | 240 | { | 303 | { |
182 | 241 | auto& buffer = pair.second; | 304 | pad_and_write_image_data_locked(lg, pair.second); |
173 | 242 | if (size != geometry::Size{gbm_bo_get_width(buffer), gbm_bo_get_height(buffer)}) | ||
174 | 243 | { | ||
175 | 244 | pad_and_write_image_data_locked(lg, buffer, cursor_image); | ||
176 | 245 | } | ||
177 | 246 | else | ||
178 | 247 | { | ||
179 | 248 | auto const count = size.width.as_uint32_t() * size.height.as_uint32_t() * sizeof(uint32_t); | ||
180 | 249 | write_buffer_data_locked(lg, buffer, cursor_image.as_argb_8888(), count); | ||
181 | 250 | } | ||
183 | 251 | } | 305 | } |
184 | 252 | } | 306 | } |
185 | 253 | 307 | ||
186 | @@ -317,7 +371,7 @@ | |||
187 | 317 | } | 371 | } |
188 | 318 | 372 | ||
189 | 319 | void mgm::Cursor::place_cursor_at_locked( | 373 | void mgm::Cursor::place_cursor_at_locked( |
191 | 320 | std::lock_guard<std::mutex> const&, | 374 | std::lock_guard<std::mutex> const& lg, |
192 | 321 | geometry::Point position, | 375 | geometry::Point position, |
193 | 322 | ForceCursorState force_state) | 376 | ForceCursorState force_state) |
194 | 323 | { | 377 | { |
195 | @@ -334,15 +388,23 @@ | |||
196 | 334 | if (output_rect.contains(position)) | 388 | if (output_rect.contains(position)) |
197 | 335 | { | 389 | { |
198 | 336 | auto dp = transform(output_rect, position - output_rect.top_left, orientation); | 390 | auto dp = transform(output_rect, position - output_rect.top_left, orientation); |
199 | 391 | auto hs = transform(geom::Rectangle{{0,0}, size}, hotspot, orientation); | ||
200 | 337 | 392 | ||
201 | 338 | // It's a little strange that we implement hotspot this way as there is | 393 | // It's a little strange that we implement hotspot this way as there is |
202 | 339 | // drmModeSetCursor2 with hotspot support. However it appears to not actually | 394 | // drmModeSetCursor2 with hotspot support. However it appears to not actually |
203 | 340 | // work on radeon and intel. There also seems to be precedent in weston for | 395 | // work on radeon and intel. There also seems to be precedent in weston for |
204 | 341 | // implementing hotspot in this fashion. | 396 | // implementing hotspot in this fashion. |
207 | 342 | output.move_cursor(geom::Point{} + dp - hotspot); | 397 | output.move_cursor(geom::Point{} + dp - hs); |
208 | 343 | if (force_state || !output.has_cursor()) // TODO - or if orientation had changed - then set buffer.. | 398 | auto& buffer = buffer_for_output(output); |
209 | 399 | |||
210 | 400 | auto const changed_orientation = buffer.change_orientation(orientation); | ||
211 | 401 | |||
212 | 402 | if (changed_orientation) | ||
213 | 403 | pad_and_write_image_data_locked(lg, buffer); | ||
214 | 404 | |||
215 | 405 | if (force_state || !output.has_cursor() || changed_orientation) | ||
216 | 344 | { | 406 | { |
218 | 345 | if (!output.set_cursor(buffer_for_output(output)) || !output.has_cursor()) | 407 | if (!output.set_cursor(buffer) || !output.has_cursor()) |
219 | 346 | set_on_all_outputs = false; | 408 | set_on_all_outputs = false; |
220 | 347 | } | 409 | } |
221 | 348 | } | 410 | } |
222 | @@ -358,7 +420,7 @@ | |||
223 | 358 | last_set_failed = !set_on_all_outputs; | 420 | last_set_failed = !set_on_all_outputs; |
224 | 359 | } | 421 | } |
225 | 360 | 422 | ||
227 | 361 | gbm_bo* mgm::Cursor::buffer_for_output(KMSOutput const& output) | 423 | mgm::Cursor::GBMBOWrapper& mgm::Cursor::buffer_for_output(KMSOutput const& output) |
228 | 362 | { | 424 | { |
229 | 363 | auto locked_buffers = buffers.lock(); | 425 | auto locked_buffers = buffers.lock(); |
230 | 364 | 426 | ||
231 | @@ -366,18 +428,18 @@ | |||
232 | 366 | locked_buffers->begin(), | 428 | locked_buffers->begin(), |
233 | 367 | locked_buffers->end(), | 429 | locked_buffers->end(), |
234 | 368 | [&output](auto const& candidate) | 430 | [&output](auto const& candidate) |
238 | 369 | { | 431 | { |
239 | 370 | return candidate.first == output.drm_fd(); | 432 | return candidate.first == output.drm_fd(); |
240 | 371 | }); | 433 | }); |
241 | 372 | 434 | ||
242 | 373 | if (buffer_it != locked_buffers->end()) | 435 | if (buffer_it != locked_buffers->end()) |
243 | 374 | { | 436 | { |
244 | 375 | return buffer_it->second; | 437 | return buffer_it->second; |
245 | 376 | } | 438 | } |
246 | 377 | 439 | ||
248 | 378 | locked_buffers->push_back(std::make_pair(output.drm_fd(), GBMBOWrapper(output.drm_fd()))); | 440 | locked_buffers->push_back(std::make_pair(output.drm_fd(), GBMBOWrapper(output.drm_fd(), mir_orientation_normal))); |
249 | 379 | 441 | ||
251 | 380 | gbm_bo* bo = locked_buffers->back().second; | 442 | GBMBOWrapper& bo = locked_buffers->back().second; |
252 | 381 | if (gbm_bo_get_width(bo) < min_buffer_width) | 443 | if (gbm_bo_get_width(bo) < min_buffer_width) |
253 | 382 | { | 444 | { |
254 | 383 | min_buffer_width = gbm_bo_get_width(bo); | 445 | min_buffer_width = gbm_bo_get_width(bo); |
255 | 384 | 446 | ||
256 | === modified file 'src/platforms/mesa/server/kms/cursor.h' | |||
257 | --- src/platforms/mesa/server/kms/cursor.h 2017-06-08 08:34:56 +0000 | |||
258 | +++ src/platforms/mesa/server/kms/cursor.h 2017-07-28 15:12:01 +0000 | |||
259 | @@ -85,6 +85,7 @@ | |||
260 | 85 | 85 | ||
261 | 86 | private: | 86 | private: |
262 | 87 | enum ForceCursorState { UpdateState, ForceState }; | 87 | enum ForceCursorState { UpdateState, ForceState }; |
263 | 88 | struct GBMBOWrapper; | ||
264 | 88 | void for_each_used_output(std::function<void(KMSOutput&, geometry::Rectangle const&, MirOrientation orientation)> const& f); | 89 | void for_each_used_output(std::function<void(KMSOutput&, geometry::Rectangle const&, MirOrientation orientation)> const& f); |
265 | 89 | void place_cursor_at(geometry::Point position, ForceCursorState force_state); | 90 | void place_cursor_at(geometry::Point position, ForceCursorState force_state); |
266 | 90 | void place_cursor_at_locked(std::lock_guard<std::mutex> const&, geometry::Point position, ForceCursorState force_state); | 91 | void place_cursor_at_locked(std::lock_guard<std::mutex> const&, geometry::Point position, ForceCursorState force_state); |
267 | @@ -95,31 +96,37 @@ | |||
268 | 95 | size_t count); | 96 | size_t count); |
269 | 96 | void pad_and_write_image_data_locked( | 97 | void pad_and_write_image_data_locked( |
270 | 97 | std::lock_guard<std::mutex> const&, | 98 | std::lock_guard<std::mutex> const&, |
273 | 98 | gbm_bo* buffer, | 99 | GBMBOWrapper& buffer); |
272 | 99 | CursorImage const& image); | ||
274 | 100 | void clear(std::lock_guard<std::mutex> const&); | 100 | void clear(std::lock_guard<std::mutex> const&); |
275 | 101 | 101 | ||
277 | 102 | gbm_bo* buffer_for_output(KMSOutput const& output); | 102 | GBMBOWrapper& buffer_for_output(KMSOutput const& output); |
278 | 103 | 103 | ||
279 | 104 | std::mutex guard; | 104 | std::mutex guard; |
280 | 105 | 105 | ||
281 | 106 | KMSOutputContainer& output_container; | 106 | KMSOutputContainer& output_container; |
282 | 107 | geometry::Point current_position; | 107 | geometry::Point current_position; |
283 | 108 | geometry::Displacement hotspot; | 108 | geometry::Displacement hotspot; |
284 | 109 | geometry::Size size; | ||
285 | 110 | std::vector<uint8_t> argb8888; | ||
286 | 109 | 111 | ||
287 | 110 | bool visible; | 112 | bool visible; |
288 | 111 | bool last_set_failed; | 113 | bool last_set_failed; |
289 | 112 | 114 | ||
290 | 113 | struct GBMBOWrapper | 115 | struct GBMBOWrapper |
291 | 114 | { | 116 | { |
293 | 115 | GBMBOWrapper(int fd); | 117 | GBMBOWrapper(int fd, MirOrientation orientation); |
294 | 116 | operator gbm_bo*(); | 118 | operator gbm_bo*(); |
295 | 119 | |||
296 | 120 | auto orientation() const -> MirOrientation { return current_orientation; } | ||
297 | 121 | auto change_orientation(MirOrientation new_orientation) -> bool; | ||
298 | 122 | |||
299 | 117 | ~GBMBOWrapper(); | 123 | ~GBMBOWrapper(); |
300 | 118 | 124 | ||
301 | 119 | GBMBOWrapper(GBMBOWrapper&& from); | 125 | GBMBOWrapper(GBMBOWrapper&& from); |
302 | 120 | private: | 126 | private: |
303 | 121 | gbm_device* device; | 127 | gbm_device* device; |
304 | 122 | gbm_bo* buffer; | 128 | gbm_bo* buffer; |
305 | 129 | MirOrientation current_orientation; | ||
306 | 123 | GBMBOWrapper(GBMBOWrapper const&) = delete; | 130 | GBMBOWrapper(GBMBOWrapper const&) = delete; |
307 | 124 | GBMBOWrapper& operator=(GBMBOWrapper const&) = delete; | 131 | GBMBOWrapper& operator=(GBMBOWrapper const&) = delete; |
308 | 125 | }; | 132 | }; |
309 | 126 | 133 | ||
310 | === modified file 'src/platforms/mesa/server/kms/display.cpp' | |||
311 | --- src/platforms/mesa/server/kms/display.cpp 2017-06-07 08:29:04 +0000 | |||
312 | +++ src/platforms/mesa/server/kms/display.cpp 2017-07-28 15:12:01 +0000 | |||
313 | @@ -420,14 +420,20 @@ | |||
314 | 420 | bool mgm::Display::apply_if_configuration_preserves_display_buffers( | 420 | bool mgm::Display::apply_if_configuration_preserves_display_buffers( |
315 | 421 | mg::DisplayConfiguration const& conf) | 421 | mg::DisplayConfiguration const& conf) |
316 | 422 | { | 422 | { |
317 | 423 | bool result = false; | ||
318 | 423 | auto const& new_kms_conf = dynamic_cast<RealKMSDisplayConfiguration const&>(conf); | 424 | auto const& new_kms_conf = dynamic_cast<RealKMSDisplayConfiguration const&>(conf); |
321 | 424 | std::lock_guard<decltype(configuration_mutex)> lock{configuration_mutex}; | 425 | |
320 | 425 | if (compatible(current_display_configuration, new_kms_conf)) | ||
322 | 426 | { | 426 | { |
325 | 427 | configure_locked(new_kms_conf, lock); | 427 | std::lock_guard<decltype(configuration_mutex)> lock{configuration_mutex}; |
326 | 428 | return true; | 428 | if (compatible(current_display_configuration, new_kms_conf)) |
327 | 429 | { | ||
328 | 430 | configure_locked(new_kms_conf, lock); | ||
329 | 431 | result = true; | ||
330 | 432 | } | ||
331 | 429 | } | 433 | } |
333 | 430 | return false; | 434 | |
334 | 435 | if (auto c = cursor.lock()) c->resume(); | ||
335 | 436 | return result; | ||
336 | 431 | } | 437 | } |
337 | 432 | 438 | ||
338 | 433 | mg::Frame mgm::Display::last_frame_on(unsigned output_id) const | 439 | mg::Frame mgm::Display::last_frame_on(unsigned output_id) const |
339 | 434 | 440 | ||
340 | === modified file 'tests/unit-tests/platforms/mesa/kms/test_cursor.cpp' | |||
341 | --- tests/unit-tests/platforms/mesa/kms/test_cursor.cpp 2017-06-07 08:29:04 +0000 | |||
342 | +++ tests/unit-tests/platforms/mesa/kms/test_cursor.cpp 2017-07-28 15:12:01 +0000 | |||
343 | @@ -272,7 +272,9 @@ | |||
344 | 272 | 272 | ||
345 | 273 | static void const* image_data; | 273 | static void const* image_data; |
346 | 274 | }; | 274 | }; |
348 | 275 | void const* StubCursorImage::image_data = reinterpret_cast<void*>(&StubCursorImage::image_data); | 275 | |
349 | 276 | char const stub_data[128*128*4] = { 0 }; | ||
350 | 277 | void const* StubCursorImage::image_data = stub_data; | ||
351 | 276 | 278 | ||
352 | 277 | // Those new cap flags are currently only available in drm/drm.h but not in | 279 | // Those new cap flags are currently only available in drm/drm.h but not in |
353 | 278 | // libdrm/drm.h nor in xf86drm.h. Additionally drm/drm.h is current c++ unfriendly | 280 | // libdrm/drm.h nor in xf86drm.h. Additionally drm/drm.h is current c++ unfriendly |
354 | @@ -407,7 +409,7 @@ | |||
355 | 407 | geom::Size const cursor_size{cursor_side, cursor_side}; | 409 | geom::Size const cursor_size{cursor_side, cursor_side}; |
356 | 408 | size_t const cursor_size_bytes{cursor_side * cursor_side * sizeof(uint32_t)}; | 410 | size_t const cursor_size_bytes{cursor_side * cursor_side * sizeof(uint32_t)}; |
357 | 409 | 411 | ||
359 | 410 | EXPECT_CALL(mock_gbm, gbm_bo_write(mock_gbm.fake_gbm.bo, StubCursorImage::image_data, cursor_size_bytes)); | 412 | EXPECT_CALL(mock_gbm, gbm_bo_write(mock_gbm.fake_gbm.bo, NotNull(), cursor_size_bytes)); |
360 | 411 | 413 | ||
361 | 412 | cursor.show(image); | 414 | cursor.show(image); |
362 | 413 | } | 415 | } |
363 | @@ -464,7 +466,7 @@ | |||
364 | 464 | cursor_tmp.show(SinglePixelCursorImage()); | 466 | cursor_tmp.show(SinglePixelCursorImage()); |
365 | 465 | } | 467 | } |
366 | 466 | 468 | ||
368 | 467 | TEST_F(MesaCursorTest, throws_when_images_are_too_large) | 469 | TEST_F(MesaCursorTest, does_not_throw_when_images_are_too_large) |
369 | 468 | { | 470 | { |
370 | 469 | using namespace testing; | 471 | using namespace testing; |
371 | 470 | 472 | ||
372 | @@ -478,9 +480,7 @@ | |||
373 | 478 | geom::Size const large_cursor_size{cursor_side, cursor_side}; | 480 | geom::Size const large_cursor_size{cursor_side, cursor_side}; |
374 | 479 | }; | 481 | }; |
375 | 480 | 482 | ||
379 | 481 | EXPECT_THROW({ | 483 | cursor.show(LargeCursorImage()); |
377 | 482 | cursor.show(LargeCursorImage()); | ||
378 | 483 | }, std::logic_error); | ||
380 | 484 | } | 484 | } |
381 | 485 | 485 | ||
382 | 486 | TEST_F(MesaCursorTest, clears_cursor_state_on_construction) | 486 | TEST_F(MesaCursorTest, clears_cursor_state_on_construction) |
383 | @@ -607,8 +607,9 @@ | |||
384 | 607 | 607 | ||
385 | 608 | current_configuration.conf.set_orentation_of_output(mg::DisplayConfigurationOutputId{2}, mir_orientation_left); | 608 | current_configuration.conf.set_orentation_of_output(mg::DisplayConfigurationOutputId{2}, mir_orientation_left); |
386 | 609 | 609 | ||
389 | 610 | EXPECT_CALL(*output_container.outputs[2], move_cursor(geom::Point{112,100})); | 610 | InSequence seq; |
390 | 611 | EXPECT_CALL(*output_container.outputs[2], move_cursor(geom::Point{150,96})); | 611 | EXPECT_CALL(*output_container.outputs[2], move_cursor(geom::Point{112, 36})); |
391 | 612 | EXPECT_CALL(*output_container.outputs[2], move_cursor(geom::Point{150, 32})); | ||
392 | 612 | 613 | ||
393 | 613 | cursor.move_to({766, 112}); | 614 | cursor.move_to({766, 112}); |
394 | 614 | cursor.move_to({770, 150}); | 615 | cursor.move_to({770, 150}); |
395 | @@ -625,9 +626,9 @@ | |||
396 | 625 | 626 | ||
397 | 626 | current_configuration.conf.set_orentation_of_output(mg::DisplayConfigurationOutputId{2}, mir_orientation_right); | 627 | current_configuration.conf.set_orentation_of_output(mg::DisplayConfigurationOutputId{2}, mir_orientation_right); |
398 | 627 | 628 | ||
402 | 628 | 629 | InSequence seq; | |
403 | 629 | EXPECT_CALL(*output_container.outputs[2], move_cursor(geom::Point{688,100})); | 630 | EXPECT_CALL(*output_container.outputs[2], move_cursor(geom::Point{624, 100})); |
404 | 630 | EXPECT_CALL(*output_container.outputs[2], move_cursor(geom::Point{650,104})); | 631 | EXPECT_CALL(*output_container.outputs[2], move_cursor(geom::Point{586, 104})); |
405 | 631 | 632 | ||
406 | 632 | cursor.move_to({766, 112}); | 633 | cursor.move_to({766, 112}); |
407 | 633 | cursor.move_to({770, 150}); | 634 | cursor.move_to({770, 150}); |
408 | @@ -643,8 +644,9 @@ | |||
409 | 643 | 644 | ||
410 | 644 | current_configuration.conf.set_orentation_of_output(mg::DisplayConfigurationOutputId{2}, mir_orientation_inverted); | 645 | current_configuration.conf.set_orentation_of_output(mg::DisplayConfigurationOutputId{2}, mir_orientation_inverted); |
411 | 645 | 646 | ||
414 | 646 | EXPECT_CALL(*output_container.outputs[2], move_cursor(geom::Point{700,88})); | 647 | InSequence seq; |
415 | 647 | EXPECT_CALL(*output_container.outputs[2], move_cursor(geom::Point{696,50})); | 648 | EXPECT_CALL(*output_container.outputs[2], move_cursor(geom::Point{636, 24})); |
416 | 649 | EXPECT_CALL(*output_container.outputs[2], move_cursor(geom::Point{632,-14})); | ||
417 | 648 | 650 | ||
418 | 649 | cursor.move_to({766, 112}); | 651 | cursor.move_to({766, 112}); |
419 | 650 | cursor.move_to({770, 150}); | 652 | cursor.move_to({770, 150}); |
FAILED: Continuous integration, rev:4219 /mir-jenkins. ubuntu. com/job/ mir-ci/ 3513/ /mir-jenkins. ubuntu. com/job/ build-mir/ 4808/console /mir-jenkins. ubuntu. com/job/ build-0- fetch/4996 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= artful/ 4985 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= xenial/ 4985 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= zesty/4985 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= clang,platform= mesa,release= artful/ 4845/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= clang,platform= mesa,release= zesty/4845/ console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= artful/ 4845/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= xenial/ 4845/console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= zesty/4845/ console /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= mesa,release= artful/ 4845 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= mesa,release= artful/ 4845/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= mesa,release= zesty/4845 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= mesa,release= zesty/4845/ artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= mesa,release= xenial/ 4845/console
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Click here to trigger a rebuild: /mir-jenkins. ubuntu. com/job/ mir-ci/ 3513/rebuild
https:/