Mir

Merge lp:~alan-griffiths/mir/fix-1706718 into lp:mir

Proposed by Alan Griffiths
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
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.

To post a comment you must log in.
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:4219
https://mir-jenkins.ubuntu.com/job/mir-ci/3513/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/4808/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4996
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/4985
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/4985
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4985
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4845/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4845/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4845/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4845/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4845/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4845
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4845/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4845
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4845/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4845/console

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

Guess who forgot to run the tests. :(

Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:4221
https://mir-jenkins.ubuntu.com/job/mir-ci/3514/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/4809/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4997
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/4986
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/4986
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4986
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4846/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4846/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4846/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4846/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4846/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4846
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4846/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4846
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4846/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4846/console

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:4223
https://mir-jenkins.ubuntu.com/job/mir-ci/3515/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/4810/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4998
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/4987
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/4987
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4987
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4847/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4847/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4847/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4847/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4847/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4847
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4847/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4847
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4847/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4847/console

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

PASSED: Continuous integration, rev:4224
https://mir-jenkins.ubuntu.com/job/mir-ci/3516/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/4811
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/5000
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/4989
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/4989
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4989
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4848
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4848/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4848
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4848/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4848
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4848/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4848
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4848/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4848
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4848/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4848
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4848/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4848
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4848/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4848
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4848/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
Revision history for this message
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_client_displayconfiguration

review: Needs Fixing
Revision history for this message
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_client_displayconfiguration

Fixed

Revision history for this message
Gerry Boland (gerboland) wrote :

LGTM

Though the --x-cursor-theme arg doesn't seem to be doing anything when I try it..

review: Approve
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

PASSED: Continuous integration, rev:4225
https://mir-jenkins.ubuntu.com/job/mir-ci/3517/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/4812
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/5010
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/4999
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/4999
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4999
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4849
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4849/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4849
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4849/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4849
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4849/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4849
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4849/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4849
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4849/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4849
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4849/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4849
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4849/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4849
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4849/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/platforms/mesa/server/kms/cursor.cpp'
--- src/platforms/mesa/server/kms/cursor.cpp 2017-07-20 14:11:27 +0000
+++ src/platforms/mesa/server/kms/cursor.cpp 2017-07-28 15:12:01 +0000
@@ -100,7 +100,7 @@
100}100}
101}101}
102102
103mgm::Cursor::GBMBOWrapper::GBMBOWrapper(int fd) :103mgm::Cursor::GBMBOWrapper::GBMBOWrapper(int fd, MirOrientation orientation) :
104 device{gbm_create_device_checked(fd)},104 device{gbm_create_device_checked(fd)},
105 buffer{105 buffer{
106 gbm_bo_create(106 gbm_bo_create(
@@ -108,7 +108,8 @@
108 get_drm_cursor_width(fd),108 get_drm_cursor_width(fd),
109 get_drm_cursor_height(fd),109 get_drm_cursor_height(fd),
110 GBM_FORMAT_ARGB8888,110 GBM_FORMAT_ARGB8888,
111 GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE)}111 GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE)},
112 current_orientation{orientation}
112{113{
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"));
114}115}
@@ -128,12 +129,22 @@
128129
129mgm::Cursor::GBMBOWrapper::GBMBOWrapper(GBMBOWrapper&& from)130mgm::Cursor::GBMBOWrapper::GBMBOWrapper(GBMBOWrapper&& from)
130 : device{from.device},131 : device{from.device},
131 buffer{from.buffer}132 buffer{from.buffer},
133 current_orientation{from.current_orientation}
132{134{
133 from.buffer = nullptr;135 from.buffer = nullptr;
134 from.device = nullptr;136 from.device = nullptr;
135}137}
136138
139auto mir::graphics::mesa::Cursor::GBMBOWrapper::change_orientation(MirOrientation new_orientation) -> bool
140{
141 if (current_orientation == new_orientation)
142 return false;
143
144 current_orientation = new_orientation;
145 return true;
146}
147
137mgm::Cursor::Cursor(148mgm::Cursor::Cursor(
138 KMSOutputContainer& output_container,149 KMSOutputContainer& output_container,
139 std::shared_ptr<CurrentConfiguration> const& current_configuration) :150 std::shared_ptr<CurrentConfiguration> const& current_configuration) :
@@ -182,37 +193,86 @@
182193
183void mgm::Cursor::pad_and_write_image_data_locked(194void mgm::Cursor::pad_and_write_image_data_locked(
184 std::lock_guard<std::mutex> const& lg,195 std::lock_guard<std::mutex> const& lg,
185 gbm_bo* buffer,196 GBMBOWrapper& buffer)
186 CursorImage const& image)
187{197{
188 auto image_argb = static_cast<uint8_t const*>(image.as_argb_8888());198 auto const orientation = buffer.orientation();
189 auto image_width = image.size().width.as_uint32_t();199 bool const sideways = orientation == mir_orientation_left || orientation == mir_orientation_right;
190 auto image_height = image.size().height.as_uint32_t();200
191 auto image_stride = image_width * 4;201 auto const min_width = sideways ? min_buffer_width : min_buffer_height;
192202 auto const min_height = sideways ? min_buffer_height : min_buffer_width;
193 if (image_width > min_buffer_width || image_height > min_buffer_height)203
194 {204 auto const image_width = std::min(min_width, size.width.as_uint32_t());
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());
196 }206 auto const image_stride = size.width.as_uint32_t() * 4;
197207
198 size_t buffer_stride = gbm_bo_get_stride(buffer); // in bytes208 auto const buffer_stride = std::max(min_width*4, gbm_bo_get_stride(buffer)); // in bytes
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));
210 size_t const padded_size = buffer_stride * buffer_height;
211
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]);
201 size_t rhs_padding = buffer_stride - image_stride;213 size_t rhs_padding = buffer_stride - 4*image_width;
202214
215 auto const filler = 0; // 0x3f; is useful to make buffer visible for debugging
216 uint8_t const* src = argb8888.data();
203 uint8_t* dest = &padded[0];217 uint8_t* dest = &padded[0];
204 uint8_t const* src = image_argb;
205218
206 for (unsigned int y = 0; y < image_height; y++)219 switch (orientation)
207 {220 {
208 memcpy(dest, src, image_stride);221 case mir_orientation_normal:
209 memset(dest + image_stride, 0, rhs_padding);222 for (unsigned int y = 0; y < image_height; y++)
210 dest += buffer_stride;223 {
211 src += image_stride;224 memcpy(dest, src, 4*image_width);
225 memset(dest + 4*image_width, filler, rhs_padding);
226 dest += buffer_stride;
227 src += image_stride;
228 }
229
230 memset(dest, 0, buffer_stride * (buffer_height - image_height));
231 break;
232
233 case mir_orientation_inverted:
234 for (unsigned int row = 0; row != image_height; ++row)
235 {
236 memset(dest+row*buffer_stride+4*image_width, filler, rhs_padding);
237
238 for (unsigned int col = 0; col != image_width; ++col)
239 {
240 memcpy(dest+row*buffer_stride+4*col, src + ((image_height-1)-row)*image_stride + 4*((image_width-1)-col), 4);
241 }
242 }
243
244 memset(dest+image_height*buffer_stride, filler, buffer_stride * (buffer_height - image_height));
245 break;
246
247 case mir_orientation_left:
248 for (unsigned int row = 0; row != image_width; ++row)
249 {
250 memset(dest+row*buffer_stride+4*image_height, filler, rhs_padding);
251
252 for (unsigned int col = 0; col != image_height; ++col)
253 {
254 memcpy(dest+row*buffer_stride+4*col, src + ((image_width-1)-row)*4 + image_stride*col, 4);
255 }
256 }
257
258 memset(dest+image_width*buffer_stride, filler, buffer_stride * (buffer_height - image_width));
259 break;
260
261 case mir_orientation_right:
262 for (unsigned int row = 0; row != image_width; ++row)
263 {
264 memset(dest+row*buffer_stride+4*image_height, filler, rhs_padding);
265
266 for (unsigned int col = 0; col != image_height; ++col)
267 {
268 memcpy(dest+row*buffer_stride+4*col, src + row*4 + image_stride*((image_height-1)-col), 4);
269 }
270 }
271
272 memset(dest+image_width*buffer_stride, filler, buffer_stride * (buffer_height - image_width));
273 break;
212 }274 }
213275
214 memset(dest, 0, buffer_stride * (gbm_bo_get_height(buffer) - image_height));
215
216 write_buffer_data_locked(lg, buffer, &padded[0], padded_size);276 write_buffer_data_locked(lg, buffer, &padded[0], padded_size);
217}277}
218278
@@ -231,23 +291,17 @@
231{291{
232 std::lock_guard<std::mutex> lg(guard);292 std::lock_guard<std::mutex> lg(guard);
233293
234 auto const& size = cursor_image.size();294 size = cursor_image.size();
295
296 argb8888.resize(size.width.as_uint32_t() * size.height.as_uint32_t() * 4);
297 memcpy(argb8888.data(), cursor_image.as_argb_8888(), argb8888.size());
235298
236 hotspot = cursor_image.hotspot();299 hotspot = cursor_image.hotspot();
237 {300 {
238 auto locked_buffers = buffers.lock();301 auto locked_buffers = buffers.lock();
239 for (auto& pair : *locked_buffers)302 for (auto& pair : *locked_buffers)
240 {303 {
241 auto& buffer = pair.second;304 pad_and_write_image_data_locked(lg, pair.second);
242 if (size != geometry::Size{gbm_bo_get_width(buffer), gbm_bo_get_height(buffer)})
243 {
244 pad_and_write_image_data_locked(lg, buffer, cursor_image);
245 }
246 else
247 {
248 auto const count = size.width.as_uint32_t() * size.height.as_uint32_t() * sizeof(uint32_t);
249 write_buffer_data_locked(lg, buffer, cursor_image.as_argb_8888(), count);
250 }
251 }305 }
252 }306 }
253307
@@ -317,7 +371,7 @@
317}371}
318372
319void mgm::Cursor::place_cursor_at_locked(373void mgm::Cursor::place_cursor_at_locked(
320 std::lock_guard<std::mutex> const&,374 std::lock_guard<std::mutex> const& lg,
321 geometry::Point position,375 geometry::Point position,
322 ForceCursorState force_state)376 ForceCursorState force_state)
323{377{
@@ -334,15 +388,23 @@
334 if (output_rect.contains(position))388 if (output_rect.contains(position))
335 {389 {
336 auto dp = transform(output_rect, position - output_rect.top_left, orientation);390 auto dp = transform(output_rect, position - output_rect.top_left, orientation);
391 auto hs = transform(geom::Rectangle{{0,0}, size}, hotspot, orientation);
337392
338 // It's a little strange that we implement hotspot this way as there is393 // It's a little strange that we implement hotspot this way as there is
339 // drmModeSetCursor2 with hotspot support. However it appears to not actually394 // drmModeSetCursor2 with hotspot support. However it appears to not actually
340 // work on radeon and intel. There also seems to be precedent in weston for395 // work on radeon and intel. There also seems to be precedent in weston for
341 // implementing hotspot in this fashion.396 // implementing hotspot in this fashion.
342 output.move_cursor(geom::Point{} + dp - hotspot);397 output.move_cursor(geom::Point{} + dp - hs);
343 if (force_state || !output.has_cursor()) // TODO - or if orientation had changed - then set buffer..398 auto& buffer = buffer_for_output(output);
399
400 auto const changed_orientation = buffer.change_orientation(orientation);
401
402 if (changed_orientation)
403 pad_and_write_image_data_locked(lg, buffer);
404
405 if (force_state || !output.has_cursor() || changed_orientation)
344 {406 {
345 if (!output.set_cursor(buffer_for_output(output)) || !output.has_cursor())407 if (!output.set_cursor(buffer) || !output.has_cursor())
346 set_on_all_outputs = false;408 set_on_all_outputs = false;
347 }409 }
348 }410 }
@@ -358,7 +420,7 @@
358 last_set_failed = !set_on_all_outputs;420 last_set_failed = !set_on_all_outputs;
359}421}
360422
361gbm_bo* mgm::Cursor::buffer_for_output(KMSOutput const& output)423mgm::Cursor::GBMBOWrapper& mgm::Cursor::buffer_for_output(KMSOutput const& output)
362{424{
363 auto locked_buffers = buffers.lock();425 auto locked_buffers = buffers.lock();
364426
@@ -366,18 +428,18 @@
366 locked_buffers->begin(),428 locked_buffers->begin(),
367 locked_buffers->end(),429 locked_buffers->end(),
368 [&output](auto const& candidate)430 [&output](auto const& candidate)
369 {431 {
370 return candidate.first == output.drm_fd();432 return candidate.first == output.drm_fd();
371 });433 });
372434
373 if (buffer_it != locked_buffers->end())435 if (buffer_it != locked_buffers->end())
374 {436 {
375 return buffer_it->second;437 return buffer_it->second;
376 }438 }
377439
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)));
379441
380 gbm_bo* bo = locked_buffers->back().second;442 GBMBOWrapper& bo = locked_buffers->back().second;
381 if (gbm_bo_get_width(bo) < min_buffer_width)443 if (gbm_bo_get_width(bo) < min_buffer_width)
382 {444 {
383 min_buffer_width = gbm_bo_get_width(bo);445 min_buffer_width = gbm_bo_get_width(bo);
384446
=== modified file 'src/platforms/mesa/server/kms/cursor.h'
--- src/platforms/mesa/server/kms/cursor.h 2017-06-08 08:34:56 +0000
+++ src/platforms/mesa/server/kms/cursor.h 2017-07-28 15:12:01 +0000
@@ -85,6 +85,7 @@
8585
86private:86private:
87 enum ForceCursorState { UpdateState, ForceState };87 enum ForceCursorState { UpdateState, ForceState };
88 struct GBMBOWrapper;
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);
89 void place_cursor_at(geometry::Point position, ForceCursorState force_state);90 void place_cursor_at(geometry::Point position, ForceCursorState force_state);
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);
@@ -95,31 +96,37 @@
95 size_t count);96 size_t count);
96 void pad_and_write_image_data_locked(97 void pad_and_write_image_data_locked(
97 std::lock_guard<std::mutex> const&,98 std::lock_guard<std::mutex> const&,
98 gbm_bo* buffer,99 GBMBOWrapper& buffer);
99 CursorImage const& image);
100 void clear(std::lock_guard<std::mutex> const&);100 void clear(std::lock_guard<std::mutex> const&);
101101
102 gbm_bo* buffer_for_output(KMSOutput const& output);102 GBMBOWrapper& buffer_for_output(KMSOutput const& output);
103 103
104 std::mutex guard;104 std::mutex guard;
105105
106 KMSOutputContainer& output_container;106 KMSOutputContainer& output_container;
107 geometry::Point current_position;107 geometry::Point current_position;
108 geometry::Displacement hotspot;108 geometry::Displacement hotspot;
109 geometry::Size size;
110 std::vector<uint8_t> argb8888;
109111
110 bool visible;112 bool visible;
111 bool last_set_failed;113 bool last_set_failed;
112114
113 struct GBMBOWrapper115 struct GBMBOWrapper
114 {116 {
115 GBMBOWrapper(int fd);117 GBMBOWrapper(int fd, MirOrientation orientation);
116 operator gbm_bo*();118 operator gbm_bo*();
119
120 auto orientation() const -> MirOrientation { return current_orientation; }
121 auto change_orientation(MirOrientation new_orientation) -> bool;
122
117 ~GBMBOWrapper();123 ~GBMBOWrapper();
118124
119 GBMBOWrapper(GBMBOWrapper&& from);125 GBMBOWrapper(GBMBOWrapper&& from);
120 private:126 private:
121 gbm_device* device;127 gbm_device* device;
122 gbm_bo* buffer;128 gbm_bo* buffer;
129 MirOrientation current_orientation;
123 GBMBOWrapper(GBMBOWrapper const&) = delete;130 GBMBOWrapper(GBMBOWrapper const&) = delete;
124 GBMBOWrapper& operator=(GBMBOWrapper const&) = delete;131 GBMBOWrapper& operator=(GBMBOWrapper const&) = delete;
125 };132 };
126133
=== modified file 'src/platforms/mesa/server/kms/display.cpp'
--- src/platforms/mesa/server/kms/display.cpp 2017-06-07 08:29:04 +0000
+++ src/platforms/mesa/server/kms/display.cpp 2017-07-28 15:12:01 +0000
@@ -420,14 +420,20 @@
420bool mgm::Display::apply_if_configuration_preserves_display_buffers(420bool mgm::Display::apply_if_configuration_preserves_display_buffers(
421 mg::DisplayConfiguration const& conf)421 mg::DisplayConfiguration const& conf)
422{422{
423 bool result = false;
423 auto const& new_kms_conf = dynamic_cast<RealKMSDisplayConfiguration const&>(conf);424 auto const& new_kms_conf = dynamic_cast<RealKMSDisplayConfiguration const&>(conf);
424 std::lock_guard<decltype(configuration_mutex)> lock{configuration_mutex};425
425 if (compatible(current_display_configuration, new_kms_conf))
426 {426 {
427 configure_locked(new_kms_conf, lock);427 std::lock_guard<decltype(configuration_mutex)> lock{configuration_mutex};
428 return true;428 if (compatible(current_display_configuration, new_kms_conf))
429 {
430 configure_locked(new_kms_conf, lock);
431 result = true;
432 }
429 }433 }
430 return false;434
435 if (auto c = cursor.lock()) c->resume();
436 return result;
431}437}
432438
433mg::Frame mgm::Display::last_frame_on(unsigned output_id) const439mg::Frame mgm::Display::last_frame_on(unsigned output_id) const
434440
=== modified file 'tests/unit-tests/platforms/mesa/kms/test_cursor.cpp'
--- tests/unit-tests/platforms/mesa/kms/test_cursor.cpp 2017-06-07 08:29:04 +0000
+++ tests/unit-tests/platforms/mesa/kms/test_cursor.cpp 2017-07-28 15:12:01 +0000
@@ -272,7 +272,9 @@
272272
273 static void const* image_data;273 static void const* image_data;
274};274};
275void const* StubCursorImage::image_data = reinterpret_cast<void*>(&StubCursorImage::image_data);275
276char const stub_data[128*128*4] = { 0 };
277void const* StubCursorImage::image_data = stub_data;
276278
277// Those new cap flags are currently only available in drm/drm.h but not in279// Those new cap flags are currently only available in drm/drm.h but not in
278// libdrm/drm.h nor in xf86drm.h. Additionally drm/drm.h is current c++ unfriendly280// libdrm/drm.h nor in xf86drm.h. Additionally drm/drm.h is current c++ unfriendly
@@ -407,7 +409,7 @@
407 geom::Size const cursor_size{cursor_side, cursor_side};409 geom::Size const cursor_size{cursor_side, cursor_side};
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)};
409411
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));
411413
412 cursor.show(image);414 cursor.show(image);
413}415}
@@ -464,7 +466,7 @@
464 cursor_tmp.show(SinglePixelCursorImage());466 cursor_tmp.show(SinglePixelCursorImage());
465}467}
466468
467TEST_F(MesaCursorTest, throws_when_images_are_too_large)469TEST_F(MesaCursorTest, does_not_throw_when_images_are_too_large)
468{470{
469 using namespace testing;471 using namespace testing;
470472
@@ -478,9 +480,7 @@
478 geom::Size const large_cursor_size{cursor_side, cursor_side};480 geom::Size const large_cursor_size{cursor_side, cursor_side};
479 };481 };
480482
481 EXPECT_THROW({483 cursor.show(LargeCursorImage());
482 cursor.show(LargeCursorImage());
483 }, std::logic_error);
484}484}
485485
486TEST_F(MesaCursorTest, clears_cursor_state_on_construction)486TEST_F(MesaCursorTest, clears_cursor_state_on_construction)
@@ -607,8 +607,9 @@
607607
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);
609609
610 EXPECT_CALL(*output_container.outputs[2], move_cursor(geom::Point{112,100}));610 InSequence seq;
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}));
612 EXPECT_CALL(*output_container.outputs[2], move_cursor(geom::Point{150, 32}));
612613
613 cursor.move_to({766, 112});614 cursor.move_to({766, 112});
614 cursor.move_to({770, 150});615 cursor.move_to({770, 150});
@@ -625,9 +626,9 @@
625626
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);
627628
628629 InSequence seq;
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}));
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}));
631632
632 cursor.move_to({766, 112});633 cursor.move_to({766, 112});
633 cursor.move_to({770, 150});634 cursor.move_to({770, 150});
@@ -643,8 +644,9 @@
643644
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);
645646
646 EXPECT_CALL(*output_container.outputs[2], move_cursor(geom::Point{700,88}));647 InSequence seq;
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}));
649 EXPECT_CALL(*output_container.outputs[2], move_cursor(geom::Point{632,-14}));
648650
649 cursor.move_to({766, 112});651 cursor.move_to({766, 112});
650 cursor.move_to({770, 150});652 cursor.move_to({770, 150});

Subscribers

People subscribed via source and target branches