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