Mir

Merge lp:~raof/mir/mesa-hybrid-cursor into lp:mir

Proposed by Chris Halse Rogers
Status: Superseded
Proposed branch: lp:~raof/mir/mesa-hybrid-cursor
Merge into: lp:mir
Prerequisite: lp:~raof/mir/mesa-hybrid-output
Diff against target: 544 lines (+257/-63)
7 files modified
src/common/CMakeLists.txt (+2/-1)
src/platforms/mesa/server/kms/CMakeLists.txt (+1/-0)
src/platforms/mesa/server/kms/cursor.cpp (+114/-30)
src/platforms/mesa/server/kms/cursor.h (+22/-8)
src/platforms/mesa/server/kms/display.cpp (+3/-14)
src/platforms/mesa/server/kms/mutex.h (+104/-0)
tests/unit-tests/platforms/mesa/kms/test_cursor.cpp (+11/-10)
To merge this branch: bzr merge lp:~raof/mir/mesa-hybrid-cursor
Reviewer Review Type Date Requested Status
Mir CI Bot continuous-integration Needs Fixing
Alan Griffiths Needs Information
Review via email: mp+320592@code.launchpad.net

This proposal has been superseded by a proposal from 2017-06-07.

Commit message

mesa-kms: Support hardware cursors in hybrid setups.

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

FAILED: Continuous integration, rev:4086
https://mir-jenkins.ubuntu.com/job/mir-ci/3208/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/4317/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4404/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/4394/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/4394/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4394/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4349/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/4349/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4349/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/4349/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/4349/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/4349/console

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

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

FAILED: Continuous integration, rev:4087
https://mir-jenkins.ubuntu.com/job/mir-ci/3218/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/4331/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4418
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/4408
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/4408
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4408
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4363
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4363/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/4363/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4363/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/4363/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/4363/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/4363/console

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

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

FAILED: Continuous integration, rev:4087
https://mir-jenkins.ubuntu.com/job/mir-ci/3247/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/4371/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4458
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/4448
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/4448
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4448
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4403
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4403/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/4403/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4403/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/4403/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/4403/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/4403/console

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

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

FAILED: Continuous integration, rev:4088
https://mir-jenkins.ubuntu.com/job/mir-ci/3273/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/4413/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4505
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/4495
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/4495
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4495
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4445
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4445/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/4445/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4445/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/4445/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/4445/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/4445/console

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

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

FAILED: Continuous integration, rev:4088
https://mir-jenkins.ubuntu.com/job/mir-ci/3350/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/4524/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4642
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/4631
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/4631
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/4631
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4631
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4555
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4555/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/4555/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4555/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/4555/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/4555/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/4555/console

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

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

It isn't clear why this failed CI (and too much time has passed to see any logs).

It still merges and doesn't obviously break things - so is it still worth landing?

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

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

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Chris Halse Rogers (raof) wrote :

