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"
15 #include "../drv_priv.h"
16 #include "../helpers.h"
19 int memfd_create_wrapper(const char *name, unsigned int flags)
23 #if defined(HAVE_MEMFD_CREATE)
24 fd = memfd_create(name, flags);
25 #elif defined(__NR_memfd_create)
26 fd = syscall(__NR_memfd_create, name, flags);
28 drv_log("Failed to create memfd '%s': memfd_create not available.", name);
33 drv_log("Failed to create memfd '%s': %s.\n", name, strerror(errno));
38 cros_gralloc_driver::cros_gralloc_driver() : drv_(nullptr)
42 cros_gralloc_driver::~cros_gralloc_driver()
48 int fd = drv_get_fd(drv_);
55 int32_t cros_gralloc_driver::init()
58 * Create a driver from rendernode while filtering out
59 * the specified undesired driver.
61 * TODO(gsingh): Enable render nodes on udl/evdi.
65 drmVersionPtr version;
66 char const *str = "%s/renderD%d";
67 const char *undesired[2] = { "vgem", nullptr };
68 uint32_t num_nodes = 63;
69 uint32_t min_node = 128;
70 uint32_t max_node = (min_node + num_nodes);
72 for (uint32_t i = 0; i < ARRAY_SIZE(undesired); i++) {
73 for (uint32_t j = min_node; j < max_node; j++) {
75 if (asprintf(&node, str, DRM_DIR_NAME, j) < 0)
78 fd = open(node, O_RDWR | O_CLOEXEC);
84 version = drmGetVersion(fd);
90 if (undesired[i] && !strcmp(version->name, undesired[i])) {
92 drmFreeVersion(version);
96 drmFreeVersion(version);
97 drv_ = drv_create(fd);
108 bool cros_gralloc_driver::is_supported(const struct cros_gralloc_buffer_descriptor *descriptor)
110 struct combination *combo;
111 uint32_t resolved_format;
112 resolved_format = drv_resolve_format(drv_, descriptor->drm_format, descriptor->use_flags);
113 combo = drv_get_combination(drv_, resolved_format, descriptor->use_flags);
114 return (combo != nullptr);
117 int32_t create_reserved_region(const std::string &buffer_name, uint64_t reserved_region_size)
119 std::string reserved_region_name = buffer_name + " reserved region";
121 int32_t reserved_region_fd = memfd_create_wrapper(reserved_region_name.c_str(), FD_CLOEXEC);
122 if (reserved_region_fd == -1) {
126 if (ftruncate(reserved_region_fd, reserved_region_size)) {
127 drv_log("Failed to set reserved region size: %s.\n", strerror(errno));
131 return reserved_region_fd;
134 int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descriptor *descriptor,
135 buffer_handle_t *out_handle)
142 uint32_t resolved_format;
143 uint32_t bytes_per_pixel;
145 int32_t reserved_region_fd;
149 struct cros_gralloc_handle *hnd;
151 resolved_format = drv_resolve_format(drv_, descriptor->drm_format, descriptor->use_flags);
152 use_flags = descriptor->use_flags;
154 * TODO(b/79682290): ARC++ assumes NV12 is always linear and doesn't
155 * send modifiers across Wayland protocol, so we or in the
156 * BO_USE_LINEAR flag here. We need to fix ARC++ to allocate and work
157 * with tiled buffers.
159 if (resolved_format == DRM_FORMAT_NV12)
160 use_flags |= BO_USE_LINEAR;
163 * This unmask is a backup in the case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED is resolved
164 * to non-YUV formats.
166 if (descriptor->drm_format == DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED &&
167 (resolved_format == DRM_FORMAT_XBGR8888 || resolved_format == DRM_FORMAT_ABGR8888)) {
168 use_flags &= ~BO_USE_HW_VIDEO_ENCODER;
171 bo = drv_bo_create(drv_, descriptor->width, descriptor->height, resolved_format, use_flags);
173 drv_log("Failed to create bo.\n");
178 * If there is a desire for more than one kernel buffer, this can be
179 * removed once the ArcCodec and Wayland service have the ability to
180 * send more than one fd. GL/Vulkan drivers may also have to modified.
182 if (drv_num_buffers_per_bo(bo) != 1) {
184 drv_log("Can only support one buffer per bo.\n");
188 num_planes = drv_bo_get_num_planes(bo);
189 num_fds = num_planes;
191 if (descriptor->reserved_region_size > 0) {
193 create_reserved_region(descriptor->name, descriptor->reserved_region_size);
194 if (reserved_region_fd < 0) {
196 return reserved_region_fd;
200 reserved_region_fd = -1;
203 num_bytes = sizeof(struct cros_gralloc_handle);
204 num_bytes += (descriptor->name.size() + 1);
206 * Ensure that the total number of bytes is a multiple of sizeof(int) as
207 * native_handle_clone() copies data based on hnd->base.numInts.
209 num_bytes = ALIGN(num_bytes, sizeof(int));
210 num_ints = num_bytes - sizeof(native_handle_t) - num_fds;
212 * Malloc is used as handles are ultimately destroyed via free in
213 * native_handle_delete().
215 hnd = static_cast<struct cros_gralloc_handle *>(malloc(num_bytes));
216 hnd->base.version = sizeof(hnd->base);
217 hnd->base.numFds = num_fds;
218 hnd->base.numInts = num_ints;
219 hnd->num_planes = num_planes;
220 for (size_t plane = 0; plane < num_planes; plane++) {
221 hnd->fds[plane] = drv_bo_get_plane_fd(bo, plane);
222 hnd->strides[plane] = drv_bo_get_plane_stride(bo, plane);
223 hnd->offsets[plane] = drv_bo_get_plane_offset(bo, plane);
224 hnd->sizes[plane] = drv_bo_get_plane_size(bo, plane);
226 hnd->fds[hnd->num_planes] = reserved_region_fd;
227 hnd->reserved_region_size = descriptor->reserved_region_size;
228 static std::atomic<uint32_t> next_buffer_id{ 1 };
229 hnd->id = next_buffer_id++;
230 hnd->width = drv_bo_get_width(bo);
231 hnd->height = drv_bo_get_height(bo);
232 hnd->format = drv_bo_get_format(bo);
233 hnd->tiling = bo->meta.tiling;
234 hnd->format_modifier = drv_bo_get_plane_format_modifier(bo, 0);
235 hnd->use_flags = descriptor->use_flags;
236 bytes_per_pixel = drv_bytes_per_pixel_from_format(hnd->format, 0);
237 hnd->pixel_stride = DIV_ROUND_UP(hnd->strides[0], bytes_per_pixel);
238 hnd->magic = cros_gralloc_magic;
239 hnd->droid_format = descriptor->droid_format;
240 hnd->usage = descriptor->droid_usage;
241 hnd->total_size = descriptor->reserved_region_size + bo->meta.total_size;
242 hnd->name_offset = handle_data_size;
244 name = (char *)(&hnd->base.data[hnd->name_offset]);
245 snprintf(name, descriptor->name.size() + 1, "%s", descriptor->name.c_str());
247 id = drv_bo_get_plane_handle(bo, 0).u32;
248 auto buffer = new cros_gralloc_buffer(id, bo, hnd, hnd->fds[hnd->num_planes],
249 hnd->reserved_region_size);
251 std::lock_guard<std::mutex> lock(mutex_);
252 buffers_.emplace(id, buffer);
253 handles_.emplace(hnd, std::make_pair(buffer, 1));
254 *out_handle = reinterpret_cast<buffer_handle_t>(hnd);
258 int32_t cros_gralloc_driver::retain(buffer_handle_t handle)
261 std::lock_guard<std::mutex> lock(mutex_);
263 auto hnd = cros_gralloc_convert_handle(handle);
265 drv_log("Invalid handle.\n");
269 auto buffer = get_buffer(hnd);
271 handles_[hnd].second++;
272 buffer->increase_refcount();
276 if (drmPrimeFDToHandle(drv_get_fd(drv_), hnd->fds[0], &id)) {
277 drv_log("drmPrimeFDToHandle failed.\n");
281 if (buffers_.count(id)) {
282 buffer = buffers_[id];
283 buffer->increase_refcount();
286 struct drv_import_fd_data data;
287 data.format = hnd->format;
288 data.tiling = hnd->tiling;
290 data.width = hnd->width;
291 data.height = hnd->height;
292 data.use_flags = hnd->use_flags;
294 memcpy(data.fds, hnd->fds, sizeof(data.fds));
295 memcpy(data.strides, hnd->strides, sizeof(data.strides));
296 memcpy(data.offsets, hnd->offsets, sizeof(data.offsets));
297 for (uint32_t plane = 0; plane < DRV_MAX_PLANES; plane++) {
298 data.format_modifiers[plane] = hnd->format_modifier;
301 bo = drv_bo_import(drv_, &data);
305 id = drv_bo_get_plane_handle(bo, 0).u32;
307 buffer = new cros_gralloc_buffer(id, bo, nullptr, hnd->fds[hnd->num_planes],
308 hnd->reserved_region_size);
309 buffers_.emplace(id, buffer);
312 handles_.emplace(hnd, std::make_pair(buffer, 1));
316 int32_t cros_gralloc_driver::release(buffer_handle_t handle)
318 std::lock_guard<std::mutex> lock(mutex_);
320 auto hnd = cros_gralloc_convert_handle(handle);
322 drv_log("Invalid handle.\n");
326 auto buffer = get_buffer(hnd);
328 drv_log("Invalid Reference.\n");
332 if (!--handles_[hnd].second)
335 if (buffer->decrease_refcount() == 0) {
336 buffers_.erase(buffer->get_id());
343 int32_t cros_gralloc_driver::lock(buffer_handle_t handle, int32_t acquire_fence,
344 bool close_acquire_fence, const struct rectangle *rect,
345 uint32_t map_flags, uint8_t *addr[DRV_MAX_PLANES])
347 int32_t ret = cros_gralloc_sync_wait(acquire_fence, close_acquire_fence);
351 std::lock_guard<std::mutex> lock(mutex_);
352 auto hnd = cros_gralloc_convert_handle(handle);
354 drv_log("Invalid handle.\n");
358 auto buffer = get_buffer(hnd);
360 drv_log("Invalid Reference.\n");
364 return buffer->lock(rect, map_flags, addr);
367 int32_t cros_gralloc_driver::unlock(buffer_handle_t handle, int32_t *release_fence)
369 std::lock_guard<std::mutex> lock(mutex_);
371 auto hnd = cros_gralloc_convert_handle(handle);
373 drv_log("Invalid handle.\n");
377 auto buffer = get_buffer(hnd);
379 drv_log("Invalid Reference.\n");
384 * From the ANativeWindow::dequeueBuffer documentation:
386 * "A value of -1 indicates that the caller may access the buffer immediately without
387 * waiting on a fence."
390 return buffer->unlock();
393 int32_t cros_gralloc_driver::invalidate(buffer_handle_t handle)
395 std::lock_guard<std::mutex> lock(mutex_);
397 auto hnd = cros_gralloc_convert_handle(handle);
399 drv_log("Invalid handle.\n");
403 auto buffer = get_buffer(hnd);
405 drv_log("Invalid Reference.\n");
409 return buffer->invalidate();
412 int32_t cros_gralloc_driver::flush(buffer_handle_t handle, int32_t *release_fence)
414 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");
429 * From the ANativeWindow::dequeueBuffer documentation:
431 * "A value of -1 indicates that the caller may access the buffer immediately without
432 * waiting on a fence."
435 return buffer->flush();
438 int32_t cros_gralloc_driver::get_backing_store(buffer_handle_t handle, uint64_t *out_store)
440 std::lock_guard<std::mutex> lock(mutex_);
442 auto hnd = cros_gralloc_convert_handle(handle);
444 drv_log("Invalid handle.\n");
448 auto buffer = get_buffer(hnd);
450 drv_log("Invalid Reference.\n");
454 *out_store = static_cast<uint64_t>(buffer->get_id());
458 int32_t cros_gralloc_driver::resource_info(buffer_handle_t handle, uint32_t strides[DRV_MAX_PLANES],
459 uint32_t offsets[DRV_MAX_PLANES])
461 std::lock_guard<std::mutex> lock(mutex_);
463 auto hnd = cros_gralloc_convert_handle(handle);
465 drv_log("Invalid handle.\n");
469 auto buffer = get_buffer(hnd);
471 drv_log("Invalid Reference.\n");
475 return buffer->resource_info(strides, offsets);
478 int32_t cros_gralloc_driver::get_reserved_region(buffer_handle_t handle,
479 void **reserved_region_addr,
480 uint64_t *reserved_region_size)
482 std::lock_guard<std::mutex> lock(mutex_);
484 auto hnd = cros_gralloc_convert_handle(handle);
486 drv_log("Invalid handle.\n");
490 auto buffer = get_buffer(hnd);
492 drv_log("Invalid Reference.\n");
496 return buffer->get_reserved_region(reserved_region_addr, reserved_region_size);
499 uint32_t cros_gralloc_driver::get_resolved_drm_format(uint32_t drm_format, uint64_t usage)
501 return drv_resolve_format(drv_, drm_format, usage);
504 cros_gralloc_buffer *cros_gralloc_driver::get_buffer(cros_gralloc_handle_t hnd)
506 /* Assumes driver mutex is held. */
507 if (handles_.count(hnd))
508 return handles_[hnd].first;
513 void cros_gralloc_driver::for_each_handle(
514 const std::function<void(cros_gralloc_handle_t)> &function)
516 std::lock_guard<std::mutex> lock(mutex_);
518 for (const auto &pair : handles_) {
519 function(pair.first);