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 int cros_gralloc_driver::get_fd() const {
30 return drv_get_fd(drv_);
33 int32_t cros_gralloc_driver::init()
36 * Create a driver from rendernode while filtering out
37 * the specified undesired driver.
39 * TODO(gsingh): Enable render nodes on udl/evdi.
43 drmVersionPtr version;
44 char const *str = "%s/renderD%d";
45 const char *undesired[2] = { "vgem", nullptr };
46 uint32_t num_nodes = 63;
47 uint32_t min_node = 128;
48 uint32_t max_node = (min_node + num_nodes);
50 for (uint32_t i = 0; i < ARRAY_SIZE(undesired); i++) {
51 for (uint32_t j = min_node; j < max_node; j++) {
53 if (asprintf(&node, str, DRM_DIR_NAME, j) < 0)
56 fd = open(node, O_RDWR, 0);
62 version = drmGetVersion(fd);
66 if (undesired[i] && !strcmp(version->name, undesired[i])) {
67 drmFreeVersion(version);
71 drmFreeVersion(version);
72 drv_ = drv_create(fd);
81 int cros_gralloc_driver::init_master()
83 int fd = open(DRM_DIR_NAME "/card0", O_RDWR, 0);
85 drv_ = drv_create(fd);
93 bool cros_gralloc_driver::is_supported(const struct cros_gralloc_buffer_descriptor *descriptor)
95 struct combination *combo;
96 uint32_t resolved_format;
97 resolved_format = drv_resolve_format(drv_, descriptor->drm_format, descriptor->use_flags);
98 combo = drv_get_combination(drv_, resolved_format, descriptor->use_flags);
99 return (combo != nullptr);
102 int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descriptor *descriptor,
103 buffer_handle_t *out_handle)
108 uint32_t resolved_format;
109 uint32_t bytes_per_pixel;
113 struct cros_gralloc_handle *hnd;
115 resolved_format = drv_resolve_format(drv_, descriptor->drm_format, descriptor->use_flags);
116 use_flags = descriptor->use_flags;
118 * TODO(b/79682290): ARC++ assumes NV12 is always linear and doesn't
119 * send modifiers across Wayland protocol, so we or in the
120 * BO_USE_LINEAR flag here. We need to fix ARC++ to allocate and work
121 * with tiled buffers.
123 if (resolved_format == DRM_FORMAT_NV12)
124 use_flags |= BO_USE_LINEAR;
126 bo = drv_bo_create(drv_, descriptor->width, descriptor->height, resolved_format, use_flags);
128 drv_log("Failed to create bo.\n");
133 * If there is a desire for more than one kernel buffer, this can be
134 * removed once the ArcCodec and Wayland service have the ability to
135 * send more than one fd. GL/Vulkan drivers may also have to modified.
137 if (drv_num_buffers_per_bo(bo) != 1) {
139 drv_log("Can only support one buffer per bo.\n");
143 hnd = new cros_gralloc_handle();
144 num_planes = drv_bo_get_num_planes(bo);
146 hnd->base.version = sizeof(hnd->base);
147 hnd->base.numFds = num_planes;
148 hnd->base.numInts = handle_data_size - num_planes;
150 for (size_t plane = 0; plane < num_planes; plane++) {
151 hnd->fds[plane] = drv_bo_get_plane_fd(bo, plane);
152 hnd->strides[plane] = drv_bo_get_plane_stride(bo, plane);
153 hnd->offsets[plane] = drv_bo_get_plane_offset(bo, plane);
155 mod = drv_bo_get_plane_format_modifier(bo, plane);
156 hnd->format_modifiers[2 * plane] = static_cast<uint32_t>(mod >> 32);
157 hnd->format_modifiers[2 * plane + 1] = static_cast<uint32_t>(mod);
160 hnd->width = drv_bo_get_width(bo);
161 hnd->height = drv_bo_get_height(bo);
162 hnd->format = drv_bo_get_format(bo);
163 hnd->use_flags[0] = static_cast<uint32_t>(descriptor->use_flags >> 32);
164 hnd->use_flags[1] = static_cast<uint32_t>(descriptor->use_flags);
165 bytes_per_pixel = drv_bytes_per_pixel_from_format(hnd->format, 0);
166 hnd->pixel_stride = DIV_ROUND_UP(hnd->strides[0], bytes_per_pixel);
167 hnd->magic = cros_gralloc_magic;
168 hnd->droid_format = descriptor->droid_format;
169 hnd->usage = descriptor->producer_usage;
171 id = drv_bo_get_plane_handle(bo, 0).u32;
172 auto buffer = new cros_gralloc_buffer(id, bo, hnd);
174 std::lock_guard<std::mutex> lock(mutex_);
175 buffers_.emplace(id, buffer);
176 handles_.emplace(hnd, std::make_pair(buffer, 1));
177 *out_handle = &hnd->base;
181 int32_t cros_gralloc_driver::retain(buffer_handle_t handle)
184 std::lock_guard<std::mutex> lock(mutex_);
186 auto hnd = cros_gralloc_convert_handle(handle);
188 drv_log("Invalid handle.\n");
192 auto buffer = get_buffer(hnd);
194 handles_[hnd].second++;
195 buffer->increase_refcount();
199 if (drmPrimeFDToHandle(drv_get_fd(drv_), hnd->fds[0], &id)) {
200 drv_log("drmPrimeFDToHandle failed.\n");
204 if (buffers_.count(id)) {
205 buffer = buffers_[id];
206 buffer->increase_refcount();
209 struct drv_import_fd_data data;
210 data.format = hnd->format;
211 data.width = hnd->width;
212 data.height = hnd->height;
213 data.use_flags = static_cast<uint64_t>(hnd->use_flags[0]) << 32;
214 data.use_flags |= hnd->use_flags[1];
216 memcpy(data.fds, hnd->fds, sizeof(data.fds));
217 memcpy(data.strides, hnd->strides, sizeof(data.strides));
218 memcpy(data.offsets, hnd->offsets, sizeof(data.offsets));
219 for (uint32_t plane = 0; plane < DRV_MAX_PLANES; plane++) {
220 data.format_modifiers[plane] =
221 static_cast<uint64_t>(hnd->format_modifiers[2 * plane]) << 32;
222 data.format_modifiers[plane] |= hnd->format_modifiers[2 * plane + 1];
225 bo = drv_bo_import(drv_, &data);
229 id = drv_bo_get_plane_handle(bo, 0).u32;
231 buffer = new cros_gralloc_buffer(id, bo, nullptr);
232 buffers_.emplace(id, buffer);
235 handles_.emplace(hnd, std::make_pair(buffer, 1));
239 int32_t cros_gralloc_driver::release(buffer_handle_t handle)
241 std::lock_guard<std::mutex> lock(mutex_);
243 auto hnd = cros_gralloc_convert_handle(handle);
245 drv_log("Invalid handle.\n");
249 auto buffer = get_buffer(hnd);
251 drv_log("Invalid Reference.\n");
255 if (!--handles_[hnd].second)
258 if (buffer->decrease_refcount() == 0) {
259 buffers_.erase(buffer->get_id());
266 int32_t cros_gralloc_driver::lock(buffer_handle_t handle, int32_t acquire_fence,
267 const struct rectangle *rect, uint32_t map_flags,
268 uint8_t *addr[DRV_MAX_PLANES])
270 int32_t ret = cros_gralloc_sync_wait(acquire_fence);
274 std::lock_guard<std::mutex> lock(mutex_);
275 auto hnd = cros_gralloc_convert_handle(handle);
277 drv_log("Invalid handle.\n");
281 auto buffer = get_buffer(hnd);
283 drv_log("Invalid Reference.\n");
287 return buffer->lock(rect, map_flags, addr);
290 int32_t cros_gralloc_driver::unlock(buffer_handle_t handle, int32_t *release_fence)
292 std::lock_guard<std::mutex> lock(mutex_);
294 auto hnd = cros_gralloc_convert_handle(handle);
296 drv_log("Invalid handle.\n");
300 auto buffer = get_buffer(hnd);
302 drv_log("Invalid Reference.\n");
307 * From the ANativeWindow::dequeueBuffer documentation:
309 * "A value of -1 indicates that the caller may access the buffer immediately without
310 * waiting on a fence."
313 return buffer->unlock();
316 int32_t cros_gralloc_driver::get_backing_store(buffer_handle_t handle, uint64_t *out_store)
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 *out_store = static_cast<uint64_t>(buffer->get_id());
336 cros_gralloc_buffer *cros_gralloc_driver::get_buffer(cros_gralloc_handle_t hnd)
338 /* Assumes driver mutex is held. */
339 if (handles_.count(hnd))
340 return handles_[hnd].first;