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.
7 #include "cros_gralloc_driver.h"
14 #include <xf86drmMode.h>
16 #include "../drv_priv.h"
17 #include "../helpers.h"
20 // Constants taken from pipe_loader_drm.c in Mesa
22 #define DRM_NUM_NODES 63
24 // DRM Render nodes start at 128
25 #define DRM_RENDER_NODE_START 128
27 // DRM Card nodes start at 0
28 #define DRM_CARD_NODE_START 0
30 int memfd_create_wrapper(const char *name, unsigned int flags)
34 #if defined(HAVE_MEMFD_CREATE)
35 fd = memfd_create(name, flags);
36 #elif defined(__NR_memfd_create)
37 fd = syscall(__NR_memfd_create, name, flags);
39 drv_log("Failed to create memfd '%s': memfd_create not available.", name);
44 drv_log("Failed to create memfd '%s': %s.\n", name, strerror(errno));
49 cros_gralloc_driver::cros_gralloc_driver() : drv_(nullptr)
53 cros_gralloc_driver::~cros_gralloc_driver()
59 int fd = drv_get_fd(drv_);
66 static bool is_kms_dev(const char *path)
68 int fd = open(path, O_RDWR | O_CLOEXEC);
72 auto res = drmModeGetResources(fd);
78 bool is_kms = res->count_crtcs > 0 && res->count_connectors > 0 && res->count_encoders > 0;
80 drmModeFreeResources(res);
86 static struct driver *init_try_node(int idx, bool use_card_node, bool try_generic)
92 if (asprintf(&node, use_card_node ? "%s/card%d" : "%s/renderD%d", DRM_DIR_NAME, idx) < 0)
95 if (use_card_node && !is_kms_dev(node)) {
100 fd = open(node, O_RDWR, 0);
106 drv = drv_create(fd, try_generic);
113 int cros_gralloc_driver::get_fd() const {
114 return drv_get_fd(drv_);
117 int32_t cros_gralloc_driver::init()
120 * Create a driver from render nodes first, then try card
123 * TODO(gsingh): Enable render nodes on udl/evdi.
126 uint32_t num_nodes = DRM_NUM_NODES;
127 uint32_t min_render_node = DRM_RENDER_NODE_START;
128 uint32_t max_render_node = (min_render_node + num_nodes);
129 uint32_t min_card_node = DRM_CARD_NODE_START;
130 uint32_t max_card_node = (min_card_node + num_nodes);
132 // Try render nodes...
133 for (uint32_t i = min_render_node; i < max_render_node; i++) {
134 drv_ = init_try_node(i, false, false);
139 // Try card nodes... for vkms mostly.
140 for (uint32_t i = min_card_node; i < max_card_node; i++) {
141 drv_ = init_try_node(i, true, false);
146 #ifdef DRI_GENERIC_DRV
147 // Try card nodes using mesa3d/dri backend
148 for (uint32_t i = min_card_node; i < max_card_node; i++) {
149 drv_ = init_try_node(i, true, true);
154 // Try render nodes using mesa3d/dri backend
155 for (uint32_t i = min_render_node; i < max_render_node; i++) {
156 drv_ = init_try_node(i, false, true);
165 int cros_gralloc_driver::init_master()
167 int fd = open(DRM_DIR_NAME "/card0", O_RDWR, 0);
169 drv_ = drv_create(fd, true);
177 bool cros_gralloc_driver::is_supported(const struct cros_gralloc_buffer_descriptor *descriptor)
179 struct combination *combo;
180 uint32_t resolved_format;
181 resolved_format = drv_resolve_format(drv_, descriptor->drm_format, descriptor->use_flags);
182 combo = drv_get_combination(drv_, resolved_format, descriptor->use_flags);
183 return (combo != nullptr);
186 int32_t create_reserved_region(const std::string &buffer_name, uint64_t reserved_region_size)
188 std::string reserved_region_name = buffer_name + " reserved region";
190 int32_t reserved_region_fd = memfd_create_wrapper(reserved_region_name.c_str(), FD_CLOEXEC);
191 if (reserved_region_fd == -1) {
195 if (ftruncate(reserved_region_fd, reserved_region_size)) {
196 drv_log("Failed to set reserved region size: %s.\n", strerror(errno));
200 return reserved_region_fd;
203 int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descriptor *descriptor,
204 buffer_handle_t *out_handle)
211 uint32_t resolved_format;
212 uint32_t bytes_per_pixel;
214 int32_t reserved_region_fd;
218 struct cros_gralloc_handle *hnd;
220 resolved_format = drv_resolve_format(drv_, descriptor->drm_format, descriptor->use_flags);
221 use_flags = descriptor->use_flags;
223 * TODO(b/79682290): ARC++ assumes NV12 is always linear and doesn't
224 * send modifiers across Wayland protocol, so we or in the
225 * BO_USE_LINEAR flag here. We need to fix ARC++ to allocate and work
226 * with tiled buffers.
228 if (resolved_format == DRM_FORMAT_NV12)
229 use_flags |= BO_USE_LINEAR;
232 * This unmask is a backup in the case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED is resolved
233 * to non-YUV formats.
235 if (descriptor->drm_format == DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED &&
236 (resolved_format == DRM_FORMAT_XBGR8888 || resolved_format == DRM_FORMAT_ABGR8888)) {
237 use_flags &= ~BO_USE_HW_VIDEO_ENCODER;
240 bo = drv_bo_create(drv_, descriptor->width, descriptor->height, resolved_format, use_flags);
242 drv_log("Failed to create bo.\n");
247 * If there is a desire for more than one kernel buffer, this can be
248 * removed once the ArcCodec and Wayland service have the ability to
249 * send more than one fd. GL/Vulkan drivers may also have to modified.
251 if (drv_num_buffers_per_bo(bo) != 1) {
253 drv_log("Can only support one buffer per bo.\n");
257 num_planes = drv_bo_get_num_planes(bo);
258 num_fds = num_planes;
260 if (descriptor->reserved_region_size > 0) {
262 create_reserved_region(descriptor->name, descriptor->reserved_region_size);
263 if (reserved_region_fd < 0) {
265 return reserved_region_fd;
269 reserved_region_fd = -1;
272 num_bytes = sizeof(struct cros_gralloc_handle);
273 num_bytes += (descriptor->name.size() + 1);
275 * Ensure that the total number of bytes is a multiple of sizeof(int) as
276 * native_handle_clone() copies data based on hnd->base.numInts.
278 num_bytes = ALIGN(num_bytes, sizeof(int));
279 num_ints = num_bytes - sizeof(native_handle_t) - num_fds;
281 * Malloc is used as handles are ultimately destroyed via free in
282 * native_handle_delete().
284 hnd = static_cast<struct cros_gralloc_handle *>(malloc(num_bytes));
285 hnd->base.version = sizeof(hnd->base);
286 hnd->base.numFds = num_fds;
287 hnd->base.numInts = num_ints;
288 hnd->num_planes = num_planes;
289 for (size_t plane = 0; plane < num_planes; plane++) {
290 hnd->fds[plane] = drv_bo_get_plane_fd(bo, plane);
291 hnd->strides[plane] = drv_bo_get_plane_stride(bo, plane);
292 hnd->offsets[plane] = drv_bo_get_plane_offset(bo, plane);
293 hnd->sizes[plane] = drv_bo_get_plane_size(bo, plane);
295 hnd->fds[hnd->num_planes] = reserved_region_fd;
296 hnd->reserved_region_size = descriptor->reserved_region_size;
297 static std::atomic<uint32_t> next_buffer_id{ 1 };
298 hnd->id = next_buffer_id++;
299 hnd->width = drv_bo_get_width(bo);
300 hnd->height = drv_bo_get_height(bo);
301 hnd->format = drv_bo_get_format(bo);
302 hnd->tiling = bo->meta.tiling;
303 hnd->format_modifier = drv_bo_get_plane_format_modifier(bo, 0);
304 hnd->use_flags = descriptor->use_flags;
305 bytes_per_pixel = drv_bytes_per_pixel_from_format(hnd->format, 0);
306 hnd->pixel_stride = DIV_ROUND_UP(hnd->strides[0], bytes_per_pixel);
307 hnd->magic = cros_gralloc_magic;
308 hnd->droid_format = descriptor->droid_format;
309 hnd->usage = descriptor->droid_usage;
310 hnd->total_size = descriptor->reserved_region_size + bo->meta.total_size;
311 hnd->name_offset = handle_data_size;
313 name = (char *)(&hnd->base.data[hnd->name_offset]);
314 snprintf(name, descriptor->name.size() + 1, "%s", descriptor->name.c_str());
317 auto buffer = new cros_gralloc_buffer(id, bo, hnd, hnd->fds[hnd->num_planes],
318 hnd->reserved_region_size);
320 std::lock_guard<std::mutex> lock(mutex_);
321 buffers_.emplace(id, buffer);
322 handles_.emplace(hnd, std::make_pair(buffer, 1));
323 *out_handle = reinterpret_cast<buffer_handle_t>(hnd);
327 int32_t cros_gralloc_driver::retain(buffer_handle_t handle)
330 std::lock_guard<std::mutex> lock(mutex_);
332 auto hnd = cros_gralloc_convert_handle(handle);
334 drv_log("Invalid handle.\n");
338 auto buffer = get_buffer(hnd);
340 handles_[hnd].second++;
341 buffer->increase_refcount();
347 if (buffers_.count(id)) {
348 buffer = buffers_[id];
349 buffer->increase_refcount();
352 struct drv_import_fd_data data;
353 data.format = hnd->format;
354 data.tiling = hnd->tiling;
356 data.width = hnd->width;
357 data.height = hnd->height;
358 data.use_flags = hnd->use_flags;
360 memcpy(data.fds, hnd->fds, sizeof(data.fds));
361 memcpy(data.strides, hnd->strides, sizeof(data.strides));
362 memcpy(data.offsets, hnd->offsets, sizeof(data.offsets));
363 for (uint32_t plane = 0; plane < DRV_MAX_PLANES; plane++) {
364 data.format_modifiers[plane] = hnd->format_modifier;
367 bo = drv_bo_import(drv_, &data);
371 buffer = new cros_gralloc_buffer(id, bo, nullptr, hnd->fds[hnd->num_planes],
372 hnd->reserved_region_size);
373 buffers_.emplace(id, buffer);
376 handles_.emplace(hnd, std::make_pair(buffer, 1));
380 int32_t cros_gralloc_driver::release(buffer_handle_t handle)
382 std::lock_guard<std::mutex> lock(mutex_);
384 auto hnd = cros_gralloc_convert_handle(handle);
386 drv_log("Invalid handle.\n");
390 auto buffer = get_buffer(hnd);
392 drv_log("Invalid Reference.\n");
396 if (!--handles_[hnd].second)
399 if (buffer->decrease_refcount() == 0) {
400 buffers_.erase(buffer->get_id());
407 int32_t cros_gralloc_driver::lock(buffer_handle_t handle, int32_t acquire_fence,
408 bool close_acquire_fence, const struct rectangle *rect,
409 uint32_t map_flags, uint8_t *addr[DRV_MAX_PLANES])
411 int32_t ret = cros_gralloc_sync_wait(acquire_fence, close_acquire_fence);
415 std::lock_guard<std::mutex> lock(mutex_);
416 auto hnd = cros_gralloc_convert_handle(handle);
418 drv_log("Invalid handle.\n");
422 auto buffer = get_buffer(hnd);
424 drv_log("Invalid Reference.\n");
428 return buffer->lock(rect, map_flags, addr);
431 int32_t cros_gralloc_driver::unlock(buffer_handle_t handle, int32_t *release_fence)
433 std::lock_guard<std::mutex> lock(mutex_);
435 auto hnd = cros_gralloc_convert_handle(handle);
437 drv_log("Invalid handle.\n");
441 auto buffer = get_buffer(hnd);
443 drv_log("Invalid Reference.\n");
448 * From the ANativeWindow::dequeueBuffer documentation:
450 * "A value of -1 indicates that the caller may access the buffer immediately without
451 * waiting on a fence."
454 return buffer->unlock();
457 int32_t cros_gralloc_driver::invalidate(buffer_handle_t handle)
459 std::lock_guard<std::mutex> lock(mutex_);
461 auto hnd = cros_gralloc_convert_handle(handle);
463 drv_log("Invalid handle.\n");
467 auto buffer = get_buffer(hnd);
469 drv_log("Invalid Reference.\n");
473 return buffer->invalidate();
476 int32_t cros_gralloc_driver::flush(buffer_handle_t handle, int32_t *release_fence)
478 std::lock_guard<std::mutex> lock(mutex_);
480 auto hnd = cros_gralloc_convert_handle(handle);
482 drv_log("Invalid handle.\n");
486 auto buffer = get_buffer(hnd);
488 drv_log("Invalid Reference.\n");
493 * From the ANativeWindow::dequeueBuffer documentation:
495 * "A value of -1 indicates that the caller may access the buffer immediately without
496 * waiting on a fence."
499 return buffer->flush();
502 int32_t cros_gralloc_driver::get_backing_store(buffer_handle_t handle, uint64_t *out_store)
504 std::lock_guard<std::mutex> lock(mutex_);
506 auto hnd = cros_gralloc_convert_handle(handle);
508 drv_log("Invalid handle.\n");
512 auto buffer = get_buffer(hnd);
514 drv_log("Invalid Reference.\n");
518 *out_store = static_cast<uint64_t>(buffer->get_id());
522 int32_t cros_gralloc_driver::resource_info(buffer_handle_t handle, uint32_t strides[DRV_MAX_PLANES],
523 uint32_t offsets[DRV_MAX_PLANES])
525 std::lock_guard<std::mutex> lock(mutex_);
527 auto hnd = cros_gralloc_convert_handle(handle);
529 drv_log("Invalid handle.\n");
533 auto buffer = get_buffer(hnd);
535 drv_log("Invalid Reference.\n");
539 return buffer->resource_info(strides, offsets);
542 int32_t cros_gralloc_driver::get_reserved_region(buffer_handle_t handle,
543 void **reserved_region_addr,
544 uint64_t *reserved_region_size)
546 std::lock_guard<std::mutex> lock(mutex_);
548 auto hnd = cros_gralloc_convert_handle(handle);
550 drv_log("Invalid handle.\n");
554 auto buffer = get_buffer(hnd);
556 drv_log("Invalid Reference.\n");
560 return buffer->get_reserved_region(reserved_region_addr, reserved_region_size);
563 uint32_t cros_gralloc_driver::get_resolved_drm_format(uint32_t drm_format, uint64_t usage)
565 return drv_resolve_format(drv_, drm_format, usage);
568 cros_gralloc_buffer *cros_gralloc_driver::get_buffer(cros_gralloc_handle_t hnd)
570 /* Assumes driver mutex is held. */
571 if (handles_.count(hnd))
572 return handles_[hnd].first;
577 void cros_gralloc_driver::for_each_handle(
578 const std::function<void(cros_gralloc_handle_t)> &function)
580 std::lock_guard<std::mutex> lock(mutex_);
582 for (const auto &pair : handles_) {
583 function(pair.first);