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_driver.h"
8
9 #include <cstdlib>
10 #include <cutils/properties.h>
11 #include <fcntl.h>
12 #include <hardware/gralloc.h>
13 #include <sys/mman.h>
14 #include <syscall.h>
15 #include <xf86drm.h>
16
17 #include "../util.h"
18
19 // Constants taken from pipe_loader_drm.c in Mesa
20
21 #define DRM_NUM_NODES 63
22
23 // DRM Render nodes start at 128
24 #define DRM_RENDER_NODE_START 128
25
26 // DRM Card nodes start at 0
27 #define DRM_CARD_NODE_START 0
28
29 class cros_gralloc_driver_preloader
30 {
31 public:
cros_gralloc_driver_preloader()32 cros_gralloc_driver_preloader()
33 {
34 drv_preload(true);
35 }
36
~cros_gralloc_driver_preloader()37 ~cros_gralloc_driver_preloader()
38 {
39 drv_preload(false);
40 }
41 };
42
43 static class cros_gralloc_driver_preloader cros_gralloc_driver_preloader;
44
memfd_create_wrapper(const char * name,unsigned int flags)45 int memfd_create_wrapper(const char *name, unsigned int flags)
46 {
47 int fd;
48
49 #if defined(HAVE_MEMFD_CREATE)
50 fd = memfd_create(name, flags);
51 #elif defined(__NR_memfd_create)
52 fd = syscall(__NR_memfd_create, name, flags);
53 #else
54 ALOGE("Failed to create memfd '%s': memfd_create not available.", name);
55 return -1;
56 #endif
57
58 if (fd == -1)
59 ALOGE("Failed to create memfd '%s': %s.", name, strerror(errno));
60
61 return fd;
62 }
63
memfd_create_reserved_region(const std::string & buffer_name,uint64_t reserved_region_size)64 int memfd_create_reserved_region(const std::string &buffer_name, uint64_t reserved_region_size)
65 {
66 const std::string reserved_region_name = buffer_name + " reserved region";
67
68 int reserved_region_fd = memfd_create_wrapper(reserved_region_name.c_str(), FD_CLOEXEC);
69 if (reserved_region_fd == -1)
70 return -errno;
71
72 if (ftruncate(reserved_region_fd, reserved_region_size)) {
73 ALOGE("Failed to set reserved region size: %s.", strerror(errno));
74 return -errno;
75 }
76
77 return reserved_region_fd;
78 }
79
get_instance()80 cros_gralloc_driver *cros_gralloc_driver::get_instance()
81 {
82 static cros_gralloc_driver s_instance;
83
84 if (!s_instance.is_initialized()) {
85 ALOGE("Failed to initialize driver.");
86 return nullptr;
87 }
88
89 return &s_instance;
90 }
91
init_try_node(int idx,char const * str)92 static struct driver *init_try_node(int idx, char const *str)
93 {
94 int fd;
95 char *node;
96 struct driver *drv;
97
98 if (asprintf(&node, str, DRM_DIR_NAME, idx) < 0)
99 return NULL;
100
101 fd = open(node, O_RDWR, 0);
102 free(node);
103
104 if (fd < 0)
105 return NULL;
106
107 drv = drv_create(fd);
108 if (!drv)
109 close(fd);
110
111 return drv;
112 }
113
init_try_nodes()114 static struct driver *init_try_nodes()
115 {
116 /*
117 * Create a driver from render nodes first, then try card
118 * nodes.
119 *
120 * TODO(gsingh): Enable render nodes on udl/evdi.
121 */
122
123 struct driver *drv;
124 char const *render_nodes_fmt = "%s/renderD%d";
125 char const *card_nodes_fmt = "%s/card%d";
126 uint32_t num_nodes = DRM_NUM_NODES;
127 uint32_t min_render_node = DRM_RENDER_NODE_START;
128 uint32_t max_render_node = (min_render_node + num_nodes);
129 uint32_t min_card_node = DRM_CARD_NODE_START;
130 uint32_t max_card_node = (min_card_node + num_nodes);
131
132 // Try render nodes...
133 for (uint32_t i = min_render_node; i < max_render_node; i++) {
134 drv = init_try_node(i, render_nodes_fmt);
135 if (drv)
136 return drv;
137 }
138
139 // Try card nodes... for vkms mostly.
140 for (uint32_t i = min_card_node; i < max_card_node; i++) {
141 drv = init_try_node(i, card_nodes_fmt);
142 if (drv)
143 return drv;
144 }
145
146 return nullptr;
147 }
148
drv_destroy_and_close(struct driver * drv)149 static void drv_destroy_and_close(struct driver *drv)
150 {
151 int fd = drv_get_fd(drv);
152 drv_destroy(drv);
153 close(fd);
154 }
155
cros_gralloc_driver()156 cros_gralloc_driver::cros_gralloc_driver() : drv_(init_try_nodes(), drv_destroy_and_close)
157 {
158 char buf[PROP_VALUE_MAX];
159 property_get("ro.product.device", buf, "unknown");
160 mt8183_camera_quirk_ = !strncmp(buf, "kukui", strlen("kukui"));
161 }
162
~cros_gralloc_driver()163 cros_gralloc_driver::~cros_gralloc_driver()
164 {
165 buffers_.clear();
166 handles_.clear();
167 }
168
is_initialized()169 bool cros_gralloc_driver::is_initialized()
170 {
171 return drv_ != nullptr;
172 }
173
get_resolved_format_and_use_flags(const struct cros_gralloc_buffer_descriptor * descriptor,uint32_t * out_format,uint64_t * out_use_flags)174 bool cros_gralloc_driver::get_resolved_format_and_use_flags(
175 const struct cros_gralloc_buffer_descriptor *descriptor, uint32_t *out_format,
176 uint64_t *out_use_flags)
177 {
178 uint32_t resolved_format;
179 uint64_t resolved_use_flags;
180 struct combination *combo;
181
182 if (mt8183_camera_quirk_ && (descriptor->use_flags & BO_USE_CAMERA_READ) &&
183 !(descriptor->use_flags & BO_USE_SCANOUT) &&
184 descriptor->drm_format == DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED) {
185 *out_use_flags = descriptor->use_flags;
186 *out_format = DRM_FORMAT_MTISP_SXYZW10;
187 return true;
188 }
189
190 drv_resolve_format_and_use_flags(drv_.get(), descriptor->drm_format, descriptor->use_flags,
191 &resolved_format, &resolved_use_flags);
192
193 combo = drv_get_combination(drv_.get(), resolved_format, resolved_use_flags);
194 if (!combo && (descriptor->droid_usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) &&
195 descriptor->droid_format != HAL_PIXEL_FORMAT_YCbCr_420_888) {
196 // Unmask BO_USE_HW_VIDEO_ENCODER for other formats. They are mostly
197 // intermediate formats not passed directly to the encoder (e.g.
198 // camera). YV12 is passed to the encoder component, but it is converted
199 // to YCbCr_420_888 before being passed to the hw encoder.
200 resolved_use_flags &= ~BO_USE_HW_VIDEO_ENCODER;
201 combo = drv_get_combination(drv_.get(), resolved_format, resolved_use_flags);
202 }
203 if (!combo && (descriptor->droid_usage & BUFFER_USAGE_FRONT_RENDERING_MASK)) {
204 resolved_use_flags &= ~BO_USE_FRONT_RENDERING;
205 resolved_use_flags |= BO_USE_LINEAR;
206 combo = drv_get_combination(drv_.get(), resolved_format, resolved_use_flags);
207 }
208 if (!combo)
209 return false;
210
211 *out_format = resolved_format;
212 *out_use_flags = resolved_use_flags;
213 return true;
214 }
215
is_supported(const struct cros_gralloc_buffer_descriptor * descriptor)216 bool cros_gralloc_driver::is_supported(const struct cros_gralloc_buffer_descriptor *descriptor)
217 {
218 uint32_t resolved_format;
219 uint64_t resolved_use_flags;
220 uint32_t max_texture_size = drv_get_max_texture_2d_size(drv_.get());
221 if (!get_resolved_format_and_use_flags(descriptor, &resolved_format, &resolved_use_flags))
222 return false;
223
224 // Allow blob buffers to go beyond the limit.
225 if (descriptor->droid_format == HAL_PIXEL_FORMAT_BLOB)
226 return true;
227
228 return descriptor->width <= max_texture_size && descriptor->height <= max_texture_size;
229 }
230
create_reserved_region(const std::string & buffer_name,uint64_t reserved_region_size)231 int cros_gralloc_driver::create_reserved_region(const std::string &buffer_name,
232 uint64_t reserved_region_size)
233 {
234 int ret;
235
236 #if ANDROID_API_LEVEL >= 31 && defined(HAS_DMABUF_SYSTEM_HEAP)
237 ret = allocator_.Alloc(kDmabufSystemHeapName, reserved_region_size);
238 if (ret >= 0)
239 return ret;
240 #endif
241
242 ret = memfd_create_reserved_region(buffer_name, reserved_region_size);
243 if (ret >= 0)
244 return ret;
245
246 ALOGE("Failed to create_reserved_region.");
247 return -1;
248 }
249
allocate(const struct cros_gralloc_buffer_descriptor * descriptor,native_handle_t ** out_handle)250 int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descriptor *descriptor,
251 native_handle_t **out_handle)
252 {
253 int ret = 0;
254 size_t num_planes;
255 size_t num_fds;
256 size_t num_ints;
257 uint32_t resolved_format;
258 uint32_t bytes_per_pixel;
259 uint64_t resolved_use_flags;
260 struct bo *bo;
261 struct cros_gralloc_handle *hnd;
262 std::unique_ptr<cros_gralloc_buffer> buffer;
263
264 if (!get_resolved_format_and_use_flags(descriptor, &resolved_format, &resolved_use_flags)) {
265 ALOGE("Failed to resolve format and use_flags.");
266 return -EINVAL;
267 }
268
269 bo = drv_bo_create(drv_.get(), descriptor->width, descriptor->height, resolved_format,
270 resolved_use_flags);
271 if (!bo) {
272 ALOGE("Failed to create bo.");
273 return -errno;
274 }
275
276 /*
277 * If there is a desire for more than one kernel buffer, this can be
278 * removed once the ArcCodec and Wayland service have the ability to
279 * send more than one fd. GL/Vulkan drivers may also have to modified.
280 */
281 if (drv_num_buffers_per_bo(bo) != 1) {
282 ALOGE("Can only support one buffer per bo.");
283 goto destroy_bo;
284 }
285
286 num_planes = drv_bo_get_num_planes(bo);
287 num_fds = num_planes;
288
289 if (descriptor->reserved_region_size > 0)
290 num_fds += 1;
291
292 num_ints = ((sizeof(struct cros_gralloc_handle) - sizeof(native_handle_t)) / sizeof(int)) -
293 num_fds;
294
295 hnd =
296 reinterpret_cast<struct cros_gralloc_handle *>(native_handle_create(num_fds, num_ints));
297
298 for (size_t i = 0; i < DRV_MAX_FDS; i++)
299 hnd->fds[i] = -1;
300
301 hnd->num_planes = num_planes;
302 for (size_t plane = 0; plane < num_planes; plane++) {
303 ret = drv_bo_get_plane_fd(bo, plane);
304 if (ret < 0)
305 goto destroy_hnd;
306
307 hnd->fds[plane] = ret;
308 hnd->strides[plane] = drv_bo_get_plane_stride(bo, plane);
309 hnd->offsets[plane] = drv_bo_get_plane_offset(bo, plane);
310 hnd->sizes[plane] = drv_bo_get_plane_size(bo, plane);
311 }
312
313 hnd->reserved_region_size = descriptor->reserved_region_size;
314 if (hnd->reserved_region_size > 0) {
315 ret = create_reserved_region(descriptor->name, hnd->reserved_region_size);
316 if (ret < 0)
317 goto destroy_hnd;
318
319 hnd->fds[hnd->num_planes] = ret;
320 }
321
322 static std::atomic<uint32_t> next_buffer_id{ 1 };
323 hnd->id = next_buffer_id++;
324 hnd->width = drv_bo_get_width(bo);
325 hnd->height = drv_bo_get_height(bo);
326 hnd->format = drv_bo_get_format(bo);
327 hnd->tiling = drv_bo_get_tiling(bo);
328 hnd->format_modifier = drv_bo_get_format_modifier(bo);
329 hnd->use_flags = drv_bo_get_use_flags(bo);
330 bytes_per_pixel = drv_bytes_per_pixel_from_format(hnd->format, 0);
331 hnd->pixel_stride = DIV_ROUND_UP(hnd->strides[0], bytes_per_pixel);
332 hnd->magic = cros_gralloc_magic;
333 hnd->droid_format = descriptor->droid_format;
334 hnd->usage = descriptor->droid_usage;
335 hnd->total_size = descriptor->reserved_region_size + drv_bo_get_total_size(bo);
336
337 buffer = cros_gralloc_buffer::create(bo, hnd);
338 if (!buffer) {
339 ALOGE("Failed to allocate: failed to create cros_gralloc_buffer.");
340 ret = -1;
341 goto destroy_hnd;
342 }
343
344 {
345 std::lock_guard<std::mutex> lock(mutex_);
346
347 struct cros_gralloc_imported_handle_info hnd_info = {
348 .buffer = buffer.get(),
349 .refcount = 1,
350 };
351 handles_.emplace(hnd, hnd_info);
352 buffers_.emplace(hnd->id, std::move(buffer));
353 }
354
355 *out_handle = hnd;
356 return 0;
357
358 destroy_hnd:
359 native_handle_close(hnd);
360 native_handle_delete(hnd);
361
362 destroy_bo:
363 drv_bo_destroy(bo);
364 return ret;
365 }
366
retain(buffer_handle_t handle)367 int32_t cros_gralloc_driver::retain(buffer_handle_t handle)
368 {
369 std::lock_guard<std::mutex> lock(mutex_);
370
371 auto hnd = cros_gralloc_convert_handle(handle);
372 if (!hnd) {
373 ALOGE("Invalid handle.");
374 return -EINVAL;
375 }
376
377 auto hnd_it = handles_.find(hnd);
378 if (hnd_it != handles_.end()) {
379 // The underlying buffer (as multiple handles can refer to the same buffer)
380 // has already been imported into this process and the given handle has
381 // already been registered in this process. Increase both the buffer and
382 // handle reference count.
383 auto &hnd_info = hnd_it->second;
384
385 hnd_info.buffer->increase_refcount();
386 hnd_info.refcount++;
387
388 return 0;
389 }
390
391 uint32_t id = hnd->id;
392
393 cros_gralloc_buffer *buffer = nullptr;
394
395 auto buffer_it = buffers_.find(id);
396 if (buffer_it != buffers_.end()) {
397 // The underlying buffer (as multiple handles can refer to the same buffer)
398 // has already been imported into this process but the given handle has not
399 // yet been registered. Increase the buffer reference count (here) and start
400 // to track the handle (below).
401 buffer = buffer_it->second.get();
402 buffer->increase_refcount();
403 } else {
404 // The underlying buffer has not yet been imported into this process. Import
405 // and start to track the buffer (here) and start to track the handle (below).
406 struct drv_import_fd_data data = {
407 .format_modifier = hnd->format_modifier,
408 .width = hnd->width,
409 .height = hnd->height,
410 .format = hnd->format,
411 .tiling = hnd->tiling,
412 .use_flags = hnd->use_flags,
413 };
414 memcpy(data.fds, hnd->fds, sizeof(data.fds));
415 memcpy(data.strides, hnd->strides, sizeof(data.strides));
416 memcpy(data.offsets, hnd->offsets, sizeof(data.offsets));
417
418 struct bo *bo = drv_bo_import(drv_.get(), &data);
419 if (!bo)
420 return -EFAULT;
421
422 auto scoped_buffer = cros_gralloc_buffer::create(bo, hnd);
423 if (!scoped_buffer) {
424 ALOGE("Failed to import: failed to create cros_gralloc_buffer.");
425 return -1;
426 }
427 buffer = scoped_buffer.get();
428 buffers_.emplace(id, std::move(scoped_buffer));
429 }
430
431 struct cros_gralloc_imported_handle_info hnd_info = {
432 .buffer = buffer,
433 .refcount = 1,
434 };
435 handles_.emplace(hnd, hnd_info);
436 return 0;
437 }
438
release(buffer_handle_t handle)439 int32_t cros_gralloc_driver::release(buffer_handle_t handle)
440 {
441 std::lock_guard<std::mutex> lock(mutex_);
442
443 auto hnd = cros_gralloc_convert_handle(handle);
444 if (!hnd) {
445 ALOGE("Invalid handle.");
446 return -EINVAL;
447 }
448
449 auto buffer = get_buffer(hnd);
450 if (!buffer) {
451 ALOGE("Invalid reference (release() called on unregistered handle).");
452 return -EINVAL;
453 }
454
455 if (!--handles_[hnd].refcount)
456 handles_.erase(hnd);
457
458 if (buffer->decrease_refcount() == 0) {
459 buffers_.erase(buffer->get_id());
460 }
461
462 return 0;
463 }
464
lock(buffer_handle_t handle,int32_t acquire_fence,bool close_acquire_fence,const struct rectangle * rect,uint32_t map_flags,uint8_t * addr[DRV_MAX_PLANES])465 int32_t cros_gralloc_driver::lock(buffer_handle_t handle, int32_t acquire_fence,
466 bool close_acquire_fence, const struct rectangle *rect,
467 uint32_t map_flags, uint8_t *addr[DRV_MAX_PLANES])
468 {
469 int32_t ret = cros_gralloc_sync_wait(acquire_fence, close_acquire_fence);
470 if (ret)
471 return ret;
472
473 std::lock_guard<std::mutex> lock(mutex_);
474
475 auto hnd = cros_gralloc_convert_handle(handle);
476 if (!hnd) {
477 ALOGE("Invalid handle.");
478 return -EINVAL;
479 }
480
481 auto buffer = get_buffer(hnd);
482 if (!buffer) {
483 ALOGE("Invalid reference (lock() called on unregistered handle).");
484 return -EINVAL;
485 }
486
487 return buffer->lock(rect, map_flags, addr);
488 }
489
unlock(buffer_handle_t handle,int32_t * release_fence)490 int32_t cros_gralloc_driver::unlock(buffer_handle_t handle, int32_t *release_fence)
491 {
492 std::lock_guard<std::mutex> lock(mutex_);
493
494 auto hnd = cros_gralloc_convert_handle(handle);
495 if (!hnd) {
496 ALOGE("Invalid handle.");
497 return -EINVAL;
498 }
499
500 auto buffer = get_buffer(hnd);
501 if (!buffer) {
502 ALOGE("Invalid reference (unlock() called on unregistered handle).");
503 return -EINVAL;
504 }
505
506 /*
507 * From the ANativeWindow::dequeueBuffer documentation:
508 *
509 * "A value of -1 indicates that the caller may access the buffer immediately without
510 * waiting on a fence."
511 */
512 *release_fence = -1;
513 return buffer->unlock();
514 }
515
invalidate(buffer_handle_t handle)516 int32_t cros_gralloc_driver::invalidate(buffer_handle_t handle)
517 {
518 std::lock_guard<std::mutex> lock(mutex_);
519
520 auto hnd = cros_gralloc_convert_handle(handle);
521 if (!hnd) {
522 ALOGE("Invalid handle.");
523 return -EINVAL;
524 }
525
526 auto buffer = get_buffer(hnd);
527 if (!buffer) {
528 ALOGE("Invalid reference (invalidate() called on unregistered handle).");
529 return -EINVAL;
530 }
531
532 return buffer->invalidate();
533 }
534
flush(buffer_handle_t handle)535 int32_t cros_gralloc_driver::flush(buffer_handle_t handle)
536 {
537 std::lock_guard<std::mutex> lock(mutex_);
538
539 auto hnd = cros_gralloc_convert_handle(handle);
540 if (!hnd) {
541 ALOGE("Invalid handle.");
542 return -EINVAL;
543 }
544
545 auto buffer = get_buffer(hnd);
546 if (!buffer) {
547 ALOGE("Invalid reference (flush() called on unregistered handle).");
548 return -EINVAL;
549 }
550
551 return buffer->flush();
552 }
553
get_backing_store(buffer_handle_t handle,uint64_t * out_store)554 int32_t cros_gralloc_driver::get_backing_store(buffer_handle_t handle, uint64_t *out_store)
555 {
556 std::lock_guard<std::mutex> lock(mutex_);
557
558 auto hnd = cros_gralloc_convert_handle(handle);
559 if (!hnd) {
560 ALOGE("Invalid handle.");
561 return -EINVAL;
562 }
563
564 auto buffer = get_buffer(hnd);
565 if (!buffer) {
566 ALOGE("Invalid reference (get_backing_store() called on unregistered handle).");
567 return -EINVAL;
568 }
569
570 *out_store = static_cast<uint64_t>(buffer->get_id());
571 return 0;
572 }
573
resource_info(buffer_handle_t handle,uint32_t strides[DRV_MAX_PLANES],uint32_t offsets[DRV_MAX_PLANES],uint64_t * format_modifier)574 int32_t cros_gralloc_driver::resource_info(buffer_handle_t handle, uint32_t strides[DRV_MAX_PLANES],
575 uint32_t offsets[DRV_MAX_PLANES],
576 uint64_t *format_modifier)
577 {
578 std::lock_guard<std::mutex> lock(mutex_);
579
580 auto hnd = cros_gralloc_convert_handle(handle);
581 if (!hnd) {
582 ALOGE("Invalid handle.");
583 return -EINVAL;
584 }
585
586 auto buffer = get_buffer(hnd);
587 if (!buffer) {
588 ALOGE("Invalid reference (resource_info() called on unregistered handle).");
589 return -EINVAL;
590 }
591
592 return buffer->resource_info(strides, offsets, format_modifier);
593 }
594
get_reserved_region(buffer_handle_t handle,void ** reserved_region_addr,uint64_t * reserved_region_size)595 int32_t cros_gralloc_driver::get_reserved_region(buffer_handle_t handle,
596 void **reserved_region_addr,
597 uint64_t *reserved_region_size)
598 {
599 std::lock_guard<std::mutex> lock(mutex_);
600
601 auto hnd = cros_gralloc_convert_handle(handle);
602 if (!hnd) {
603 ALOGE("Invalid handle.");
604 return -EINVAL;
605 }
606
607 auto buffer = get_buffer(hnd);
608 if (!buffer) {
609 ALOGE("Invalid reference (get_reserved_region() called on unregistered handle).");
610 return -EINVAL;
611 }
612
613 return buffer->get_reserved_region(reserved_region_addr, reserved_region_size);
614 }
615
get_resolved_drm_format(uint32_t drm_format,uint64_t use_flags)616 uint32_t cros_gralloc_driver::get_resolved_drm_format(uint32_t drm_format, uint64_t use_flags)
617 {
618 uint32_t resolved_format;
619 uint64_t resolved_use_flags;
620
621 drv_resolve_format_and_use_flags(drv_.get(), drm_format, use_flags, &resolved_format,
622 &resolved_use_flags);
623
624 return resolved_format;
625 }
626
get_buffer(cros_gralloc_handle_t hnd)627 cros_gralloc_buffer *cros_gralloc_driver::get_buffer(cros_gralloc_handle_t hnd)
628 {
629 /* Assumes driver mutex is held. */
630 if (handles_.count(hnd))
631 return handles_[hnd].buffer;
632
633 return nullptr;
634 }
635
with_buffer(cros_gralloc_handle_t hnd,const std::function<void (cros_gralloc_buffer *)> & function)636 void cros_gralloc_driver::with_buffer(cros_gralloc_handle_t hnd,
637 const std::function<void(cros_gralloc_buffer *)> &function)
638 {
639 std::lock_guard<std::mutex> lock(mutex_);
640
641 auto buffer = get_buffer(hnd);
642 if (!buffer) {
643 ALOGE("Invalid reference (with_buffer() called on unregistered handle).");
644 return;
645 }
646
647 function(buffer);
648 }
649
with_each_buffer(const std::function<void (cros_gralloc_buffer *)> & function)650 void cros_gralloc_driver::with_each_buffer(
651 const std::function<void(cros_gralloc_buffer *)> &function)
652 {
653 std::lock_guard<std::mutex> lock(mutex_);
654
655 for (const auto &pair : buffers_)
656 function(pair.second.get());
657 }
658