OSDN Git Service

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