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 cros_gralloc_driver::cros_gralloc_driver() : drv_(nullptr)
18 cros_gralloc_driver::~cros_gralloc_driver()
29 int32_t cros_gralloc_driver::init()
32 * Create a driver from rendernode while filtering out
33 * the specified undesired driver.
35 * TODO(gsingh): Enable render nodes on udl/evdi.
39 drmVersionPtr version;
40 char const *str = "%s/renderD%d";
41 const char *undesired[2] = { "vgem", nullptr };
42 uint32_t num_nodes = 63;
43 uint32_t min_node = 128;
44 uint32_t max_node = (min_node + num_nodes);
46 for (uint32_t i = 0; i < ARRAY_SIZE(undesired); i++) {
47 for (uint32_t j = min_node; j < max_node; j++) {
49 if (asprintf(&node, str, DRM_DIR_NAME, j) < 0)
52 fd = open(node, O_RDWR, 0);
58 version = drmGetVersion(fd);
62 if (undesired[i] && !strcmp(version->name, undesired[i])) {
63 drmFreeVersion(version);
67 drmFreeVersion(version);
68 drv_ = drv_create(fd);
77 bool cros_gralloc_driver::is_supported(const struct cros_gralloc_buffer_descriptor *descriptor)
79 struct combination *combo;
80 uint32_t resolved_format;
81 resolved_format = drv_resolve_format(drv_, descriptor->drm_format, descriptor->drv_usage);
82 combo = drv_get_combination(drv_, resolved_format, descriptor->drv_usage);
83 return (combo != nullptr);
86 int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descriptor *descriptor,
87 buffer_handle_t *out_handle)
92 uint32_t resolved_format;
95 struct cros_gralloc_handle *hnd;
97 resolved_format = drv_resolve_format(drv_, descriptor->drm_format, descriptor->drv_usage);
98 bo = drv_bo_create(drv_, descriptor->width, descriptor->height, resolved_format,
99 descriptor->drv_usage);
101 cros_gralloc_error("Failed to create bo.");
106 * If there is a desire for more than one kernel buffer, this can be
107 * removed once the ArcCodec and Wayland service have the ability to
108 * send more than one fd. GL/Vulkan drivers may also have to modified.
110 if (drv_num_buffers_per_bo(bo) != 1) {
112 cros_gralloc_error("Can only support one buffer per bo.");
116 hnd = new cros_gralloc_handle();
117 num_planes = drv_bo_get_num_planes(bo);
119 hnd->base.version = sizeof(hnd->base);
120 hnd->base.numFds = num_planes;
121 hnd->base.numInts = handle_data_size - num_planes;
123 for (size_t plane = 0; plane < num_planes; plane++) {
124 hnd->fds[plane] = drv_bo_get_plane_fd(bo, plane);
125 hnd->strides[plane] = drv_bo_get_plane_stride(bo, plane);
126 hnd->offsets[plane] = drv_bo_get_plane_offset(bo, plane);
127 hnd->sizes[plane] = drv_bo_get_plane_size(bo, plane);
129 mod = drv_bo_get_plane_format_modifier(bo, plane);
130 hnd->format_modifiers[2 * plane] = static_cast<uint32_t>(mod >> 32);
131 hnd->format_modifiers[2 * plane + 1] = static_cast<uint32_t>(mod);
134 hnd->width = drv_bo_get_width(bo);
135 hnd->height = drv_bo_get_height(bo);
136 hnd->format = drv_bo_get_format(bo);
137 hnd->pixel_stride = drv_bo_get_stride_in_pixels(bo);
138 hnd->magic = cros_gralloc_magic;
139 hnd->droid_format = descriptor->droid_format;
140 hnd->usage = descriptor->producer_usage;
142 id = drv_bo_get_plane_handle(bo, 0).u32;
143 auto buffer = new cros_gralloc_buffer(id, bo, hnd);
145 std::lock_guard<std::mutex> lock(mutex_);
146 buffers_.emplace(id, buffer);
147 handles_.emplace(hnd, std::make_pair(buffer, 1));
148 *out_handle = &hnd->base;
152 int32_t cros_gralloc_driver::retain(buffer_handle_t handle)
155 std::lock_guard<std::mutex> lock(mutex_);
157 auto hnd = cros_gralloc_convert_handle(handle);
159 cros_gralloc_error("Invalid handle.");
163 auto buffer = get_buffer(hnd);
165 handles_[hnd].second++;
166 buffer->increase_refcount();
170 if (drmPrimeFDToHandle(drv_get_fd(drv_), hnd->fds[0], &id)) {
171 cros_gralloc_error("drmPrimeFDToHandle failed.");
175 if (buffers_.count(id)) {
176 buffer = buffers_[id];
177 buffer->increase_refcount();
180 struct drv_import_fd_data data;
181 data.format = hnd->format;
182 data.width = hnd->width;
183 data.height = hnd->height;
185 memcpy(data.fds, hnd->fds, sizeof(data.fds));
186 memcpy(data.strides, hnd->strides, sizeof(data.strides));
187 memcpy(data.offsets, hnd->offsets, sizeof(data.offsets));
188 memcpy(data.sizes, hnd->sizes, sizeof(data.sizes));
189 for (uint32_t plane = 0; plane < DRV_MAX_PLANES; plane++) {
190 data.format_modifiers[plane] =
191 static_cast<uint64_t>(hnd->format_modifiers[2 * plane]) << 32;
192 data.format_modifiers[plane] |= hnd->format_modifiers[2 * plane + 1];
195 bo = drv_bo_import(drv_, &data);
199 id = drv_bo_get_plane_handle(bo, 0).u32;
201 buffer = new cros_gralloc_buffer(id, bo, nullptr);
202 buffers_.emplace(id, buffer);
205 handles_.emplace(hnd, std::make_pair(buffer, 1));
209 int32_t cros_gralloc_driver::release(buffer_handle_t handle)
211 std::lock_guard<std::mutex> lock(mutex_);
213 auto hnd = cros_gralloc_convert_handle(handle);
215 cros_gralloc_error("Invalid handle.");
219 auto buffer = get_buffer(hnd);
221 cros_gralloc_error("Invalid Reference.");
225 if (!--handles_[hnd].second)
228 if (buffer->decrease_refcount() == 0) {
229 buffers_.erase(buffer->get_id());
236 int32_t cros_gralloc_driver::lock(buffer_handle_t handle, int32_t acquire_fence, uint64_t flags,
237 uint8_t *addr[DRV_MAX_PLANES])
239 std::lock_guard<std::mutex> lock(mutex_);
241 auto hnd = cros_gralloc_convert_handle(handle);
243 cros_gralloc_error("Invalid handle.");
247 auto buffer = get_buffer(hnd);
249 cros_gralloc_error("Invalid Reference.");
253 if (acquire_fence >= 0) {
254 cros_gralloc_error("Sync wait not yet supported.");
258 return buffer->lock(flags, addr);
261 int32_t cros_gralloc_driver::unlock(buffer_handle_t handle)
263 std::lock_guard<std::mutex> lock(mutex_);
265 auto hnd = cros_gralloc_convert_handle(handle);
267 cros_gralloc_error("Invalid handle.");
271 auto buffer = get_buffer(hnd);
273 cros_gralloc_error("Invalid Reference.");
277 return buffer->unlock();
280 int32_t cros_gralloc_driver::get_backing_store(buffer_handle_t handle, uint64_t *out_store)
282 std::lock_guard<std::mutex> lock(mutex_);
284 auto hnd = cros_gralloc_convert_handle(handle);
286 cros_gralloc_error("Invalid handle.");
290 auto buffer = get_buffer(hnd);
292 cros_gralloc_error("Invalid Reference.");
296 *out_store = static_cast<uint64_t>(buffer->get_id());
300 cros_gralloc_buffer *cros_gralloc_driver::get_buffer(cros_gralloc_handle_t hnd)
302 /* Assumes driver mutex is held. */
303 if (handles_.count(hnd))
304 return handles_[hnd].first;