OSDN Git Service

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