OSDN Git Service

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