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