• 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 <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