1 /*
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.
5 */
6
7 #include "cros_gralloc_driver.h"
8
9 #include <cstdlib>
10 #include <fcntl.h>
11 #include <sys/mman.h>
12 #include <syscall.h>
13 #include <xf86drm.h>
14
15 #include "../drv_priv.h"
16 #include "../helpers.h"
17 #include "../util.h"
18
19 // Constants taken from pipe_loader_drm.c in Mesa
20
21 #define DRM_NUM_NODES 63
22
23 // DRM Render nodes start at 128
24 #define DRM_RENDER_NODE_START 128
25
26 // DRM Card nodes start at 0
27 #define DRM_CARD_NODE_START 0
28
memfd_create_wrapper(const char * name,unsigned int flags)29 int memfd_create_wrapper(const char *name, unsigned int flags)
30 {
31 int fd;
32
33 #if defined(HAVE_MEMFD_CREATE)
34 fd = memfd_create(name, flags);
35 #elif defined(__NR_memfd_create)
36 fd = syscall(__NR_memfd_create, name, flags);
37 #else
38 drv_log("Failed to create memfd '%s': memfd_create not available.", name);
39 return -1;
40 #endif
41
42 if (fd == -1)
43 drv_log("Failed to create memfd '%s': %s.\n", name, strerror(errno));
44
45 return fd;
46 }
47
cros_gralloc_driver()48 cros_gralloc_driver::cros_gralloc_driver() : drv_(nullptr)
49 {
50 }
51
~cros_gralloc_driver()52 cros_gralloc_driver::~cros_gralloc_driver()
53 {
54 buffers_.clear();
55 handles_.clear();
56
57 if (drv_) {
58 int fd = drv_get_fd(drv_);
59 drv_destroy(drv_);
60 drv_ = nullptr;
61 close(fd);
62 }
63 }
64
init_try_node(int idx,char const * str)65 static struct driver *init_try_node(int idx, char const *str)
66 {
67 int fd;
68 char *node;
69 struct driver *drv;
70
71 if (asprintf(&node, str, DRM_DIR_NAME, idx) < 0)
72 return NULL;
73
74 fd = open(node, O_RDWR, 0);
75 free(node);
76
77 if (fd < 0)
78 return NULL;
79
80 drv = drv_create(fd);
81 if (!drv)
82 close(fd);
83
84 return drv;
85 }
86
init()87 int32_t cros_gralloc_driver::init()
88 {
89 /*
90 * Create a driver from render nodes first, then try card
91 * nodes.
92 *
93 * TODO(gsingh): Enable render nodes on udl/evdi.
94 */
95
96 char const *render_nodes_fmt = "%s/renderD%d";
97 char const *card_nodes_fmt = "%s/card%d";
98 uint32_t num_nodes = DRM_NUM_NODES;
99 uint32_t min_render_node = DRM_RENDER_NODE_START;
100 uint32_t max_render_node = (min_render_node + num_nodes);
101 uint32_t min_card_node = DRM_CARD_NODE_START;
102 uint32_t max_card_node = (min_card_node + num_nodes);
103
104 // Try render nodes...
105 for (uint32_t i = min_render_node; i < max_render_node; i++) {
106 drv_ = init_try_node(i, render_nodes_fmt);
107 if (drv_)
108 return 0;
109 }
110
111 // Try card nodes... for vkms mostly.
112 for (uint32_t i = min_card_node; i < max_card_node; i++) {
113 drv_ = init_try_node(i, card_nodes_fmt);
114 if (drv_)
115 return 0;
116 }
117
118 return -ENODEV;
119 }
120
is_supported(const struct cros_gralloc_buffer_descriptor * descriptor)121 bool cros_gralloc_driver::is_supported(const struct cros_gralloc_buffer_descriptor *descriptor)
122 {
123 struct combination *combo;
124 uint32_t resolved_format;
125 resolved_format = drv_resolve_format(drv_, descriptor->drm_format, descriptor->use_flags);
126 combo = drv_get_combination(drv_, resolved_format, descriptor->use_flags);
127 return (combo != nullptr);
128 }
129
create_reserved_region(const std::string & buffer_name,uint64_t reserved_region_size)130 int32_t create_reserved_region(const std::string &buffer_name, uint64_t reserved_region_size)
131 {
132 std::string reserved_region_name = buffer_name + " reserved region";
133
134 int32_t reserved_region_fd = memfd_create_wrapper(reserved_region_name.c_str(), FD_CLOEXEC);
135 if (reserved_region_fd == -1)
136 return -errno;
137
138 if (ftruncate(reserved_region_fd, reserved_region_size)) {
139 drv_log("Failed to set reserved region size: %s.\n", strerror(errno));
140 return -errno;
141 }
142
143 return reserved_region_fd;
144 }
145
emplace_buffer(struct bo * bo,struct cros_gralloc_handle * hnd)146 void cros_gralloc_driver::emplace_buffer(struct bo *bo, struct cros_gralloc_handle *hnd)
147 {
148 auto buffer = new cros_gralloc_buffer(hnd->id, bo, hnd, hnd->fds[hnd->num_planes],
149 hnd->reserved_region_size);
150
151 std::lock_guard<std::mutex> lock(mutex_);
152 buffers_.emplace(hnd->id, buffer);
153 handles_.emplace(hnd, std::make_pair(buffer, 1));
154 }
155
allocate(const struct cros_gralloc_buffer_descriptor * descriptor,buffer_handle_t * out_handle)156 int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descriptor *descriptor,
157 buffer_handle_t *out_handle)
158 {
159 int ret = 0;
160 size_t num_planes;
161 size_t num_fds;
162 size_t num_ints;
163 size_t num_bytes;
164 uint32_t resolved_format;
165 uint32_t bytes_per_pixel;
166 uint64_t use_flags;
167 char *name;
168 struct bo *bo;
169 struct cros_gralloc_handle *hnd;
170
171 resolved_format = drv_resolve_format(drv_, descriptor->drm_format, descriptor->use_flags);
172 use_flags = descriptor->use_flags;
173
174 /*
175 * This unmask is a backup in the case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED is resolved
176 * to non-YUV formats.
177 */
178 if (descriptor->drm_format == DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED &&
179 (resolved_format == DRM_FORMAT_XBGR8888 || resolved_format == DRM_FORMAT_ABGR8888)) {
180 use_flags &= ~BO_USE_HW_VIDEO_ENCODER;
181 }
182
183 bo = drv_bo_create(drv_, descriptor->width, descriptor->height, resolved_format, use_flags);
184 if (!bo) {
185 drv_log("Failed to create bo.\n");
186 return -errno;
187 }
188
189 /*
190 * If there is a desire for more than one kernel buffer, this can be
191 * removed once the ArcCodec and Wayland service have the ability to
192 * send more than one fd. GL/Vulkan drivers may also have to modified.
193 */
194 if (drv_num_buffers_per_bo(bo) != 1) {
195 drv_log("Can only support one buffer per bo.\n");
196 goto destroy_bo;
197 }
198
199 num_planes = drv_bo_get_num_planes(bo);
200 num_fds = num_planes;
201
202 if (descriptor->reserved_region_size > 0)
203 num_fds += 1;
204
205 num_bytes = sizeof(struct cros_gralloc_handle);
206 num_bytes += (descriptor->name.size() + 1);
207 /*
208 * Ensure that the total number of bytes is a multiple of sizeof(int) as
209 * native_handle_clone() copies data based on hnd->base.numInts.
210 */
211 num_bytes = ALIGN(num_bytes, sizeof(int));
212 num_ints = ((num_bytes - sizeof(native_handle_t)) / sizeof(int)) - num_fds;
213
214 hnd =
215 reinterpret_cast<struct cros_gralloc_handle *>(native_handle_create(num_fds, num_ints));
216
217 for (size_t i = 0; i < DRV_MAX_FDS; i++)
218 hnd->fds[i] = -1;
219
220 hnd->num_planes = num_planes;
221 for (size_t plane = 0; plane < num_planes; plane++) {
222 ret = drv_bo_get_plane_fd(bo, plane);
223 if (ret < 0)
224 goto destroy_hnd;
225
226 hnd->fds[plane] = ret;
227 hnd->strides[plane] = drv_bo_get_plane_stride(bo, plane);
228 hnd->offsets[plane] = drv_bo_get_plane_offset(bo, plane);
229 hnd->sizes[plane] = drv_bo_get_plane_size(bo, plane);
230 }
231
232 hnd->reserved_region_size = descriptor->reserved_region_size;
233 if (hnd->reserved_region_size > 0) {
234 ret = create_reserved_region(descriptor->name, hnd->reserved_region_size);
235 if (ret < 0)
236 goto destroy_hnd;
237
238 hnd->fds[hnd->num_planes] = ret;
239 }
240
241 static std::atomic<uint32_t> next_buffer_id{ 1 };
242 hnd->id = next_buffer_id++;
243 hnd->width = drv_bo_get_width(bo);
244 hnd->height = drv_bo_get_height(bo);
245 hnd->format = drv_bo_get_format(bo);
246 hnd->tiling = bo->meta.tiling;
247 hnd->format_modifier = drv_bo_get_format_modifier(bo);
248 hnd->use_flags = descriptor->use_flags;
249 bytes_per_pixel = drv_bytes_per_pixel_from_format(hnd->format, 0);
250 hnd->pixel_stride = DIV_ROUND_UP(hnd->strides[0], bytes_per_pixel);
251 hnd->magic = cros_gralloc_magic;
252 hnd->droid_format = descriptor->droid_format;
253 hnd->usage = descriptor->droid_usage;
254 hnd->total_size = descriptor->reserved_region_size + bo->meta.total_size;
255 hnd->name_offset = handle_data_size;
256
257 name = (char *)(&hnd->data[hnd->name_offset]);
258 snprintf(name, descriptor->name.size() + 1, "%s", descriptor->name.c_str());
259
260 emplace_buffer(bo, hnd);
261
262 *out_handle = reinterpret_cast<buffer_handle_t>(hnd);
263 return 0;
264
265 destroy_hnd:
266 native_handle_close(hnd);
267 native_handle_delete(hnd);
268
269 destroy_bo:
270 drv_bo_destroy(bo);
271 return ret;
272 }
273
retain(buffer_handle_t handle)274 int32_t cros_gralloc_driver::retain(buffer_handle_t handle)
275 {
276 uint32_t id;
277 std::lock_guard<std::mutex> lock(mutex_);
278
279 auto hnd = cros_gralloc_convert_handle(handle);
280 if (!hnd) {
281 drv_log("Invalid handle.\n");
282 return -EINVAL;
283 }
284
285 auto buffer = get_buffer(hnd);
286 if (buffer) {
287 handles_[hnd].second++;
288 buffer->increase_refcount();
289 return 0;
290 }
291
292 id = hnd->id;
293
294 if (buffers_.count(id)) {
295 buffer = buffers_[id];
296 buffer->increase_refcount();
297 } else {
298 struct bo *bo;
299 struct drv_import_fd_data data;
300 data.format = hnd->format;
301 data.tiling = hnd->tiling;
302
303 data.width = hnd->width;
304 data.height = hnd->height;
305 data.use_flags = hnd->use_flags;
306
307 memcpy(data.fds, hnd->fds, sizeof(data.fds));
308 memcpy(data.strides, hnd->strides, sizeof(data.strides));
309 memcpy(data.offsets, hnd->offsets, sizeof(data.offsets));
310 data.format_modifier = hnd->format_modifier;
311
312 bo = drv_bo_import(drv_, &data);
313 if (!bo)
314 return -EFAULT;
315
316 buffer = new cros_gralloc_buffer(id, bo, nullptr, hnd->fds[hnd->num_planes],
317 hnd->reserved_region_size);
318 buffers_.emplace(id, buffer);
319 }
320
321 handles_.emplace(hnd, std::make_pair(buffer, 1));
322 return 0;
323 }
324
release(buffer_handle_t handle)325 int32_t cros_gralloc_driver::release(buffer_handle_t handle)
326 {
327 std::lock_guard<std::mutex> lock(mutex_);
328
329 auto hnd = cros_gralloc_convert_handle(handle);
330 if (!hnd) {
331 drv_log("Invalid handle.\n");
332 return -EINVAL;
333 }
334
335 auto buffer = get_buffer(hnd);
336 if (!buffer) {
337 drv_log("Invalid Reference.\n");
338 return -EINVAL;
339 }
340
341 if (!--handles_[hnd].second)
342 handles_.erase(hnd);
343
344 if (buffer->decrease_refcount() == 0) {
345 buffers_.erase(buffer->get_id());
346 delete buffer;
347 }
348
349 return 0;
350 }
351
lock(buffer_handle_t handle,int32_t acquire_fence,bool close_acquire_fence,const struct rectangle * rect,uint32_t map_flags,uint8_t * addr[DRV_MAX_PLANES])352 int32_t cros_gralloc_driver::lock(buffer_handle_t handle, int32_t acquire_fence,
353 bool close_acquire_fence, const struct rectangle *rect,
354 uint32_t map_flags, uint8_t *addr[DRV_MAX_PLANES])
355 {
356 int32_t ret = cros_gralloc_sync_wait(acquire_fence, close_acquire_fence);
357 if (ret)
358 return ret;
359
360 std::lock_guard<std::mutex> lock(mutex_);
361 auto hnd = cros_gralloc_convert_handle(handle);
362 if (!hnd) {
363 drv_log("Invalid handle.\n");
364 return -EINVAL;
365 }
366
367 auto buffer = get_buffer(hnd);
368 if (!buffer) {
369 drv_log("Invalid Reference.\n");
370 return -EINVAL;
371 }
372
373 return buffer->lock(rect, map_flags, addr);
374 }
375
unlock(buffer_handle_t handle,int32_t * release_fence)376 int32_t cros_gralloc_driver::unlock(buffer_handle_t handle, int32_t *release_fence)
377 {
378 std::lock_guard<std::mutex> lock(mutex_);
379
380 auto hnd = cros_gralloc_convert_handle(handle);
381 if (!hnd) {
382 drv_log("Invalid handle.\n");
383 return -EINVAL;
384 }
385
386 auto buffer = get_buffer(hnd);
387 if (!buffer) {
388 drv_log("Invalid Reference.\n");
389 return -EINVAL;
390 }
391
392 /*
393 * From the ANativeWindow::dequeueBuffer documentation:
394 *
395 * "A value of -1 indicates that the caller may access the buffer immediately without
396 * waiting on a fence."
397 */
398 *release_fence = -1;
399 return buffer->unlock();
400 }
401
invalidate(buffer_handle_t handle)402 int32_t cros_gralloc_driver::invalidate(buffer_handle_t handle)
403 {
404 std::lock_guard<std::mutex> lock(mutex_);
405
406 auto hnd = cros_gralloc_convert_handle(handle);
407 if (!hnd) {
408 drv_log("Invalid handle.\n");
409 return -EINVAL;
410 }
411
412 auto buffer = get_buffer(hnd);
413 if (!buffer) {
414 drv_log("Invalid Reference.\n");
415 return -EINVAL;
416 }
417
418 return buffer->invalidate();
419 }
420
flush(buffer_handle_t handle,int32_t * release_fence)421 int32_t cros_gralloc_driver::flush(buffer_handle_t handle, int32_t *release_fence)
422 {
423 std::lock_guard<std::mutex> lock(mutex_);
424
425 auto hnd = cros_gralloc_convert_handle(handle);
426 if (!hnd) {
427 drv_log("Invalid handle.\n");
428 return -EINVAL;
429 }
430
431 auto buffer = get_buffer(hnd);
432 if (!buffer) {
433 drv_log("Invalid Reference.\n");
434 return -EINVAL;
435 }
436
437 /*
438 * From the ANativeWindow::dequeueBuffer documentation:
439 *
440 * "A value of -1 indicates that the caller may access the buffer immediately without
441 * waiting on a fence."
442 */
443 *release_fence = -1;
444 return buffer->flush();
445 }
446
get_backing_store(buffer_handle_t handle,uint64_t * out_store)447 int32_t cros_gralloc_driver::get_backing_store(buffer_handle_t handle, uint64_t *out_store)
448 {
449 std::lock_guard<std::mutex> lock(mutex_);
450
451 auto hnd = cros_gralloc_convert_handle(handle);
452 if (!hnd) {
453 drv_log("Invalid handle.\n");
454 return -EINVAL;
455 }
456
457 auto buffer = get_buffer(hnd);
458 if (!buffer) {
459 drv_log("Invalid Reference.\n");
460 return -EINVAL;
461 }
462
463 *out_store = static_cast<uint64_t>(buffer->get_id());
464 return 0;
465 }
466
resource_info(buffer_handle_t handle,uint32_t strides[DRV_MAX_PLANES],uint32_t offsets[DRV_MAX_PLANES],uint64_t * format_modifier)467 int32_t cros_gralloc_driver::resource_info(buffer_handle_t handle, uint32_t strides[DRV_MAX_PLANES],
468 uint32_t offsets[DRV_MAX_PLANES],
469 uint64_t *format_modifier)
470 {
471 std::lock_guard<std::mutex> lock(mutex_);
472
473 auto hnd = cros_gralloc_convert_handle(handle);
474 if (!hnd) {
475 drv_log("Invalid handle.\n");
476 return -EINVAL;
477 }
478
479 auto buffer = get_buffer(hnd);
480 if (!buffer) {
481 drv_log("Invalid Reference.\n");
482 return -EINVAL;
483 }
484
485 return buffer->resource_info(strides, offsets, format_modifier);
486 }
487
get_reserved_region(buffer_handle_t handle,void ** reserved_region_addr,uint64_t * reserved_region_size)488 int32_t cros_gralloc_driver::get_reserved_region(buffer_handle_t handle,
489 void **reserved_region_addr,
490 uint64_t *reserved_region_size)
491 {
492 std::lock_guard<std::mutex> lock(mutex_);
493
494 auto hnd = cros_gralloc_convert_handle(handle);
495 if (!hnd) {
496 drv_log("Invalid handle.\n");
497 return -EINVAL;
498 }
499
500 auto buffer = get_buffer(hnd);
501 if (!buffer) {
502 drv_log("Invalid Reference.\n");
503 return -EINVAL;
504 }
505
506 return buffer->get_reserved_region(reserved_region_addr, reserved_region_size);
507 }
508
get_resolved_drm_format(uint32_t drm_format,uint64_t usage)509 uint32_t cros_gralloc_driver::get_resolved_drm_format(uint32_t drm_format, uint64_t usage)
510 {
511 return drv_resolve_format(drv_, drm_format, usage);
512 }
513
get_buffer(cros_gralloc_handle_t hnd)514 cros_gralloc_buffer *cros_gralloc_driver::get_buffer(cros_gralloc_handle_t hnd)
515 {
516 /* Assumes driver mutex is held. */
517 if (handles_.count(hnd))
518 return handles_[hnd].first;
519
520 return nullptr;
521 }
522
for_each_handle(const std::function<void (cros_gralloc_handle_t)> & function)523 void cros_gralloc_driver::for_each_handle(
524 const std::function<void(cros_gralloc_handle_t)> &function)
525 {
526 std::lock_guard<std::mutex> lock(mutex_);
527
528 for (const auto &pair : handles_)
529 function(pair.first);
530 }
531