OSDN Git Service

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