OSDN Git Service

Reland "i915: Add GBM_BO_USE_HW_VIDEO_DECODER use flag"
[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 #include "../util.h"
9
10 #include <cstdlib>
11 #include <fcntl.h>
12 #include <xf86drm.h>
13
14 cros_gralloc_driver::cros_gralloc_driver() : drv_(nullptr)
15 {
16 }
17
18 cros_gralloc_driver::~cros_gralloc_driver()
19 {
20         buffers_.clear();
21         handles_.clear();
22
23         if (drv_) {
24                 drv_destroy(drv_);
25                 drv_ = nullptr;
26         }
27 }
28
29 int32_t cros_gralloc_driver::init()
30 {
31         /*
32          * Create a driver from rendernode while filtering out
33          * the specified undesired driver.
34          *
35          * TODO(gsingh): Enable render nodes on udl/evdi.
36          */
37
38         int fd;
39         drmVersionPtr version;
40         char const *str = "%s/renderD%d";
41         const char *undesired[2] = { "vgem", nullptr };
42         uint32_t num_nodes = 63;
43         uint32_t min_node = 128;
44         uint32_t max_node = (min_node + num_nodes);
45
46         for (uint32_t i = 0; i < ARRAY_SIZE(undesired); i++) {
47                 for (uint32_t j = min_node; j < max_node; j++) {
48                         char *node;
49                         if (asprintf(&node, str, DRM_DIR_NAME, j) < 0)
50                                 continue;
51
52                         fd = open(node, O_RDWR, 0);
53                         free(node);
54
55                         if (fd < 0)
56                                 continue;
57
58                         version = drmGetVersion(fd);
59                         if (!version)
60                                 continue;
61
62                         if (undesired[i] && !strcmp(version->name, undesired[i])) {
63                                 drmFreeVersion(version);
64                                 continue;
65                         }
66
67                         drmFreeVersion(version);
68                         drv_ = drv_create(fd);
69                         if (drv_)
70                                 return 0;
71                 }
72         }
73
74         return -ENODEV;
75 }
76
77 bool cros_gralloc_driver::is_supported(const struct cros_gralloc_buffer_descriptor *descriptor)
78 {
79         struct combination *combo;
80         uint32_t resolved_format;
81         resolved_format = drv_resolve_format(drv_, descriptor->drm_format, descriptor->use_flags);
82         combo = drv_get_combination(drv_, resolved_format, descriptor->use_flags);
83         return (combo != nullptr);
84 }
85
86 int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descriptor *descriptor,
87                                       buffer_handle_t *out_handle)
88 {
89         uint32_t id;
90         uint64_t mod;
91         size_t num_planes;
92         uint32_t resolved_format;
93         uint32_t bytes_per_pixel;
94         uint64_t use_flags;
95
96         struct bo *bo;
97         struct cros_gralloc_handle *hnd;
98
99         resolved_format = drv_resolve_format(drv_, descriptor->drm_format, descriptor->use_flags);
100         use_flags = descriptor->use_flags;
101         /*
102          * TODO(b/79682290): ARC++ assumes NV12 is always linear and doesn't
103          * send modifiers across Wayland protocol, so we or in the
104          * BO_USE_LINEAR flag here. We need to fix ARC++ to allocate and work
105          * with tiled buffers.
106          */
107         if (resolved_format == DRM_FORMAT_NV12)
108                 use_flags |= BO_USE_LINEAR;
109         bo = drv_bo_create(drv_, descriptor->width, descriptor->height, resolved_format,
110                            use_flags);
111         if (!bo) {
112                 drv_log("Failed to create bo.\n");
113                 return -ENOMEM;
114         }
115
116         /*
117          * If there is a desire for more than one kernel buffer, this can be
118          * removed once the ArcCodec and Wayland service have the ability to
119          * send more than one fd. GL/Vulkan drivers may also have to modified.
120          */
121         if (drv_num_buffers_per_bo(bo) != 1) {
122                 drv_bo_destroy(bo);
123                 drv_log("Can only support one buffer per bo.\n");
124                 return -EINVAL;
125         }
126
127         hnd = new cros_gralloc_handle();
128         num_planes = drv_bo_get_num_planes(bo);
129
130         hnd->base.version = sizeof(hnd->base);
131         hnd->base.numFds = num_planes;
132         hnd->base.numInts = handle_data_size - num_planes;
133
134         for (size_t plane = 0; plane < num_planes; plane++) {
135                 hnd->fds[plane] = drv_bo_get_plane_fd(bo, plane);
136                 hnd->strides[plane] = drv_bo_get_plane_stride(bo, plane);
137                 hnd->offsets[plane] = drv_bo_get_plane_offset(bo, plane);
138
139                 mod = drv_bo_get_plane_format_modifier(bo, plane);
140                 hnd->format_modifiers[2 * plane] = static_cast<uint32_t>(mod >> 32);
141                 hnd->format_modifiers[2 * plane + 1] = static_cast<uint32_t>(mod);
142         }
143
144         hnd->width = drv_bo_get_width(bo);
145         hnd->height = drv_bo_get_height(bo);
146         hnd->format = drv_bo_get_format(bo);
147         hnd->use_flags[0] = static_cast<uint32_t>(descriptor->use_flags >> 32);
148         hnd->use_flags[1] = static_cast<uint32_t>(descriptor->use_flags);
149         bytes_per_pixel = drv_bytes_per_pixel_from_format(hnd->format, 0);
150         hnd->pixel_stride = DIV_ROUND_UP(hnd->strides[0], bytes_per_pixel);
151         hnd->magic = cros_gralloc_magic;
152         hnd->droid_format = descriptor->droid_format;
153         hnd->usage = descriptor->producer_usage;
154
155         id = drv_bo_get_plane_handle(bo, 0).u32;
156         auto buffer = new cros_gralloc_buffer(id, bo, hnd);
157
158         std::lock_guard<std::mutex> lock(mutex_);
159         buffers_.emplace(id, buffer);
160         handles_.emplace(hnd, std::make_pair(buffer, 1));
161         *out_handle = &hnd->base;
162         return 0;
163 }
164
165 int32_t cros_gralloc_driver::retain(buffer_handle_t handle)
166 {
167         uint32_t id;
168         std::lock_guard<std::mutex> lock(mutex_);
169
170         auto hnd = cros_gralloc_convert_handle(handle);
171         if (!hnd) {
172                 drv_log("Invalid handle.\n");
173                 return -EINVAL;
174         }
175
176         auto buffer = get_buffer(hnd);
177         if (buffer) {
178                 handles_[hnd].second++;
179                 buffer->increase_refcount();
180                 return 0;
181         }
182
183         if (drmPrimeFDToHandle(drv_get_fd(drv_), hnd->fds[0], &id)) {
184                 drv_log("drmPrimeFDToHandle failed.\n");
185                 return -errno;
186         }
187
188         if (buffers_.count(id)) {
189                 buffer = buffers_[id];
190                 buffer->increase_refcount();
191         } else {
192                 struct bo *bo;
193                 struct drv_import_fd_data data;
194                 data.format = hnd->format;
195                 data.width = hnd->width;
196                 data.height = hnd->height;
197                 data.use_flags = static_cast<uint64_t>(hnd->use_flags[0]) << 32;
198                 data.use_flags |= hnd->use_flags[1];
199
200                 memcpy(data.fds, hnd->fds, sizeof(data.fds));
201                 memcpy(data.strides, hnd->strides, sizeof(data.strides));
202                 memcpy(data.offsets, hnd->offsets, sizeof(data.offsets));
203                 for (uint32_t plane = 0; plane < DRV_MAX_PLANES; plane++) {
204                         data.format_modifiers[plane] =
205                             static_cast<uint64_t>(hnd->format_modifiers[2 * plane]) << 32;
206                         data.format_modifiers[plane] |= hnd->format_modifiers[2 * plane + 1];
207                 }
208
209                 bo = drv_bo_import(drv_, &data);
210                 if (!bo)
211                         return -EFAULT;
212
213                 id = drv_bo_get_plane_handle(bo, 0).u32;
214
215                 buffer = new cros_gralloc_buffer(id, bo, nullptr);
216                 buffers_.emplace(id, buffer);
217         }
218
219         handles_.emplace(hnd, std::make_pair(buffer, 1));
220         return 0;
221 }
222
223 int32_t cros_gralloc_driver::release(buffer_handle_t handle)
224 {
225         std::lock_guard<std::mutex> lock(mutex_);
226
227         auto hnd = cros_gralloc_convert_handle(handle);
228         if (!hnd) {
229                 drv_log("Invalid handle.\n");
230                 return -EINVAL;
231         }
232
233         auto buffer = get_buffer(hnd);
234         if (!buffer) {
235                 drv_log("Invalid Reference.\n");
236                 return -EINVAL;
237         }
238
239         if (!--handles_[hnd].second)
240                 handles_.erase(hnd);
241
242         if (buffer->decrease_refcount() == 0) {
243                 buffers_.erase(buffer->get_id());
244                 delete buffer;
245         }
246
247         return 0;
248 }
249
250 int32_t cros_gralloc_driver::lock(buffer_handle_t handle, int32_t acquire_fence,
251                                   const struct rectangle *rect, uint32_t map_flags,
252                                   uint8_t *addr[DRV_MAX_PLANES])
253 {
254         int32_t ret = cros_gralloc_sync_wait(acquire_fence);
255         if (ret)
256                 return ret;
257
258         std::lock_guard<std::mutex> lock(mutex_);
259         auto hnd = cros_gralloc_convert_handle(handle);
260         if (!hnd) {
261                 drv_log("Invalid handle.\n");
262                 return -EINVAL;
263         }
264
265         auto buffer = get_buffer(hnd);
266         if (!buffer) {
267                 drv_log("Invalid Reference.\n");
268                 return -EINVAL;
269         }
270
271         return buffer->lock(rect, map_flags, addr);
272 }
273
274 int32_t cros_gralloc_driver::unlock(buffer_handle_t handle, int32_t *release_fence)
275 {
276         std::lock_guard<std::mutex> lock(mutex_);
277
278         auto hnd = cros_gralloc_convert_handle(handle);
279         if (!hnd) {
280                 drv_log("Invalid handle.\n");
281                 return -EINVAL;
282         }
283
284         auto buffer = get_buffer(hnd);
285         if (!buffer) {
286                 drv_log("Invalid Reference.\n");
287                 return -EINVAL;
288         }
289
290         /*
291          * From the ANativeWindow::dequeueBuffer documentation:
292          *
293          * "A value of -1 indicates that the caller may access the buffer immediately without
294          * waiting on a fence."
295          */
296         *release_fence = -1;
297         return buffer->unlock();
298 }
299
300 int32_t cros_gralloc_driver::get_backing_store(buffer_handle_t handle, uint64_t *out_store)
301 {
302         std::lock_guard<std::mutex> lock(mutex_);
303
304         auto hnd = cros_gralloc_convert_handle(handle);
305         if (!hnd) {
306                 drv_log("Invalid handle.\n");
307                 return -EINVAL;
308         }
309
310         auto buffer = get_buffer(hnd);
311         if (!buffer) {
312                 drv_log("Invalid Reference.\n");
313                 return -EINVAL;
314         }
315
316         *out_store = static_cast<uint64_t>(buffer->get_id());
317         return 0;
318 }
319
320 cros_gralloc_buffer *cros_gralloc_driver::get_buffer(cros_gralloc_handle_t hnd)
321 {
322         /* Assumes driver mutex is held. */
323         if (handles_.count(hnd))
324                 return handles_[hnd].first;
325
326         return nullptr;
327 }