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, 0);
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 int32_t reserved_region_fd;
100 std::string reserved_region_name = buffer_name + " reserved region";
102 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;
116 int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descriptor *descriptor,
117 buffer_handle_t *out_handle)
124 uint32_t resolved_format;
125 uint32_t bytes_per_pixel;
127 int32_t reserved_region_fd;
131 struct cros_gralloc_handle *hnd;
133 resolved_format = drv_resolve_format(drv_, descriptor->drm_format, descriptor->use_flags);
134 use_flags = descriptor->use_flags;
136 * TODO(b/79682290): ARC++ assumes NV12 is always linear and doesn't
137 * send modifiers across Wayland protocol, so we or in the
138 * BO_USE_LINEAR flag here. We need to fix ARC++ to allocate and work
139 * with tiled buffers.
141 if (resolved_format == DRM_FORMAT_NV12)
142 use_flags |= BO_USE_LINEAR;
145 * This unmask is a backup in the case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED is resolved
146 * to non-YUV formats.
148 if (descriptor->drm_format == DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED &&
149 (resolved_format == DRM_FORMAT_XBGR8888 || resolved_format == DRM_FORMAT_ABGR8888)) {
150 use_flags &= ~BO_USE_HW_VIDEO_ENCODER;
153 bo = drv_bo_create(drv_, descriptor->width, descriptor->height, resolved_format, use_flags);
155 drv_log("Failed to create bo.\n");
160 * If there is a desire for more than one kernel buffer, this can be
161 * removed once the ArcCodec and Wayland service have the ability to
162 * send more than one fd. GL/Vulkan drivers may also have to modified.
164 if (drv_num_buffers_per_bo(bo) != 1) {
166 drv_log("Can only support one buffer per bo.\n");
170 num_planes = drv_bo_get_num_planes(bo);
171 num_fds = num_planes;
173 if (descriptor->reserved_region_size > 0) {
175 create_reserved_region(descriptor->name, descriptor->reserved_region_size);
176 if (reserved_region_fd < 0) {
178 return reserved_region_fd;
182 reserved_region_fd = -1;
185 num_bytes = sizeof(struct cros_gralloc_handle);
186 num_bytes += (descriptor->name.size() + 1);
188 * Ensure that the total number of bytes is a multiple of sizeof(int) as
189 * native_handle_clone() copies data based on hnd->base.numInts.
191 num_bytes = ALIGN(num_bytes, sizeof(int));
192 num_ints = num_bytes - sizeof(native_handle_t) - num_fds;
194 * Malloc is used as handles are ultimetly destroyed via free in
195 * native_handle_delete().
197 hnd = static_cast<struct cros_gralloc_handle *>(malloc(num_bytes));
198 hnd->base.version = sizeof(hnd->base);
199 hnd->base.numFds = num_fds;
200 hnd->base.numInts = num_ints;
201 hnd->num_planes = num_planes;
202 for (size_t plane = 0; plane < num_planes; plane++) {
203 hnd->fds[plane] = drv_bo_get_plane_fd(bo, plane);
204 hnd->strides[plane] = drv_bo_get_plane_stride(bo, plane);
205 hnd->offsets[plane] = drv_bo_get_plane_offset(bo, plane);
206 hnd->sizes[plane] = drv_bo_get_plane_size(bo, plane);
208 hnd->fds[hnd->num_planes] = reserved_region_fd;
209 hnd->reserved_region_size = descriptor->reserved_region_size;
210 static std::atomic<uint32_t> next_buffer_id{ 1 };
211 hnd->id = next_buffer_id++;
212 hnd->width = drv_bo_get_width(bo);
213 hnd->height = drv_bo_get_height(bo);
214 hnd->format = drv_bo_get_format(bo);
215 hnd->format_modifier = drv_bo_get_plane_format_modifier(bo, 0);
216 hnd->use_flags = descriptor->use_flags;
217 bytes_per_pixel = drv_bytes_per_pixel_from_format(hnd->format, 0);
218 hnd->pixel_stride = DIV_ROUND_UP(hnd->strides[0], bytes_per_pixel);
219 hnd->magic = cros_gralloc_magic;
220 hnd->droid_format = descriptor->droid_format;
221 hnd->usage = descriptor->droid_usage;
222 hnd->total_size = descriptor->reserved_region_size + bo->meta.total_size;
223 hnd->name_offset = handle_data_size;
225 name = (char *)(&hnd->base.data[hnd->name_offset]);
226 snprintf(name, descriptor->name.size() + 1, "%s", descriptor->name.c_str());
228 id = drv_bo_get_plane_handle(bo, 0).u32;
229 auto buffer = new cros_gralloc_buffer(id, bo, hnd, hnd->fds[hnd->num_planes],
230 hnd->reserved_region_size);
232 std::lock_guard<std::mutex> lock(mutex_);
233 buffers_.emplace(id, buffer);
234 handles_.emplace(hnd, std::make_pair(buffer, 1));
235 *out_handle = reinterpret_cast<buffer_handle_t>(hnd);
239 int32_t cros_gralloc_driver::retain(buffer_handle_t handle)
242 std::lock_guard<std::mutex> lock(mutex_);
244 auto hnd = cros_gralloc_convert_handle(handle);
246 drv_log("Invalid handle.\n");
250 auto buffer = get_buffer(hnd);
252 handles_[hnd].second++;
253 buffer->increase_refcount();
257 if (drmPrimeFDToHandle(drv_get_fd(drv_), hnd->fds[0], &id)) {
258 drv_log("drmPrimeFDToHandle failed.\n");
262 if (buffers_.count(id)) {
263 buffer = buffers_[id];
264 buffer->increase_refcount();
267 struct drv_import_fd_data data;
268 data.format = hnd->format;
270 data.width = hnd->width;
271 data.height = hnd->height;
272 data.use_flags = hnd->use_flags;
274 memcpy(data.fds, hnd->fds, sizeof(data.fds));
275 memcpy(data.strides, hnd->strides, sizeof(data.strides));
276 memcpy(data.offsets, hnd->offsets, sizeof(data.offsets));
277 for (uint32_t plane = 0; plane < DRV_MAX_PLANES; plane++) {
278 data.format_modifiers[plane] = hnd->format_modifier;
281 bo = drv_bo_import(drv_, &data);
285 id = drv_bo_get_plane_handle(bo, 0).u32;
287 buffer = new cros_gralloc_buffer(id, bo, nullptr, hnd->fds[hnd->num_planes],
288 hnd->reserved_region_size);
289 buffers_.emplace(id, buffer);
292 handles_.emplace(hnd, std::make_pair(buffer, 1));
296 int32_t cros_gralloc_driver::release(buffer_handle_t handle)
298 std::lock_guard<std::mutex> lock(mutex_);
300 auto hnd = cros_gralloc_convert_handle(handle);
302 drv_log("Invalid handle.\n");
306 auto buffer = get_buffer(hnd);
308 drv_log("Invalid Reference.\n");
312 if (!--handles_[hnd].second)
315 if (buffer->decrease_refcount() == 0) {
316 buffers_.erase(buffer->get_id());
323 int32_t cros_gralloc_driver::lock(buffer_handle_t handle, int32_t acquire_fence,
324 bool close_acquire_fence, const struct rectangle *rect,
325 uint32_t map_flags, uint8_t *addr[DRV_MAX_PLANES])
327 int32_t ret = cros_gralloc_sync_wait(acquire_fence, close_acquire_fence);
331 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 drv_log("Invalid Reference.\n");
344 return buffer->lock(rect, map_flags, addr);
347 int32_t cros_gralloc_driver::unlock(buffer_handle_t handle, int32_t *release_fence)
349 std::lock_guard<std::mutex> lock(mutex_);
351 auto hnd = cros_gralloc_convert_handle(handle);
353 drv_log("Invalid handle.\n");
357 auto buffer = get_buffer(hnd);
359 drv_log("Invalid Reference.\n");
364 * From the ANativeWindow::dequeueBuffer documentation:
366 * "A value of -1 indicates that the caller may access the buffer immediately without
367 * waiting on a fence."
370 return buffer->unlock();
373 int32_t cros_gralloc_driver::invalidate(buffer_handle_t handle)
375 std::lock_guard<std::mutex> lock(mutex_);
377 auto hnd = cros_gralloc_convert_handle(handle);
379 drv_log("Invalid handle.\n");
383 auto buffer = get_buffer(hnd);
385 drv_log("Invalid Reference.\n");
389 return buffer->invalidate();
392 int32_t cros_gralloc_driver::flush(buffer_handle_t handle, int32_t *release_fence)
394 std::lock_guard<std::mutex> lock(mutex_);
396 auto hnd = cros_gralloc_convert_handle(handle);
398 drv_log("Invalid handle.\n");
402 auto buffer = get_buffer(hnd);
404 drv_log("Invalid Reference.\n");
409 * From the ANativeWindow::dequeueBuffer documentation:
411 * "A value of -1 indicates that the caller may access the buffer immediately without
412 * waiting on a fence."
415 return buffer->flush();
418 int32_t cros_gralloc_driver::get_backing_store(buffer_handle_t handle, uint64_t *out_store)
420 std::lock_guard<std::mutex> lock(mutex_);
422 auto hnd = cros_gralloc_convert_handle(handle);
424 drv_log("Invalid handle.\n");
428 auto buffer = get_buffer(hnd);
430 drv_log("Invalid Reference.\n");
434 *out_store = static_cast<uint64_t>(buffer->get_id());
438 int32_t cros_gralloc_driver::resource_info(buffer_handle_t handle, uint32_t strides[DRV_MAX_PLANES],
439 uint32_t offsets[DRV_MAX_PLANES])
441 std::lock_guard<std::mutex> lock(mutex_);
443 auto hnd = cros_gralloc_convert_handle(handle);
445 drv_log("Invalid handle.\n");
449 auto buffer = get_buffer(hnd);
451 drv_log("Invalid Reference.\n");
455 return buffer->resource_info(strides, offsets);
458 int32_t cros_gralloc_driver::get_reserved_region(buffer_handle_t handle,
459 void **reserved_region_addr,
460 uint64_t *reserved_region_size)
462 std::lock_guard<std::mutex> lock(mutex_);
464 auto hnd = cros_gralloc_convert_handle(handle);
466 drv_log("Invalid handle.\n");
470 auto buffer = get_buffer(hnd);
472 drv_log("Invalid Reference.\n");
476 return buffer->get_reserved_region(reserved_region_addr, reserved_region_size);
479 uint32_t cros_gralloc_driver::get_resolved_drm_format(uint32_t drm_format, uint64_t usage)
481 return drv_resolve_format(drv_, drm_format, usage);
484 cros_gralloc_buffer *cros_gralloc_driver::get_buffer(cros_gralloc_handle_t hnd)
486 /* Assumes driver mutex is held. */
487 if (handles_.count(hnd))
488 return handles_[hnd].first;
493 void cros_gralloc_driver::for_each_handle(
494 const std::function<void(cros_gralloc_handle_t)> &function)
496 std::lock_guard<std::mutex> lock(mutex_);
498 for (const auto &pair : handles_) {
499 function(pair.first);