• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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