OSDN Git Service

minigbm: cros_gralloc: map protected flag to linear
[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 | O_CLOEXEC);
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         std::string reserved_region_name = buffer_name + " reserved region";
100
101 #ifdef __NR_memfd_create
102         int32_t 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 #else
115         drv_log("Failed to create reserved region '%s': memfd_create not available.",
116                 reserved_region_name.c_str());
117         return -1;
118 #endif
119 }
120
121 int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descriptor *descriptor,
122                                       buffer_handle_t *out_handle)
123 {
124         uint32_t id;
125         size_t num_planes;
126         size_t num_fds;
127         size_t num_ints;
128         size_t num_bytes;
129         uint32_t resolved_format;
130         uint32_t bytes_per_pixel;
131         uint64_t use_flags;
132         int32_t reserved_region_fd;
133         char *name;
134
135         struct bo *bo;
136         struct cros_gralloc_handle *hnd;
137
138         resolved_format = drv_resolve_format(drv_, descriptor->drm_format, descriptor->use_flags);
139         use_flags = descriptor->use_flags;
140         /*
141          * TODO(b/79682290): ARC++ assumes NV12 is always linear and doesn't
142          * send modifiers across Wayland protocol, so we or in the
143          * BO_USE_LINEAR flag here. We need to fix ARC++ to allocate and work
144          * with tiled buffers.
145          */
146         if (resolved_format == DRM_FORMAT_NV12)
147                 use_flags |= BO_USE_LINEAR;
148
149         /*
150          * This unmask is a backup in the case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED is resolved
151          * to non-YUV formats.
152          */
153         if (descriptor->drm_format == DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED &&
154             (resolved_format == DRM_FORMAT_XBGR8888 || resolved_format == DRM_FORMAT_ABGR8888)) {
155                 use_flags &= ~BO_USE_HW_VIDEO_ENCODER;
156         }
157
158         bo = drv_bo_create(drv_, descriptor->width, descriptor->height, resolved_format, use_flags);
159         if (!bo) {
160                 drv_log("Failed to create bo.\n");
161                 return -ENOMEM;
162         }
163
164         /*
165          * If there is a desire for more than one kernel buffer, this can be
166          * removed once the ArcCodec and Wayland service have the ability to
167          * send more than one fd. GL/Vulkan drivers may also have to modified.
168          */
169         if (drv_num_buffers_per_bo(bo) != 1) {
170                 drv_bo_destroy(bo);
171                 drv_log("Can only support one buffer per bo.\n");
172                 return -EINVAL;
173         }
174
175         num_planes = drv_bo_get_num_planes(bo);
176         num_fds = num_planes;
177
178         if (descriptor->reserved_region_size > 0) {
179                 reserved_region_fd =
180                     create_reserved_region(descriptor->name, descriptor->reserved_region_size);
181                 if (reserved_region_fd < 0) {
182                         drv_bo_destroy(bo);
183                         return reserved_region_fd;
184                 }
185                 num_fds += 1;
186         } else {
187                 reserved_region_fd = -1;
188         }
189
190         num_bytes = sizeof(struct cros_gralloc_handle);
191         num_bytes += (descriptor->name.size() + 1);
192         /*
193          * Ensure that the total number of bytes is a multiple of sizeof(int) as
194          * native_handle_clone() copies data based on hnd->base.numInts.
195          */
196         num_bytes = ALIGN(num_bytes, sizeof(int));
197         num_ints = num_bytes - sizeof(native_handle_t) - num_fds;
198         /*
199          * Malloc is used as handles are ultimately destroyed via free in
200          * native_handle_delete().
201          */
202         hnd = static_cast<struct cros_gralloc_handle *>(malloc(num_bytes));
203         hnd->base.version = sizeof(hnd->base);
204         hnd->base.numFds = num_fds;
205         hnd->base.numInts = num_ints;
206         hnd->num_planes = num_planes;
207         for (size_t plane = 0; plane < num_planes; plane++) {
208                 hnd->fds[plane] = drv_bo_get_plane_fd(bo, plane);
209                 hnd->strides[plane] = drv_bo_get_plane_stride(bo, plane);
210                 hnd->offsets[plane] = drv_bo_get_plane_offset(bo, plane);
211                 hnd->sizes[plane] = drv_bo_get_plane_size(bo, plane);
212         }
213         hnd->fds[hnd->num_planes] = reserved_region_fd;
214         hnd->reserved_region_size = descriptor->reserved_region_size;
215         static std::atomic<uint32_t> next_buffer_id{ 1 };
216         hnd->id = next_buffer_id++;
217         hnd->width = drv_bo_get_width(bo);
218         hnd->height = drv_bo_get_height(bo);
219         hnd->format = drv_bo_get_format(bo);
220         hnd->tiling = bo->meta.tiling;
221         hnd->format_modifier = drv_bo_get_plane_format_modifier(bo, 0);
222         hnd->use_flags = descriptor->use_flags;
223         bytes_per_pixel = drv_bytes_per_pixel_from_format(hnd->format, 0);
224         hnd->pixel_stride = DIV_ROUND_UP(hnd->strides[0], bytes_per_pixel);
225         hnd->magic = cros_gralloc_magic;
226         hnd->droid_format = descriptor->droid_format;
227         hnd->usage = descriptor->droid_usage;
228         hnd->total_size = descriptor->reserved_region_size + bo->meta.total_size;
229         hnd->name_offset = handle_data_size;
230
231         name = (char *)(&hnd->base.data[hnd->name_offset]);
232         snprintf(name, descriptor->name.size() + 1, "%s", descriptor->name.c_str());
233
234         id = drv_bo_get_plane_handle(bo, 0).u32;
235         auto buffer = new cros_gralloc_buffer(id, bo, hnd, hnd->fds[hnd->num_planes],
236                                               hnd->reserved_region_size);
237
238         std::lock_guard<std::mutex> lock(mutex_);
239         buffers_.emplace(id, buffer);
240         handles_.emplace(hnd, std::make_pair(buffer, 1));
241         *out_handle = reinterpret_cast<buffer_handle_t>(hnd);
242         return 0;
243 }
244
245 int32_t cros_gralloc_driver::retain(buffer_handle_t handle)
246 {
247         uint32_t id;
248         std::lock_guard<std::mutex> lock(mutex_);
249
250         auto hnd = cros_gralloc_convert_handle(handle);
251         if (!hnd) {
252                 drv_log("Invalid handle.\n");
253                 return -EINVAL;
254         }
255
256         auto buffer = get_buffer(hnd);
257         if (buffer) {
258                 handles_[hnd].second++;
259                 buffer->increase_refcount();
260                 return 0;
261         }
262
263         if (drmPrimeFDToHandle(drv_get_fd(drv_), hnd->fds[0], &id)) {
264                 drv_log("drmPrimeFDToHandle failed.\n");
265                 return -errno;
266         }
267
268         if (buffers_.count(id)) {
269                 buffer = buffers_[id];
270                 buffer->increase_refcount();
271         } else {
272                 struct bo *bo;
273                 struct drv_import_fd_data data;
274                 data.format = hnd->format;
275                 data.tiling = hnd->tiling;
276
277                 data.width = hnd->width;
278                 data.height = hnd->height;
279                 data.use_flags = hnd->use_flags;
280
281                 memcpy(data.fds, hnd->fds, sizeof(data.fds));
282                 memcpy(data.strides, hnd->strides, sizeof(data.strides));
283                 memcpy(data.offsets, hnd->offsets, sizeof(data.offsets));
284                 for (uint32_t plane = 0; plane < DRV_MAX_PLANES; plane++) {
285                         data.format_modifiers[plane] = hnd->format_modifier;
286                 }
287
288                 bo = drv_bo_import(drv_, &data);
289                 if (!bo)
290                         return -EFAULT;
291
292                 id = drv_bo_get_plane_handle(bo, 0).u32;
293
294                 buffer = new cros_gralloc_buffer(id, bo, nullptr, hnd->fds[hnd->num_planes],
295                                                  hnd->reserved_region_size);
296                 buffers_.emplace(id, buffer);
297         }
298
299         handles_.emplace(hnd, std::make_pair(buffer, 1));
300         return 0;
301 }
302
303 int32_t cros_gralloc_driver::release(buffer_handle_t handle)
304 {
305         std::lock_guard<std::mutex> lock(mutex_);
306
307         auto hnd = cros_gralloc_convert_handle(handle);
308         if (!hnd) {
309                 drv_log("Invalid handle.\n");
310                 return -EINVAL;
311         }
312
313         auto buffer = get_buffer(hnd);
314         if (!buffer) {
315                 drv_log("Invalid Reference.\n");
316                 return -EINVAL;
317         }
318
319         if (!--handles_[hnd].second)
320                 handles_.erase(hnd);
321
322         if (buffer->decrease_refcount() == 0) {
323                 buffers_.erase(buffer->get_id());
324                 delete buffer;
325         }
326
327         return 0;
328 }
329
330 int32_t cros_gralloc_driver::lock(buffer_handle_t handle, int32_t acquire_fence,
331                                   bool close_acquire_fence, const struct rectangle *rect,
332                                   uint32_t map_flags, uint8_t *addr[DRV_MAX_PLANES])
333 {
334         int32_t ret = cros_gralloc_sync_wait(acquire_fence, close_acquire_fence);
335         if (ret)
336                 return ret;
337
338         std::lock_guard<std::mutex> lock(mutex_);
339         auto hnd = cros_gralloc_convert_handle(handle);
340         if (!hnd) {
341                 drv_log("Invalid handle.\n");
342                 return -EINVAL;
343         }
344
345         auto buffer = get_buffer(hnd);
346         if (!buffer) {
347                 drv_log("Invalid Reference.\n");
348                 return -EINVAL;
349         }
350
351         return buffer->lock(rect, map_flags, addr);
352 }
353
354 int32_t cros_gralloc_driver::unlock(buffer_handle_t handle, int32_t *release_fence)
355 {
356         std::lock_guard<std::mutex> lock(mutex_);
357
358         auto hnd = cros_gralloc_convert_handle(handle);
359         if (!hnd) {
360                 drv_log("Invalid handle.\n");
361                 return -EINVAL;
362         }
363
364         auto buffer = get_buffer(hnd);
365         if (!buffer) {
366                 drv_log("Invalid Reference.\n");
367                 return -EINVAL;
368         }
369
370         /*
371          * From the ANativeWindow::dequeueBuffer documentation:
372          *
373          * "A value of -1 indicates that the caller may access the buffer immediately without
374          * waiting on a fence."
375          */
376         *release_fence = -1;
377         return buffer->unlock();
378 }
379
380 int32_t cros_gralloc_driver::invalidate(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         return buffer->invalidate();
397 }
398
399 int32_t cros_gralloc_driver::flush(buffer_handle_t handle, int32_t *release_fence)
400 {
401         std::lock_guard<std::mutex> lock(mutex_);
402
403         auto hnd = cros_gralloc_convert_handle(handle);
404         if (!hnd) {
405                 drv_log("Invalid handle.\n");
406                 return -EINVAL;
407         }
408
409         auto buffer = get_buffer(hnd);
410         if (!buffer) {
411                 drv_log("Invalid Reference.\n");
412                 return -EINVAL;
413         }
414
415         /*
416          * From the ANativeWindow::dequeueBuffer documentation:
417          *
418          * "A value of -1 indicates that the caller may access the buffer immediately without
419          * waiting on a fence."
420          */
421         *release_fence = -1;
422         return buffer->flush();
423 }
424
425 int32_t cros_gralloc_driver::get_backing_store(buffer_handle_t handle, uint64_t *out_store)
426 {
427         std::lock_guard<std::mutex> lock(mutex_);
428
429         auto hnd = cros_gralloc_convert_handle(handle);
430         if (!hnd) {
431                 drv_log("Invalid handle.\n");
432                 return -EINVAL;
433         }
434
435         auto buffer = get_buffer(hnd);
436         if (!buffer) {
437                 drv_log("Invalid Reference.\n");
438                 return -EINVAL;
439         }
440
441         *out_store = static_cast<uint64_t>(buffer->get_id());
442         return 0;
443 }
444
445 int32_t cros_gralloc_driver::resource_info(buffer_handle_t handle, uint32_t strides[DRV_MAX_PLANES],
446                                            uint32_t offsets[DRV_MAX_PLANES])
447 {
448         std::lock_guard<std::mutex> lock(mutex_);
449
450         auto hnd = cros_gralloc_convert_handle(handle);
451         if (!hnd) {
452                 drv_log("Invalid handle.\n");
453                 return -EINVAL;
454         }
455
456         auto buffer = get_buffer(hnd);
457         if (!buffer) {
458                 drv_log("Invalid Reference.\n");
459                 return -EINVAL;
460         }
461
462         return buffer->resource_info(strides, offsets);
463 }
464
465 int32_t cros_gralloc_driver::get_reserved_region(buffer_handle_t handle,
466                                                  void **reserved_region_addr,
467                                                  uint64_t *reserved_region_size)
468 {
469         std::lock_guard<std::mutex> lock(mutex_);
470
471         auto hnd = cros_gralloc_convert_handle(handle);
472         if (!hnd) {
473                 drv_log("Invalid handle.\n");
474                 return -EINVAL;
475         }
476
477         auto buffer = get_buffer(hnd);
478         if (!buffer) {
479                 drv_log("Invalid Reference.\n");
480                 return -EINVAL;
481         }
482
483         return buffer->get_reserved_region(reserved_region_addr, reserved_region_size);
484 }
485
486 uint32_t cros_gralloc_driver::get_resolved_drm_format(uint32_t drm_format, uint64_t usage)
487 {
488         return drv_resolve_format(drv_, drm_format, usage);
489 }
490
491 cros_gralloc_buffer *cros_gralloc_driver::get_buffer(cros_gralloc_handle_t hnd)
492 {
493         /* Assumes driver mutex is held. */
494         if (handles_.count(hnd))
495                 return handles_[hnd].first;
496
497         return nullptr;
498 }
499
500 void cros_gralloc_driver::for_each_handle(
501     const std::function<void(cros_gralloc_handle_t)> &function)
502 {
503         std::lock_guard<std::mutex> lock(mutex_);
504
505         for (const auto &pair : handles_) {
506                 function(pair.first);
507         }
508 }