1 /*
2 * Copyright 2017 The Chromium OS Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
6
7 #include "cros_gralloc_buffer.h"
8
9 #include <assert.h>
10 #include <sys/mman.h>
11
12 #include <cutils/native_handle.h>
13
14 #include "cros_gralloc_buffer_metadata.h"
15
16 using aidl::android::hardware::graphics::common::BlendMode;
17 using aidl::android::hardware::graphics::common::Cta861_3;
18 using aidl::android::hardware::graphics::common::Dataspace;
19 using aidl::android::hardware::graphics::common::Smpte2086;
20
21 /*static*/
22 std::unique_ptr<cros_gralloc_buffer>
create(struct bo * acquire_bo,const struct cros_gralloc_handle * borrowed_handle)23 cros_gralloc_buffer::create(struct bo *acquire_bo,
24 const struct cros_gralloc_handle *borrowed_handle)
25 {
26 auto acquire_hnd =
27 reinterpret_cast<struct cros_gralloc_handle *>(native_handle_clone(borrowed_handle));
28 if (!acquire_hnd) {
29 ALOGE("Failed to create cros_gralloc_buffer: failed to clone handle.");
30 return {};
31 }
32
33 std::unique_ptr<cros_gralloc_buffer> buffer(
34 new cros_gralloc_buffer(acquire_bo, acquire_hnd));
35 if (!buffer) {
36 ALOGE("Failed to create cros_gralloc_buffer: failed to allocate.");
37 native_handle_close(acquire_hnd);
38 native_handle_delete(acquire_hnd);
39 return {};
40 }
41
42 return buffer;
43 }
44
45 int32_t
initialize_metadata(const struct cros_gralloc_buffer_descriptor * descriptor)46 cros_gralloc_buffer::initialize_metadata(const struct cros_gralloc_buffer_descriptor *descriptor)
47 {
48 struct cros_gralloc_buffer_metadata *metadata;
49
50 int ret = get_metadata(&metadata);
51 if (ret) {
52 ALOGE("Failed to initialize metadata: failed to get metadata region.");
53 return ret;
54 }
55
56 if (metadata == nullptr) {
57 ALOGE("Failed to initialize metadata: invalid metadata address.");
58 return -1;
59 }
60
61 new (metadata) cros_gralloc_buffer_metadata();
62
63 snprintf(metadata->name, CROS_GRALLOC_BUFFER_METADATA_MAX_NAME_SIZE, "%s",
64 descriptor->name.c_str());
65 metadata->dataspace = descriptor->dataspace;
66 metadata->blend_mode = descriptor->blend;
67 return 0;
68 }
69
cros_gralloc_buffer(struct bo * acquire_bo,struct cros_gralloc_handle * acquire_handle)70 cros_gralloc_buffer::cros_gralloc_buffer(struct bo *acquire_bo,
71 struct cros_gralloc_handle *acquire_handle)
72 : bo_(acquire_bo), hnd_(acquire_handle)
73 {
74 assert(bo_);
75 assert(hnd_);
76 for (uint32_t plane = 0; plane < DRV_MAX_PLANES; plane++)
77 lock_data_[plane] = nullptr;
78 }
79
~cros_gralloc_buffer()80 cros_gralloc_buffer::~cros_gralloc_buffer()
81 {
82 drv_bo_destroy(bo_);
83 if (reserved_region_addr_) {
84 munmap(reserved_region_addr_, hnd_->reserved_region_size);
85 }
86 native_handle_close(hnd_);
87 native_handle_delete(hnd_);
88 }
89
get_id() const90 uint32_t cros_gralloc_buffer::get_id() const
91 {
92 return hnd_->id;
93 }
94
get_width() const95 uint32_t cros_gralloc_buffer::get_width() const
96 {
97 return hnd_->width;
98 }
99
get_pixel_stride() const100 uint32_t cros_gralloc_buffer::get_pixel_stride() const
101 {
102 return hnd_->pixel_stride;
103 }
104
get_height() const105 uint32_t cros_gralloc_buffer::get_height() const
106 {
107 return hnd_->height;
108 }
109
get_format() const110 uint32_t cros_gralloc_buffer::get_format() const
111 {
112 return hnd_->format;
113 }
114
get_format_modifier() const115 uint64_t cros_gralloc_buffer::get_format_modifier() const
116 {
117 return hnd_->format_modifier;
118 }
119
get_total_size() const120 uint64_t cros_gralloc_buffer::get_total_size() const
121 {
122 return hnd_->total_size;
123 }
124
get_num_planes() const125 uint32_t cros_gralloc_buffer::get_num_planes() const
126 {
127 return hnd_->num_planes;
128 }
129
get_plane_offset(uint32_t plane) const130 uint32_t cros_gralloc_buffer::get_plane_offset(uint32_t plane) const
131 {
132 return hnd_->offsets[plane];
133 }
134
get_plane_stride(uint32_t plane) const135 uint32_t cros_gralloc_buffer::get_plane_stride(uint32_t plane) const
136 {
137 return hnd_->strides[plane];
138 }
139
get_plane_size(uint32_t plane) const140 uint32_t cros_gralloc_buffer::get_plane_size(uint32_t plane) const
141 {
142 return hnd_->sizes[plane];
143 }
144
get_android_format() const145 int32_t cros_gralloc_buffer::get_android_format() const
146 {
147 return hnd_->droid_format;
148 }
149
get_android_usage() const150 int64_t cros_gralloc_buffer::get_android_usage() const
151 {
152 return hnd_->usage;
153 }
154
get_name(std::optional<std::string> * name) const155 int32_t cros_gralloc_buffer::get_name(std::optional<std::string> *name) const
156 {
157 const struct cros_gralloc_buffer_metadata *metadata;
158
159 int ret = get_metadata(&metadata);
160 if (ret) {
161 ALOGE("Failed to get_name: failed to get metadata.");
162 return ret;
163 }
164
165 *name = metadata->name;
166 return 0;
167 }
168
get_blend_mode(std::optional<BlendMode> * blend_mode) const169 int32_t cros_gralloc_buffer::get_blend_mode(std::optional<BlendMode> *blend_mode) const
170 {
171 const struct cros_gralloc_buffer_metadata *metadata;
172
173 int ret = get_metadata(&metadata);
174 if (ret) {
175 ALOGE("Failed to get_blend_mode: failed to get metadata.");
176 return ret;
177 }
178
179 *blend_mode = metadata->blend_mode;
180 return 0;
181 }
182
set_blend_mode(BlendMode blend_mode)183 int32_t cros_gralloc_buffer::set_blend_mode(BlendMode blend_mode)
184 {
185 struct cros_gralloc_buffer_metadata *metadata;
186
187 int ret = get_metadata(&metadata);
188 if (ret) {
189 ALOGE("Failed to set_blend_mode: failed to get metadata.");
190 return ret;
191 }
192
193 metadata->blend_mode = blend_mode;
194 return 0;
195 }
196
get_dataspace(std::optional<Dataspace> * dataspace) const197 int32_t cros_gralloc_buffer::get_dataspace(std::optional<Dataspace> *dataspace) const
198 {
199 const struct cros_gralloc_buffer_metadata *metadata;
200
201 int ret = get_metadata(&metadata);
202 if (ret) {
203 ALOGE("Failed to get_dataspace: failed to get metadata.");
204 return ret;
205 }
206
207 *dataspace = metadata->dataspace;
208 return 0;
209 }
210
set_dataspace(Dataspace dataspace)211 int32_t cros_gralloc_buffer::set_dataspace(Dataspace dataspace)
212 {
213 struct cros_gralloc_buffer_metadata *metadata;
214
215 int ret = get_metadata(&metadata);
216 if (ret) {
217 ALOGE("Failed to set_dataspace: failed to get metadata.");
218 return ret;
219 }
220
221 metadata->dataspace = dataspace;
222 return 0;
223 }
224
get_cta861_3(std::optional<Cta861_3> * cta) const225 int32_t cros_gralloc_buffer::get_cta861_3(std::optional<Cta861_3> *cta) const
226 {
227 const struct cros_gralloc_buffer_metadata *metadata;
228
229 int ret = get_metadata(&metadata);
230 if (ret) {
231 ALOGE("Failed to get_cta861_3: failed to get metadata.");
232 return ret;
233 }
234
235 *cta = metadata->cta861_3.to_std_optional();
236 return 0;
237 }
238
set_cta861_3(std::optional<Cta861_3> cta)239 int32_t cros_gralloc_buffer::set_cta861_3(std::optional<Cta861_3> cta)
240 {
241 struct cros_gralloc_buffer_metadata *metadata;
242
243 int ret = get_metadata(&metadata);
244 if (ret) {
245 ALOGE("Failed to set_cta861_3: failed to get metadata.");
246 return ret;
247 }
248
249 metadata->cta861_3 = cta;
250 return 0;
251 }
252
get_smpte2086(std::optional<Smpte2086> * smpte) const253 int32_t cros_gralloc_buffer::get_smpte2086(std::optional<Smpte2086> *smpte) const
254 {
255 const struct cros_gralloc_buffer_metadata *metadata;
256
257 int ret = get_metadata(&metadata);
258 if (ret) {
259 ALOGE("Failed to get_smpte2086: failed to get metadata.");
260 return ret;
261 }
262
263 *smpte = metadata->smpte2086.to_std_optional();
264 return 0;
265 }
266
set_smpte2086(std::optional<Smpte2086> smpte)267 int32_t cros_gralloc_buffer::set_smpte2086(std::optional<Smpte2086> smpte)
268 {
269 struct cros_gralloc_buffer_metadata *metadata;
270
271 int ret = get_metadata(&metadata);
272 if (ret) {
273 ALOGE("Failed to set_cta861_3: failed to get metadata.");
274 return ret;
275 }
276
277 metadata->smpte2086 = smpte;
278 return 0;
279 }
280
increase_refcount()281 int32_t cros_gralloc_buffer::increase_refcount()
282 {
283 return ++refcount_;
284 }
285
decrease_refcount()286 int32_t cros_gralloc_buffer::decrease_refcount()
287 {
288 assert(refcount_ > 0);
289 return --refcount_;
290 }
291
lock(const struct rectangle * rect,uint32_t map_flags,uint8_t * addr[DRV_MAX_PLANES])292 int32_t cros_gralloc_buffer::lock(const struct rectangle *rect, uint32_t map_flags,
293 uint8_t *addr[DRV_MAX_PLANES])
294 {
295 void *vaddr = nullptr;
296
297 memset(addr, 0, DRV_MAX_PLANES * sizeof(*addr));
298
299 if (map_flags) {
300 if (lock_data_[0]) {
301 drv_bo_invalidate(bo_, lock_data_[0]);
302 vaddr = lock_data_[0]->vma->addr;
303 } else {
304 struct rectangle r = *rect;
305
306 if (!r.width && !r.height && !r.x && !r.y) {
307 /*
308 * Android IMapper.hal: An accessRegion of all-zeros means the
309 * entire buffer.
310 */
311 r.width = drv_bo_get_width(bo_);
312 r.height = drv_bo_get_height(bo_);
313 }
314
315 vaddr = drv_bo_map(bo_, &r, map_flags, &lock_data_[0], 0);
316 }
317
318 if (vaddr == MAP_FAILED) {
319 ALOGE("Mapping failed.");
320 return -EFAULT;
321 }
322 }
323
324 for (uint32_t plane = 0; plane < hnd_->num_planes; plane++)
325 addr[plane] = static_cast<uint8_t *>(vaddr) + drv_bo_get_plane_offset(bo_, plane);
326
327 lockcount_++;
328 return 0;
329 }
330
unlock()331 int32_t cros_gralloc_buffer::unlock()
332 {
333 if (lockcount_ <= 0) {
334 ALOGE("Buffer was not locked.");
335 return -EINVAL;
336 }
337
338 if (!--lockcount_) {
339 if (lock_data_[0]) {
340 drv_bo_flush_or_unmap(bo_, lock_data_[0]);
341 lock_data_[0] = nullptr;
342 }
343 }
344
345 return 0;
346 }
347
resource_info(uint32_t strides[DRV_MAX_PLANES],uint32_t offsets[DRV_MAX_PLANES],uint64_t * format_modifier)348 int32_t cros_gralloc_buffer::resource_info(uint32_t strides[DRV_MAX_PLANES],
349 uint32_t offsets[DRV_MAX_PLANES],
350 uint64_t *format_modifier)
351 {
352 return drv_resource_info(bo_, strides, offsets, format_modifier);
353 }
354
invalidate()355 int32_t cros_gralloc_buffer::invalidate()
356 {
357 if (lockcount_ <= 0) {
358 ALOGE("Buffer was not locked.");
359 return -EINVAL;
360 }
361
362 if (lock_data_[0])
363 return drv_bo_invalidate(bo_, lock_data_[0]);
364
365 return 0;
366 }
367
flush()368 int32_t cros_gralloc_buffer::flush()
369 {
370 if (lockcount_ <= 0) {
371 ALOGE("Buffer was not locked.");
372 return -EINVAL;
373 }
374
375 if (lock_data_[0])
376 return drv_bo_flush(bo_, lock_data_[0]);
377
378 return 0;
379 }
380
get_reserved_region(void ** addr,uint64_t * size) const381 int32_t cros_gralloc_buffer::get_reserved_region(void **addr, uint64_t *size) const
382 {
383 int32_t reserved_region_fd = hnd_->fds[hnd_->num_planes];
384 if (reserved_region_fd < 0) {
385 ALOGE("Buffer does not have reserved region.");
386 return -EINVAL;
387 }
388
389 if (!reserved_region_addr_) {
390 reserved_region_addr_ =
391 mmap(nullptr, hnd_->reserved_region_size, PROT_WRITE | PROT_READ, MAP_SHARED,
392 reserved_region_fd, 0);
393 if (reserved_region_addr_ == MAP_FAILED) {
394 ALOGE("Failed to mmap reserved region: %s.", strerror(errno));
395 return -errno;
396 }
397 }
398
399 *addr = reserved_region_addr_;
400 *size = hnd_->reserved_region_size;
401 return 0;
402 }
403
get_client_reserved_region(void ** client_reserved_region_addr,uint64_t * client_reserved_region_size) const404 int32_t cros_gralloc_buffer::get_client_reserved_region(void **client_reserved_region_addr,
405 uint64_t *client_reserved_region_size) const
406 {
407 int32_t ret = get_reserved_region(client_reserved_region_addr, client_reserved_region_size);
408 if (ret) {
409 return ret;
410 }
411
412 *client_reserved_region_addr =
413 reinterpret_cast<void *>(reinterpret_cast<char *>(*client_reserved_region_addr) +
414 sizeof(struct cros_gralloc_buffer_metadata));
415 *client_reserved_region_size =
416 *client_reserved_region_size - sizeof(struct cros_gralloc_buffer_metadata);
417 return 0;
418 }
419
get_metadata(struct cros_gralloc_buffer_metadata ** metadata)420 int32_t cros_gralloc_buffer::get_metadata(struct cros_gralloc_buffer_metadata **metadata)
421 {
422 void *metadata_addr;
423 uint64_t metadata_region_size;
424 int32_t ret = get_reserved_region(&metadata_addr, &metadata_region_size);
425 if (ret) {
426 return ret;
427 }
428
429 if (metadata_addr == nullptr) {
430 return -1;
431 }
432
433 *metadata = reinterpret_cast<struct cros_gralloc_buffer_metadata *>(metadata_addr);
434 return 0;
435 }
436
437 int32_t
get_metadata(const struct cros_gralloc_buffer_metadata ** metadata) const438 cros_gralloc_buffer::get_metadata(const struct cros_gralloc_buffer_metadata **metadata) const
439 {
440 void *metadata_addr;
441 uint64_t metadata_region_size;
442 int32_t ret = get_reserved_region(&metadata_addr, &metadata_region_size);
443 if (ret) {
444 return ret;
445 }
446
447 if (metadata_addr == nullptr) {
448 return -1;
449 }
450
451 *metadata = reinterpret_cast<const struct cros_gralloc_buffer_metadata *>(metadata_addr);
452 return 0;
453 }
454