It's still worth merging. Once it builds, it seems!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/common/CMakeLists.txt'
2--- src/common/CMakeLists.txt 2017-02-15 14:45:41 +0000
3+++ src/common/CMakeLists.txt 2017-03-29 05:01:14 +0000
4@@ -20,7 +20,8 @@
5 $<TARGET_OBJECTS:mirtime>
6 ${CMAKE_CURRENT_SOURCE_DIR}/output_type_names.cpp
7 ${CMAKE_CURRENT_SOURCE_DIR}/log.cpp
8- ${CMAKE_CURRENT_SOURCE_DIR}/libname.cpp ${PROJECT_SOURCE_DIR}/include/common/mir/libname.h
9+ ${CMAKE_CURRENT_SOURCE_DIR}/libname.cpp
10+ ${PROJECT_SOURCE_DIR}/include/common/mir/libname.h
11 ${PROJECT_SOURCE_DIR}/include/common/mir/posix_rw_mutex.h
12 posix_rw_mutex.cpp
13 edid.cpp
14
15=== modified file 'src/platforms/mesa/server/kms/CMakeLists.txt'
16--- src/platforms/mesa/server/kms/CMakeLists.txt 2017-03-29 05:01:13 +0000
17+++ src/platforms/mesa/server/kms/CMakeLists.txt 2017-03-29 05:01:14 +0000
18@@ -44,6 +44,7 @@
19 real_kms_output_container.cpp
20 egl_helper.h
21 egl_helper.cpp
22+ mutex.h
23 )
24
25 configure_file(${CMAKE_CURRENT_SOURCE_DIR}/symbols.map.in
26
27=== modified file 'src/platforms/mesa/server/kms/cursor.cpp'
28--- src/platforms/mesa/server/kms/cursor.cpp 2017-03-10 10:20:24 +0000
29+++ src/platforms/mesa/server/kms/cursor.cpp 2017-03-29 05:01:14 +0000
30@@ -88,34 +88,73 @@
31 drmGetCap(fd, DRM_CAP_CURSOR_WIDTH, &width);
32 return int(width);
33 }
34-}
35-
36-mgm::Cursor::GBMBOWrapper::GBMBOWrapper(gbm_device* gbm) :
37- buffer(gbm_bo_create(
38- gbm,
39- get_drm_cursor_width(gbm_device_get_fd(gbm)),
40- get_drm_cursor_height(gbm_device_get_fd(gbm)),
41- GBM_FORMAT_ARGB8888,
42- GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE))
43+
44+gbm_device* gbm_create_device_checked(int fd)
45+{
46+ auto device = gbm_create_device(fd);
47+ if (!device)
48+ {
49+ BOOST_THROW_EXCEPTION(std::runtime_error("Failed to create gbm device"));
50+ }
51+ return device;
52+}
53+}
54+
55+mgm::Cursor::GBMBOWrapper::GBMBOWrapper(int fd) :
56+ device{gbm_create_device_checked(fd)},
57+ buffer{
58+ gbm_bo_create(
59+ device,
60+ get_drm_cursor_width(fd),
61+ get_drm_cursor_height(fd),
62+ GBM_FORMAT_ARGB8888,
63+ GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE)}
64 {
65 if (!buffer) BOOST_THROW_EXCEPTION(std::runtime_error("failed to create gbm buffer"));
66 }
67
68-inline mgm::Cursor::GBMBOWrapper::operator gbm_bo*() { return buffer; }
69-inline mgm::Cursor::GBMBOWrapper::~GBMBOWrapper() { gbm_bo_destroy(buffer); }
70+inline mgm::Cursor::GBMBOWrapper::operator gbm_bo*()
71+{
72+ return buffer;
73+}
74+
75+inline mgm::Cursor::GBMBOWrapper::~GBMBOWrapper()
76+{
77+ if (device)
78+ gbm_device_destroy(device);
79+ if (buffer)
80+ gbm_bo_destroy(buffer);
81+}
82+
83+mgm::Cursor::GBMBOWrapper::GBMBOWrapper(GBMBOWrapper&& from)
84+ : device{from.device},
85+ buffer{from.buffer}
86+{
87+ const_cast<gbm_bo*&>(from.buffer) = nullptr;
88+ const_cast<gbm_device*&>(from.device) = nullptr;
89+}
90
91 mgm::Cursor::Cursor(
92- gbm_device* gbm,
93 KMSOutputContainer& output_container,
94 std::shared_ptr<CurrentConfiguration> const& current_configuration) :
95 output_container(output_container),
96 current_position(),
97 last_set_failed(false),
98- buffer(gbm),
99- buffer_width(gbm_bo_get_width(buffer)),
100- buffer_height(gbm_bo_get_height(buffer)),
101+ min_buffer_width{std::numeric_limits<uint32_t>::max()},
102+ min_buffer_height{std::numeric_limits<uint32_t>::max()},
103 current_configuration(current_configuration)
104 {
105+ // Generate the buffers for the initial configuration.
106+ current_configuration->with_current_configuration_do(
107+ [this](KMSDisplayConfiguration const& kms_conf)
108+ {
109+ kms_conf.for_each_output(
110+ [this, &kms_conf](auto const& output)
111+ {
112+ buffer_for_output(*kms_conf.get_output_for(output.id));
113+ });
114+ });
115+
116 hide();
117 if (last_set_failed)
118 throw std::runtime_error("Initial KMS cursor set failed");
119@@ -126,7 +165,11 @@
120 hide();
121 }
122
123-void mgm::Cursor::write_buffer_data_locked(std::lock_guard<std::mutex> const&, void const* data, size_t count)
124+void mgm::Cursor::write_buffer_data_locked(
125+ std::lock_guard<std::mutex> const&,
126+ gbm_bo* buffer,
127+ void const* data,
128+ size_t count)
129 {
130 if (auto result = gbm_bo_write(buffer, data, count))
131 {
132@@ -136,20 +179,23 @@
133 }
134 }
135
136-void mgm::Cursor::pad_and_write_image_data_locked(std::lock_guard<std::mutex> const& lg, CursorImage const& image)
137+void mgm::Cursor::pad_and_write_image_data_locked(
138+ std::lock_guard<std::mutex> const& lg,
139+ gbm_bo* buffer,
140+ CursorImage const& image)
141 {
142 auto image_argb = static_cast<uint8_t const*>(image.as_argb_8888());
143 auto image_width = image.size().width.as_uint32_t();
144 auto image_height = image.size().height.as_uint32_t();
145 auto image_stride = image_width * 4;
146
147- if (image_width > buffer_width || image_height > buffer_height)
148+ if (image_width > min_buffer_width || image_height > min_buffer_height)
149 {
150 BOOST_THROW_EXCEPTION(std::logic_error("Image is too big for GBM cursor buffer"));
151 }
152
153 size_t buffer_stride = gbm_bo_get_stride(buffer); // in bytes
154- size_t padded_size = buffer_stride * buffer_height;
155+ size_t padded_size = buffer_stride * gbm_bo_get_height(buffer);
156 auto padded = std::unique_ptr<uint8_t[]>(new uint8_t[padded_size]);
157 size_t rhs_padding = buffer_stride - image_stride;
158
159@@ -164,9 +210,9 @@
160 src += image_stride;
161 }
162
163- memset(dest, 0, buffer_stride * (buffer_height - image_height));
164+ memset(dest, 0, buffer_stride * (gbm_bo_get_height(buffer) - image_height));
165
166- write_buffer_data_locked(lg, &padded[0], padded_size);
167+ write_buffer_data_locked(lg, buffer, &padded[0], padded_size);
168 }
169
170 void mgm::Cursor::show()
171@@ -186,14 +232,20 @@
172
173 auto const& size = cursor_image.size();
174
175- if (size != geometry::Size{buffer_width, buffer_height})
176- {
177- pad_and_write_image_data_locked(lg, cursor_image);
178- }
179- else
180- {
181- auto const count = size.width.as_uint32_t() * size.height.as_uint32_t() * sizeof(uint32_t);
182- write_buffer_data_locked(lg, cursor_image.as_argb_8888(), count);
183+ {
184+ auto locked_buffers = buffers.lock();
185+ for (auto& pair : *locked_buffers)
186+ {
187+ auto& buffer = pair.second;
188+ if (size != geometry::Size{gbm_bo_get_width(buffer), gbm_bo_get_height(buffer)})
189+ {
190+ pad_and_write_image_data_locked(lg, buffer, cursor_image);
191+ } else
192+ {
193+ auto const count = size.width.as_uint32_t() * size.height.as_uint32_t() * sizeof(uint32_t);
194+ write_buffer_data_locked(lg, buffer, cursor_image.as_argb_8888(), count);
195+ }
196+ }
197 }
198 hotspot = cursor_image.hotspot();
199
200@@ -288,7 +340,7 @@
201 output.move_cursor(geom::Point{} + dp - hotspot);
202 if (force_state || !output.has_cursor()) // TODO - or if orientation had changed - then set buffer..
203 {
204- if (!output.set_cursor(buffer) || !output.has_cursor())
205+ if (!output.set_cursor(buffer_for_output(output)) || !output.has_cursor())
206 set_on_all_outputs = false;
207 }
208 }
209@@ -303,3 +355,35 @@
210
211 last_set_failed = !set_on_all_outputs;
212 }
213+
214+gbm_bo* mgm::Cursor::buffer_for_output(KMSOutput const& output)
215+{
216+ auto locked_buffers = buffers.lock();
217+
218+ auto buffer_it = std::find_if(
219+ locked_buffers->begin(),
220+ locked_buffers->end(),
221+ [&output](auto const& candidate)
222+ {
223+ return candidate.first == output.drm_fd();
224+ });
225+
226+ if (buffer_it != locked_buffers->end())
227+ {
228+ return buffer_it->second;
229+ }
230+
231+ locked_buffers->push_back(std::make_pair(output.drm_fd(), GBMBOWrapper(output.drm_fd())));
232+
233+ gbm_bo* bo = locked_buffers->back().second;
234+ if (gbm_bo_get_width(bo) < min_buffer_width)
235+ {
236+ min_buffer_width = gbm_bo_get_width(bo);
237+ }
238+ if (gbm_bo_get_height(bo) < min_buffer_height)
239+ {
240+ min_buffer_height = gbm_bo_get_height(bo);
241+ }
242+
243+ return bo;
244+}
245
246=== modified file 'src/platforms/mesa/server/kms/cursor.h'
247--- src/platforms/mesa/server/kms/cursor.h 2017-02-15 07:38:33 +0000
248+++ src/platforms/mesa/server/kms/cursor.h 2017-03-29 05:01:14 +0000
249@@ -25,11 +25,13 @@
250 #include "mir/geometry/displacement.h"
251
252 #include "mir_toolkit/common.h"
253+#include "mutex.h"
254
255 #include <gbm.h>
256
257 #include <memory>
258 #include <mutex>
259+#include <vector>
260
261 namespace mir
262 {
263@@ -66,7 +68,6 @@
264 {
265 public:
266 Cursor(
267- gbm_device* device,
268 KMSOutputContainer& output_container,
269 std::shared_ptr<CurrentConfiguration> const& current_configuration);
270
271@@ -86,9 +87,18 @@
272 void for_each_used_output(std::function<void(KMSOutput&, geometry::Rectangle const&, MirOrientation orientation)> const& f);
273 void place_cursor_at(geometry::Point position, ForceCursorState force_state);
274 void place_cursor_at_locked(std::lock_guard<std::mutex> const&, geometry::Point position, ForceCursorState force_state);
275- void write_buffer_data_locked(std::lock_guard<std::mutex> const&, void const* data, size_t count);
276- void pad_and_write_image_data_locked(std::lock_guard<std::mutex> const&, CursorImage const& image);
277+ void write_buffer_data_locked(
278+ std::lock_guard<std::mutex> const&,
279+ gbm_bo* buffer,
280+ void const* data,
281+ size_t count);
282+ void pad_and_write_image_data_locked(
283+ std::lock_guard<std::mutex> const&,
284+ gbm_bo* buffer,
285+ CursorImage const& image);
286 void clear(std::lock_guard<std::mutex> const&);
287+
288+ gbm_bo* buffer_for_output(KMSOutput const& output);
289
290 std::mutex guard;
291
292@@ -101,17 +111,21 @@
293
294 struct GBMBOWrapper
295 {
296- GBMBOWrapper(gbm_device* gbm);
297+ GBMBOWrapper(int fd);
298 operator gbm_bo*();
299 ~GBMBOWrapper();
300+
301+ GBMBOWrapper(GBMBOWrapper&& from);
302 private:
303- gbm_bo* buffer;
304+ gbm_device* const device;
305+ gbm_bo* const buffer;
306 GBMBOWrapper(GBMBOWrapper const&) = delete;
307 GBMBOWrapper& operator=(GBMBOWrapper const&) = delete;
308- } buffer;
309+ };
310+ Mutex<std::vector<std::pair<int, GBMBOWrapper>>> buffers;
311
312- uint32_t buffer_width;
313- uint32_t buffer_height;
314+ uint32_t min_buffer_width;
315+ uint32_t min_buffer_height;
316
317 std::shared_ptr<CurrentConfiguration> const current_configuration;
318 };
319
320=== modified file 'src/platforms/mesa/server/kms/display.cpp'
321--- src/platforms/mesa/server/kms/display.cpp 2017-03-29 05:01:13 +0000
322+++ src/platforms/mesa/server/kms/display.cpp 2017-03-29 05:01:14 +0000
323@@ -260,17 +260,6 @@
324
325 auto mgm::Display::create_hardware_cursor() -> std::shared_ptr<graphics::Cursor>
326 {
327- /*
328- * TODO: Using the hardware cursor in a hybrid-output situation requires making
329- * mgm::Cursor hybrid-aware so it can create a cursor bo on each GPU.
330- *
331- * For a first cut, just disable the hardware cursor on hybrid systems.
332- */
333- if (drm.size() > 1)
334- {
335- return nullptr;
336- }
337-
338 // There is only one hardware cursor. We do not keep a strong reference to it in the display though,
339 // if no other component of Mir is interested (i.e. the input stack does not keep a reference to send
340 // position updates) we must be configured not to use a cursor and thusly let it deallocate.
341@@ -298,9 +287,9 @@
342
343 try
344 {
345- locked_cursor = std::make_shared<Cursor>(gbm->device,
346- *output_container,
347- std::make_shared<KMSCurrentConfiguration>(*this));
348+ locked_cursor = std::make_shared<Cursor>(
349+ *output_container,
350+ std::make_shared<KMSCurrentConfiguration>(*this));
351 }
352 catch (std::runtime_error const&)
353 {
354
355=== added file 'src/platforms/mesa/server/kms/mutex.h'
356--- src/platforms/mesa/server/kms/mutex.h 1970-01-01 00:00:00 +0000
357+++ src/platforms/mesa/server/kms/mutex.h 2017-03-29 05:01:14 +0000
358@@ -0,0 +1,104 @@
359+/*
360+ * Copyright © 2017 Canonical Ltd.
361+ *
362+ * This program is free software: you can redistribute it and/or modify it
363+ * under the terms of the GNU Lesser General Public License version 3,
364+ * as published by the Free Software Foundation.
365+ *
366+ * This program is distributed in the hope that it will be useful,
367+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
368+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
369+ * GNU Lesser General Public License for more details.
370+ *
371+ * You should have received a copy of the GNU Lesser General Public License
372+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
373+ *
374+ * Authored by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com>
375+ */
376+
377+#ifndef MIR_MUTEX_H_
378+#define MIR_MUTEX_H_
379+
380+#include <mutex>
381+
382+namespace mir
383+{
384+/**
385+ * Smart-pointer-esque accessor for Mutex<> protected data.
386+ *
387+ * Ensures exclusive access to the referenced data.
388+ *
389+ * \tparam Guarded Type of data guarded by the mutex.
390+ */
391+template<typename Guarded>
392+class MutexGuard
393+{
394+public:
395+ MutexGuard(std::unique_lock<std::mutex>&& lock, Guarded& value)
396+ : value{value},
397+ lock{std::move(lock)}
398+ {
399+ }
400+ MutexGuard(MutexGuard&& from) = default;
401+ ~MutexGuard() noexcept(false)
402+ {
403+ if (lock.owns_lock())
404+ {
405+ lock.unlock();
406+ }
407+ }
408+
409+ Guarded& operator*()
410+ {
411+ return value;
412+ }
413+ Guarded* operator->()
414+ {
415+ return &value;
416+ }
417+private:
418+ Guarded& value;
419+ std::unique_lock<std::mutex> lock;
420+};
421+
422+/**
423+ * A data-locking mutex
424+ *
425+ * This is a mutex which owns the data it guards, and can give out a
426+ * smart-pointer-esque lock to lock and access it.
427+ *
428+ * \tparam Guarded The type of data guarded by the mutex
429+ */
430+template<typename Guarded>
431+class Mutex
432+{
433+public:
434+ Mutex() = default;
435+ Mutex(Guarded&& initial_value)
436+ : value{std::move(initial_value)}
437+ {
438+ }
439+
440+ Mutex(Mutex const&) = delete;
441+ Mutex& operator=(Mutex const&) = delete;
442+
443+ /**
444+ * Lock the mutex and return an accessor for the protected data.
445+ *
446+ * \return A smart-pointer-esque accessor for the contained data.
447+ * While code has access to the MutexGuard it is guaranteed to have exclusive
448+ * access to the contained data.
449+ */
450+ MutexGuard<Guarded> lock()
451+ {
452+ return MutexGuard<Guarded>{std::unique_lock<std::mutex>{mutex}, value};
453+ }
454+
455+private:
456+ std::mutex mutex;
457+ Guarded value;
458+};
459+
460+}
461+
462+#endif //MIR_MUTEX_H_
463
464=== modified file 'tests/unit-tests/platforms/mesa/kms/test_cursor.cpp'
465--- tests/unit-tests/platforms/mesa/kms/test_cursor.cpp 2017-03-10 10:20:24 +0000
466+++ tests/unit-tests/platforms/mesa/kms/test_cursor.cpp 2017-03-29 05:01:14 +0000
467@@ -297,7 +297,7 @@
468
469 size_t const cursor_side{64};
470 MesaCursorTest()
471- : cursor{mock_gbm.fake_gbm.device, output_container,
472+ : cursor{output_container,
473 mt::fake_shared(current_configuration)}
474 {
475 using namespace ::testing;
476@@ -348,7 +348,7 @@
477 GBM_FORMAT_ARGB8888,
478 GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE));
479
480- mgm::Cursor cursor_tmp{mock_gbm.fake_gbm.device, output_container,
481+ mgm::Cursor cursor_tmp{output_container,
482 std::make_shared<StubCurrentConfiguration>(output_container)};
483 }
484
485@@ -356,10 +356,11 @@
486 {
487 using namespace ::testing;
488
489- EXPECT_CALL(mock_gbm, gbm_bo_get_width(_));
490- EXPECT_CALL(mock_gbm, gbm_bo_get_height(_));
491+ // Our standard mock DRM has 2 GPU devices, and we should construct a cursor on both.
492+ EXPECT_CALL(mock_gbm, gbm_bo_get_width(_)).Times(2);
493+ EXPECT_CALL(mock_gbm, gbm_bo_get_height(_)).Times(2);
494
495- mgm::Cursor cursor_tmp{mock_gbm.fake_gbm.device, output_container,
496+ mgm::Cursor cursor_tmp{output_container,
497 std::make_shared<StubCurrentConfiguration>(output_container)};
498 }
499
500@@ -374,7 +375,7 @@
501
502 EXPECT_CALL(mock_gbm, gbm_bo_create(_, drm_buffer_size, drm_buffer_size, _, _));
503
504- mgm::Cursor cursor_tmp{mock_gbm.fake_gbm.device, output_container,
505+ mgm::Cursor cursor_tmp{output_container,
506 std::make_shared<StubCurrentConfiguration>(output_container)};
507 }
508
509@@ -391,7 +392,7 @@
510
511 EXPECT_CALL(mock_gbm, gbm_bo_create(_, 64, 64, _, _));
512
513- mgm::Cursor cursor_tmp{mock_gbm.fake_gbm.device, output_container,
514+ mgm::Cursor cursor_tmp{output_container,
515 std::make_shared<StubCurrentConfiguration>(output_container)};
516 }
517
518@@ -455,7 +456,7 @@
519
520 EXPECT_CALL(mock_gbm, gbm_bo_write(mock_gbm.fake_gbm.bo, ContainsASingleWhitePixel(width*height), buffer_size_bytes));
521
522- mgm::Cursor cursor_tmp{mock_gbm.fake_gbm.device, output_container,
523+ mgm::Cursor cursor_tmp{output_container,
524 std::make_shared<StubCurrentConfiguration>(output_container)};
525 cursor_tmp.show(SinglePixelCursorImage());
526 }
527@@ -492,7 +493,7 @@
528 EXPECT_CALL(*output_container.outputs[1], has_cursor()).Times(0);
529 EXPECT_CALL(*output_container.outputs[2], has_cursor()).Times(0);
530
531- mgm::Cursor cursor_tmp{mock_gbm.fake_gbm.device, output_container,
532+ mgm::Cursor cursor_tmp{output_container,
533 std::make_shared<StubCurrentConfiguration>(output_container)};
534
535 output_container.verify_and_clear_expectations();
536@@ -510,7 +511,7 @@
537 .WillByDefault(Return(false));
538
539 EXPECT_THROW(
540- mgm::Cursor cursor_tmp(mock_gbm.fake_gbm.device, output_container,
541+ mgm::Cursor cursor_tmp(output_container,
542 std::make_shared<StubCurrentConfiguration>(output_container));
543 , std::runtime_error);
544 }

Subscribers

People subscribed via source and target branches