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