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 "../drv_priv.h"
15 #include "../helpers.h"
18 cros_gralloc_driver::cros_gralloc_driver() : drv_(nullptr)
22 cros_gralloc_driver::~cros_gralloc_driver()
28 int fd = drv_get_fd(drv_);
35 int32_t cros_gralloc_driver::init()
38 * Create a driver from rendernode while filtering out
39 * the specified undesired driver.
41 * TODO(gsingh): Enable render nodes on udl/evdi.
45 drmVersionPtr version;
46 char const *str = "%s/renderD%d";
47 const char *undesired[2] = { "vgem", nullptr };
48 uint32_t num_nodes = 63;
49 uint32_t min_node = 128;
50 uint32_t max_node = (min_node + num_nodes);
52 for (uint32_t i = 0; i < ARRAY_SIZE(undesired); i++) {
53 for (uint32_t j = min_node; j < max_node; j++) {
55 if (asprintf(&node, str, DRM_DIR_NAME, j) < 0)
58 fd = open(node, O_RDWR | O_CLOEXEC);
64 version = drmGetVersion(fd);
70 if (undesired[i] && !strcmp(version->name, undesired[i])) {
72 drmFreeVersion(version);
76 drmFreeVersion(version);
77 drv_ = drv_create(fd);
88 bool cros_gralloc_driver::is_supported(const struct cros_gralloc_buffer_descriptor *descriptor)
90 struct combination *combo;
91 uint32_t resolved_format;
92 resolved_format = drv_resolve_format(drv_, descriptor->drm_format, descriptor->use_flags);
93 combo = drv_get_combination(drv_, resolved_format, descriptor->use_flags);
94 return (combo != nullptr);
97 int32_t create_reserved_region(const std::string &buffer_name, uint64_t reserved_region_size)
99 std::string reserved_region_name = buffer_name + " reserved region";
101 #ifdef __NR_memfd_create
102 int32_t reserved_region_fd = memfd_create(reserved_region_name.c_str(), FD_CLOEXEC);
103 if (reserved_region_fd == -1) {
104 drv_log("Failed to create reserved region fd: %s.\n", strerror(errno));
108 if (ftruncate(reserved_region_fd, reserved_region_size)) {
109 drv_log("Failed to set reserved region size: %s.\n", strerror(errno));
113 return reserved_region_fd;
115 drv_log("Failed to create reserved region '%s': memfd_create not available.",
116 reserved_region_name.c_str());
121 int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descriptor *descriptor,
122 buffer_handle_t *out_handle)
129 uint32_t resolved_format;
130 uint32_t bytes_per_pixel;
132 int32_t reserved_region_fd;
136 struct cros_gralloc_handle *hnd;
138 resolved_format = drv_resolve_format(drv_, descriptor->drm_format, descriptor->use_flags);
139 use_flags = descriptor->use_flags;
141 * TODO(b/79682290): ARC++ assumes NV12 is always linear and doesn't
142 * send modifiers across Wayland protocol, so we or in the
143 * BO_USE_LINEAR flag here. We need to fix ARC++ to allocate and work
144 * with tiled buffers.
146 if (resolved_format == DRM_FORMAT_NV12)
147 use_flags |= BO_USE_LINEAR;
150 * This unmask is a backup in the case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED is resolved
151 * to non-YUV formats.
153 if (descriptor->drm_format == DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED &&
154 (resolved_format == DRM_FORMAT_XBGR8888 || resolved_format == DRM_FORMAT_ABGR8888)) {
155 use_flags &= ~BO_USE_HW_VIDEO_ENCODER;
158 bo = drv_bo_create(drv_, descriptor->width, descriptor->height, resolved_format, use_flags);
160 drv_log("Failed to create bo.\n");
165 * If there is a desire for more than one kernel buffer, this can be
166 * removed once the ArcCodec and Wayland service have the ability to
167 * send more than one fd. GL/Vulkan drivers may also have to modified.
169 if (drv_num_buffers_per_bo(bo) != 1) {
171 drv_log("Can only support one buffer per bo.\n");
175 num_planes = drv_bo_get_num_planes(bo);
176 num_fds = num_planes;
178 if (descriptor->reserved_region_size > 0) {
180 create_reserved_region(descriptor->name, descriptor->reserved_region_size);
181 if (reserved_region_fd < 0) {
183 return reserved_region_fd;
187 reserved_region_fd = -1;
190 num_bytes = sizeof(struct cros_gralloc_handle);
191 num_bytes += (descriptor->name.size() + 1);
193 * Ensure that the total number of bytes is a multiple of sizeof(int) as
194 * native_handle_clone() copies data based on hnd->base.numInts.
196 num_bytes = ALIGN(num_bytes, sizeof(int));
197 num_ints = num_bytes - sizeof(native_handle_t) - num_fds;
199 * Malloc is used as handles are ultimately destroyed via free in
200 * native_handle_delete().
202 hnd = static_cast<struct cros_gralloc_handle *>(malloc(num_bytes));
203 hnd->base.version = sizeof(hnd->base);
204 hnd->base.numFds = num_fds;
205 hnd->base.numInts = num_ints;
206 hnd->num_planes = num_planes;
207 for (size_t plane = 0; plane < num_planes; plane++) {
208 hnd->fds[plane] = drv_bo_get_plane_fd(bo, plane);
209 hnd->strides[plane] = drv_bo_get_plane_stride(bo, plane);
210 hnd->offsets[plane] = drv_bo_get_plane_offset(bo, plane);
211 hnd->sizes[plane] = drv_bo_get_plane_size(bo, plane);
213 hnd->fds[hnd->num_planes] = reserved_region_fd;
214 hnd->reserved_region_size = descriptor->reserved_region_size;
215 static std::atomic<uint32_t> next_buffer_id{ 1 };
216 hnd->id = next_buffer_id++;
217 hnd->width = drv_bo_get_width(bo);
218 hnd->height = drv_bo_get_height(bo);
219 hnd->format = drv_bo_get_format(bo);
220 hnd->tiling = bo->meta.tiling;
221 hnd->format_modifier = drv_bo_get_plane_format_modifier(bo, 0);
222 hnd->use_flags = descriptor->use_flags;
223 bytes_per_pixel = drv_bytes_per_pixel_from_format(hnd->format, 0);
224 hnd->pixel_stride = DIV_ROUND_UP(hnd->strides[0], bytes_per_pixel);
225 hnd->magic = cros_gralloc_magic;
226 hnd->droid_format = descriptor->droid_format;
227 hnd->usage = descriptor->droid_usage;
228 hnd->total_size = descriptor->reserved_region_size + bo->meta.total_size;
229 hnd->name_offset = handle_data_size;
231 name = (char *)(&hnd->base.data[hnd->name_offset]);
232 snprintf(name, descriptor->name.size() + 1, "%s", descriptor->name.c_str());
234 id = drv_bo_get_plane_handle(bo, 0).u32;
235 auto buffer = new cros_gralloc_buffer(id, bo, hnd, hnd->fds[hnd->num_planes],
236 hnd->reserved_region_size);
238 std::lock_guard<std::mutex> lock(mutex_);
239 buffers_.emplace(id, buffer);
240 handles_.emplace(hnd, std::make_pair(buffer, 1));
241 *out_handle = reinterpret_cast<buffer_handle_t>(hnd);
245 int32_t cros_gralloc_driver::retain(buffer_handle_t handle)
248 std::lock_guard<std::mutex> lock(mutex_);
250 auto hnd = cros_gralloc_convert_handle(handle);
252 drv_log("Invalid handle.\n");
256 auto buffer = get_buffer(hnd);
258 handles_[hnd].second++;
259 buffer->increase_refcount();
263 if (drmPrimeFDToHandle(drv_get_fd(drv_), hnd->fds[0], &id)) {
264 drv_log("drmPrimeFDToHandle failed.\n");
268 if (buffers_.count(id)) {
269 buffer = buffers_[id];
270 buffer->increase_refcount();
273 struct drv_import_fd_data data;
274 data.format = hnd->format;
275 data.tiling = hnd->tiling;
277 data.width = hnd->width;
278 data.height = hnd->height;
279 data.use_flags = hnd->use_flags;
281 memcpy(data.fds, hnd->fds, sizeof(data.fds));
282 memcpy(data.strides, hnd->strides, sizeof(data.strides));
283 memcpy(data.offsets, hnd->offsets, sizeof(data.offsets));
284 for (uint32_t plane = 0; plane < DRV_MAX_PLANES; plane++) {
285 data.format_modifiers[plane] = hnd->format_modifier;
288 bo = drv_bo_import(drv_, &data);
292 id = drv_bo_get_plane_handle(bo, 0).u32;
294 buffer = new cros_gralloc_buffer(id, bo, nullptr, hnd->fds[hnd->num_planes],
295 hnd->reserved_region_size);
296 buffers_.emplace(id, buffer);
299 handles_.emplace(hnd, std::make_pair(buffer, 1));
303 int32_t cros_gralloc_driver::release(buffer_handle_t handle)
305 std::lock_guard<std::mutex> lock(mutex_);
307 auto hnd = cros_gralloc_convert_handle(handle);
309 drv_log("Invalid handle.\n");
313 auto buffer = get_buffer(hnd);
315 drv_log("Invalid Reference.\n");
319 if (!--handles_[hnd].second)
322 if (buffer->decrease_refcount() == 0) {
323 buffers_.erase(buffer->get_id());
330 int32_t cros_gralloc_driver::lock(buffer_handle_t handle, int32_t acquire_fence,
331 bool close_acquire_fence, const struct rectangle *rect,
332 uint32_t map_flags, uint8_t *addr[DRV_MAX_PLANES])
334 int32_t ret = cros_gralloc_sync_wait(acquire_fence, close_acquire_fence);
338 std::lock_guard<std::mutex> lock(mutex_);
339 auto hnd = cros_gralloc_convert_handle(handle);
341 drv_log("Invalid handle.\n");
345 auto buffer = get_buffer(hnd);
347 drv_log("Invalid Reference.\n");
351 return buffer->lock(rect, map_flags, addr);
354 int32_t cros_gralloc_driver::unlock(buffer_handle_t handle, int32_t *release_fence)
356 std::lock_guard<std::mutex> lock(mutex_);
358 auto hnd = cros_gralloc_convert_handle(handle);
360 drv_log("Invalid handle.\n");
364 auto buffer = get_buffer(hnd);
366 drv_log("Invalid Reference.\n");
371 * From the ANativeWindow::dequeueBuffer documentation:
373 * "A value of -1 indicates that the caller may access the buffer immediately without
374 * waiting on a fence."
377 return buffer->unlock();
380 int32_t cros_gralloc_driver::invalidate(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 return buffer->invalidate();
399 int32_t cros_gralloc_driver::flush(buffer_handle_t handle, int32_t *release_fence)
401 std::lock_guard<std::mutex> lock(mutex_);
403 auto hnd = cros_gralloc_convert_handle(handle);
405 drv_log("Invalid handle.\n");
409 auto buffer = get_buffer(hnd);
411 drv_log("Invalid Reference.\n");
416 * From the ANativeWindow::dequeueBuffer documentation:
418 * "A value of -1 indicates that the caller may access the buffer immediately without
419 * waiting on a fence."
422 return buffer->flush();
425 int32_t cros_gralloc_driver::get_backing_store(buffer_handle_t handle, uint64_t *out_store)
427 std::lock_guard<std::mutex> lock(mutex_);
429 auto hnd = cros_gralloc_convert_handle(handle);
431 drv_log("Invalid handle.\n");
435 auto buffer = get_buffer(hnd);
437 drv_log("Invalid Reference.\n");
441 *out_store = static_cast<uint64_t>(buffer->get_id());
445 int32_t cros_gralloc_driver::resource_info(buffer_handle_t handle, uint32_t strides[DRV_MAX_PLANES],
446 uint32_t offsets[DRV_MAX_PLANES])
448 std::lock_guard<std::mutex> lock(mutex_);
450 auto hnd = cros_gralloc_convert_handle(handle);
452 drv_log("Invalid handle.\n");
456 auto buffer = get_buffer(hnd);
458 drv_log("Invalid Reference.\n");
462 return buffer->resource_info(strides, offsets);
465 int32_t cros_gralloc_driver::get_reserved_region(buffer_handle_t handle,
466 void **reserved_region_addr,
467 uint64_t *reserved_region_size)
469 std::lock_guard<std::mutex> lock(mutex_);
471 auto hnd = cros_gralloc_convert_handle(handle);
473 drv_log("Invalid handle.\n");
477 auto buffer = get_buffer(hnd);
479 drv_log("Invalid Reference.\n");
483 return buffer->get_reserved_region(reserved_region_addr, reserved_region_size);
486 uint32_t cros_gralloc_driver::get_resolved_drm_format(uint32_t drm_format, uint64_t usage)
488 return drv_resolve_format(drv_, drm_format, usage);
491 cros_gralloc_buffer *cros_gralloc_driver::get_buffer(cros_gralloc_handle_t hnd)
493 /* Assumes driver mutex is held. */
494 if (handles_.count(hnd))
495 return handles_[hnd].first;
500 void cros_gralloc_driver::for_each_handle(
501 const std::function<void(cros_gralloc_handle_t)> &function)
503 std::lock_guard<std::mutex> lock(mutex_);
505 for (const auto &pair : handles_) {
506 function(pair.first);