OSDN Git Service

minigbm: Drop drv_bo_get_stride_in_pixels() helper
[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
95         struct bo *bo;
96         struct cros_gralloc_handle *hnd;
97
98         resolved_format = drv_resolve_format(drv_, descriptor->drm_format, descriptor->use_flags);
99         bo = drv_bo_create(drv_, descriptor->width, descriptor->height, resolved_format,
100                            descriptor->use_flags);
101         if (!bo) {
102                 drv_log("Failed to create bo.\n");
103                 return -ENOMEM;
104         }
105
106         /*
107          * If there is a desire for more than one kernel buffer, this can be
108          * removed once the ArcCodec and Wayland service have the ability to
109          * send more than one fd. GL/Vulkan drivers may also have to modified.
110          */
111         if (drv_num_buffers_per_bo(bo) != 1) {
112                 drv_bo_destroy(bo);
113                 drv_log("Can only support one buffer per bo.\n");
114                 return -EINVAL;
115         }
116
117         hnd = new cros_gralloc_handle();
118         num_planes = drv_bo_get_num_planes(bo);
119
120         hnd->base.version = sizeof(hnd->base);
121         hnd->base.numFds = num_planes;
122         hnd->base.numInts = handle_data_size - num_planes;
123
124         for (size_t plane = 0; plane < num_planes; plane++) {
125                 hnd->fds[plane] = drv_bo_get_plane_fd(bo, plane);
126                 hnd->strides[plane] = drv_bo_get_plane_stride(bo, plane);
127                 hnd->offsets[plane] = drv_bo_get_plane_offset(bo, plane);
128
129                 mod = drv_bo_get_plane_format_modifier(bo, plane);
130                 hnd->format_modifiers[2 * plane] = static_cast<uint32_t>(mod >> 32);
131                 hnd->format_modifiers[2 * plane + 1] = static_cast<uint32_t>(mod);
132         }
133
134         hnd->width = drv_bo_get_width(bo);
135         hnd->height = drv_bo_get_height(bo);
136         hnd->format = drv_bo_get_format(bo);
137         hnd->use_flags[0] = static_cast<uint32_t>(descriptor->use_flags >> 32);
138         hnd->use_flags[1] = static_cast<uint32_t>(descriptor->use_flags);
139         bytes_per_pixel = drv_bytes_per_pixel_from_format(hnd->format, 0);
140         hnd->pixel_stride = DIV_ROUND_UP(hnd->strides[0], bytes_per_pixel);
141         hnd->magic = cros_gralloc_magic;
142         hnd->droid_format = descriptor->droid_format;
143         hnd->usage = descriptor->producer_usage;
144
145         id = drv_bo_get_plane_handle(bo, 0).u32;
146         auto buffer = new cros_gralloc_buffer(id, bo, hnd);
147
148         std::lock_guard<std::mutex> lock(mutex_);
149         buffers_.emplace(id, buffer);
150         handles_.emplace(hnd, std::make_pair(buffer, 1));
151         *out_handle = &hnd->base;
152         return 0;
153 }
154
155 int32_t cros_gralloc_driver::retain(buffer_handle_t handle)
156 {
157         uint32_t id;
158         std::lock_guard<std::mutex> lock(mutex_);
159
160         auto hnd = cros_gralloc_convert_handle(handle);
161         if (!hnd) {
162                 drv_log("Invalid handle.\n");
163                 return -EINVAL;
164         }
165
166         auto buffer = get_buffer(hnd);
167         if (buffer) {
168                 handles_[hnd].second++;
169                 buffer->increase_refcount();
170                 return 0;
171         }
172
173         if (drmPrimeFDToHandle(drv_get_fd(drv_), hnd->fds[0], &id)) {
174                 drv_log("drmPrimeFDToHandle failed.\n");
175                 return -errno;
176         }
177
178         if (buffers_.count(id)) {
179                 buffer = buffers_[id];
180                 buffer->increase_refcount();
181         } else {
182                 struct bo *bo;
183                 struct drv_import_fd_data data;
184                 data.format = hnd->format;
185                 data.width = hnd->width;
186                 data.height = hnd->height;
187                 data.use_flags = static_cast<uint64_t>(hnd->use_flags[0]) << 32;
188                 data.use_flags |= hnd->use_flags[1];
189
190                 memcpy(data.fds, hnd->fds, sizeof(data.fds));
191                 memcpy(data.strides, hnd->strides, sizeof(data.strides));
192                 memcpy(data.offsets, hnd->offsets, sizeof(data.offsets));
193                 for (uint32_t plane = 0; plane < DRV_MAX_PLANES; plane++) {
194                         data.format_modifiers[plane] =
195                             static_cast<uint64_t>(hnd->format_modifiers[2 * plane]) << 32;
196                         data.format_modifiers[plane] |= hnd->format_modifiers[2 * plane + 1];
197                 }
198
199                 bo = drv_bo_import(drv_, &data);
200                 if (!bo)
201                         return -EFAULT;
202
203                 id = drv_bo_get_plane_handle(bo, 0).u32;
204
205                 buffer = new cros_gralloc_buffer(id, bo, nullptr);
206                 buffers_.emplace(id, buffer);
207         }
208
209         handles_.emplace(hnd, std::make_pair(buffer, 1));
210         return 0;
211 }
212
213 int32_t cros_gralloc_driver::release(buffer_handle_t handle)
214 {
215         std::lock_guard<std::mutex> lock(mutex_);
216
217         auto hnd = cros_gralloc_convert_handle(handle);
218         if (!hnd) {
219                 drv_log("Invalid handle.\n");
220                 return -EINVAL;
221         }
222
223         auto buffer = get_buffer(hnd);
224         if (!buffer) {
225                 drv_log("Invalid Reference.\n");
226                 return -EINVAL;
227         }
228
229         if (!--handles_[hnd].second)
230                 handles_.erase(hnd);
231
232         if (buffer->decrease_refcount() == 0) {
233                 buffers_.erase(buffer->get_id());
234                 delete buffer;
235         }
236
237         return 0;
238 }
239
240 int32_t cros_gralloc_driver::lock(buffer_handle_t handle, int32_t acquire_fence,
241                                   const struct rectangle *rect, uint32_t map_flags,
242                                   uint8_t *addr[DRV_MAX_PLANES])
243 {
244         int32_t ret = cros_gralloc_sync_wait(acquire_fence);
245         if (ret)
246                 return ret;
247
248         std::lock_guard<std::mutex> lock(mutex_);
249         auto hnd = cros_gralloc_convert_handle(handle);
250         if (!hnd) {
251                 drv_log("Invalid handle.\n");
252                 return -EINVAL;
253         }
254
255         auto buffer = get_buffer(hnd);
256         if (!buffer) {
257                 drv_log("Invalid Reference.\n");
258                 return -EINVAL;
259         }
260
261         return buffer->lock(rect, map_flags, addr);
262 }
263
264 int32_t cros_gralloc_driver::unlock(buffer_handle_t handle, int32_t *release_fence)
265 {
266         std::lock_guard<std::mutex> lock(mutex_);
267
268         auto hnd = cros_gralloc_convert_handle(handle);
269         if (!hnd) {
270                 drv_log("Invalid handle.\n");
271                 return -EINVAL;
272         }
273
274         auto buffer = get_buffer(hnd);
275         if (!buffer) {
276                 drv_log("Invalid Reference.\n");
277                 return -EINVAL;
278         }
279
280         /*
281          * From the ANativeWindow::dequeueBuffer documentation:
282          *
283          * "A value of -1 indicates that the caller may access the buffer immediately without
284          * waiting on a fence."
285          */
286         *release_fence = -1;
287         return buffer->unlock();
288 }
289
290 int32_t cros_gralloc_driver::get_backing_store(buffer_handle_t handle, uint64_t *out_store)
291 {
292         std::lock_guard<std::mutex> lock(mutex_);
293
294         auto hnd = cros_gralloc_convert_handle(handle);
295         if (!hnd) {
296                 drv_log("Invalid handle.\n");
297                 return -EINVAL;
298         }
299
300         auto buffer = get_buffer(hnd);
301         if (!buffer) {
302                 drv_log("Invalid Reference.\n");
303                 return -EINVAL;
304         }
305
306         *out_store = static_cast<uint64_t>(buffer->get_id());
307         return 0;
308 }
309
310 cros_gralloc_buffer *cros_gralloc_driver::get_buffer(cros_gralloc_handle_t hnd)
311 {
312         /* Assumes driver mutex is held. */
313         if (handles_.count(hnd))
314                 return handles_[hnd].first;
315
316         return nullptr;
317 }