OSDN Git Service

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