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"
10 #include "i915_private_android.h"
17 cros_gralloc_driver::cros_gralloc_driver() : drv_(nullptr)
21 cros_gralloc_driver::~cros_gralloc_driver()
32 int32_t cros_gralloc_driver::init()
35 * Create a driver from rendernode while filtering out
36 * the specified undesired driver.
38 * TODO(gsingh): Enable render nodes on udl/evdi.
42 drmVersionPtr version;
43 char const *str = "%s/renderD%d";
44 const char *undesired[2] = { "vgem", nullptr };
45 uint32_t num_nodes = 63;
46 uint32_t min_node = 128;
47 uint32_t max_node = (min_node + num_nodes);
49 for (uint32_t i = 0; i < ARRAY_SIZE(undesired); i++) {
50 for (uint32_t j = min_node; j < max_node; j++) {
52 if (asprintf(&node, str, DRM_DIR_NAME, j) < 0)
55 fd = open(node, O_RDWR, 0);
61 version = drmGetVersion(fd);
65 if (undesired[i] && !strcmp(version->name, undesired[i])) {
66 drmFreeVersion(version);
70 drmFreeVersion(version);
71 drv_ = drv_create(fd);
80 bool cros_gralloc_driver::is_supported(const struct cros_gralloc_buffer_descriptor *descriptor)
82 struct combination *combo;
83 uint32_t resolved_format;
84 resolved_format = drv_resolve_format(drv_, descriptor->drm_format, descriptor->use_flags);
85 combo = drv_get_combination(drv_, resolved_format, descriptor->use_flags);
86 return (combo != nullptr);
89 int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descriptor *descriptor,
90 buffer_handle_t *out_handle)
95 uint32_t resolved_format;
98 struct cros_gralloc_handle *hnd;
100 resolved_format = drv_resolve_format(drv_, descriptor->drm_format, descriptor->use_flags);
101 if (descriptor->modifier == 0) {
102 bo = drv_bo_create(drv_, descriptor->width, descriptor->height, resolved_format,
103 descriptor->use_flags);
105 bo = drv_bo_create_with_modifiers(drv_, descriptor->width, descriptor->height,
106 resolved_format, &descriptor->modifier, 1);
109 cros_gralloc_error("Failed to create bo.");
114 * If there is a desire for more than one kernel buffer, this can be
115 * removed once the ArcCodec and Wayland service have the ability to
116 * send more than one fd. GL/Vulkan drivers may also have to modified.
118 if (drv_num_buffers_per_bo(bo) != 1) {
120 cros_gralloc_error("Can only support one buffer per bo.");
124 hnd = new cros_gralloc_handle();
125 num_planes = drv_bo_get_num_planes(bo);
127 hnd->base.version = sizeof(hnd->base);
128 hnd->base.numFds = num_planes;
129 hnd->base.numInts = handle_data_size - num_planes;
131 for (size_t plane = 0; plane < num_planes; plane++) {
132 hnd->fds[plane] = drv_bo_get_plane_fd(bo, plane);
133 hnd->strides[plane] = drv_bo_get_plane_stride(bo, plane);
134 hnd->offsets[plane] = drv_bo_get_plane_offset(bo, plane);
135 hnd->sizes[plane] = drv_bo_get_plane_size(bo, plane);
137 mod = drv_bo_get_plane_format_modifier(bo, plane);
138 hnd->format_modifiers[2 * plane] = static_cast<uint32_t>(mod >> 32);
139 hnd->format_modifiers[2 * plane + 1] = static_cast<uint32_t>(mod);
142 hnd->width = drv_bo_get_width(bo);
143 hnd->height = drv_bo_get_height(bo);
144 hnd->format = drv_bo_get_format(bo);
145 hnd->tiling_mode = drv_bo_get_stride_or_tiling(bo);
146 hnd->use_flags[0] = static_cast<uint32_t>(descriptor->use_flags >> 32);
147 hnd->use_flags[1] = static_cast<uint32_t>(descriptor->use_flags);
148 hnd->pixel_stride = drv_bo_get_stride_in_pixels(bo);
149 hnd->magic = cros_gralloc_magic;
150 int32_t format = i915_private_invert_format(hnd->format);
152 format = descriptor->droid_format;
154 hnd->droid_format = format;
155 hnd->usage = descriptor->producer_usage;
156 hnd->producer_usage = descriptor->producer_usage;
157 hnd->consumer_usage = descriptor->consumer_usage;
159 id = drv_bo_get_plane_handle(bo, 0).u32;
160 auto buffer = new cros_gralloc_buffer(id, bo, hnd);
162 SCOPED_SPIN_LOCK(mutex_);
163 buffers_.emplace(id, buffer);
164 handles_.emplace(hnd, std::make_pair(buffer, 1));
165 *out_handle = &hnd->base;
169 int32_t cros_gralloc_driver::retain(buffer_handle_t handle)
172 SCOPED_SPIN_LOCK(mutex_);
174 auto hnd = cros_gralloc_convert_handle(handle);
176 cros_gralloc_error("Invalid handle.");
180 auto buffer = get_buffer(hnd);
182 handles_[hnd].second++;
183 buffer->increase_refcount();
187 if (drmPrimeFDToHandle(drv_get_fd(drv_), hnd->fds[0], &id)) {
188 cros_gralloc_error("drmPrimeFDToHandle failed.");
192 if (buffers_.count(id)) {
193 buffer = buffers_[id];
194 buffer->increase_refcount();
197 struct drv_import_fd_data data;
198 data.format = hnd->format;
199 data.width = hnd->width;
200 data.height = hnd->height;
201 data.use_flags = static_cast<uint64_t>(hnd->use_flags[0]) << 32;
202 data.use_flags |= hnd->use_flags[1];
204 memcpy(data.fds, hnd->fds, sizeof(data.fds));
205 memcpy(data.strides, hnd->strides, sizeof(data.strides));
206 memcpy(data.offsets, hnd->offsets, sizeof(data.offsets));
207 for (uint32_t plane = 0; plane < DRV_MAX_PLANES; plane++) {
208 data.format_modifiers[plane] =
209 static_cast<uint64_t>(hnd->format_modifiers[2 * plane]) << 32;
210 data.format_modifiers[plane] |= hnd->format_modifiers[2 * plane + 1];
213 bo = drv_bo_import(drv_, &data);
217 id = drv_bo_get_plane_handle(bo, 0).u32;
219 buffer = new cros_gralloc_buffer(id, bo, nullptr);
220 buffers_.emplace(id, buffer);
223 handles_.emplace(hnd, std::make_pair(buffer, 1));
227 int32_t cros_gralloc_driver::release(buffer_handle_t handle)
229 SCOPED_SPIN_LOCK(mutex_);
231 auto hnd = cros_gralloc_convert_handle(handle);
233 cros_gralloc_error("Invalid handle.");
237 auto buffer = get_buffer(hnd);
239 cros_gralloc_error("Invalid Reference.");
243 if (!--handles_[hnd].second)
246 if (buffer->decrease_refcount() == 0) {
247 buffers_.erase(buffer->get_id());
254 int32_t cros_gralloc_driver::lock(buffer_handle_t handle, int32_t acquire_fence, uint32_t map_flags,
255 uint8_t *addr[DRV_MAX_PLANES])
257 int32_t ret = cros_gralloc_sync_wait(acquire_fence);
261 SCOPED_SPIN_LOCK(mutex_);
262 auto hnd = cros_gralloc_convert_handle(handle);
264 cros_gralloc_error("Invalid handle.");
268 auto buffer = get_buffer(hnd);
270 cros_gralloc_error("Invalid Reference.");
274 return buffer->lock(map_flags, addr);
277 int32_t cros_gralloc_driver::unlock(buffer_handle_t handle, int32_t *release_fence)
279 SCOPED_SPIN_LOCK(mutex_);;
281 auto hnd = cros_gralloc_convert_handle(handle);
283 cros_gralloc_error("Invalid handle.");
287 auto buffer = get_buffer(hnd);
289 cros_gralloc_error("Invalid Reference.");
294 * From the ANativeWindow::dequeueBuffer documentation:
296 * "A value of -1 indicates that the caller may access the buffer immediately without
297 * waiting on a fence."
300 return buffer->unlock();
303 int32_t cros_gralloc_driver::get_backing_store(buffer_handle_t handle, uint64_t *out_store)
305 SCOPED_SPIN_LOCK(mutex_);
307 auto hnd = cros_gralloc_convert_handle(handle);
309 cros_gralloc_error("Invalid handle.");
313 auto buffer = get_buffer(hnd);
315 cros_gralloc_error("Invalid Reference.");
319 *out_store = static_cast<uint64_t>(buffer->get_id());
323 cros_gralloc_buffer *cros_gralloc_driver::get_buffer(cros_gralloc_handle_t hnd)
325 /* Assumes driver mutex is held. */
326 if (handles_.count(hnd))
327 return handles_[hnd].first;