OSDN Git Service

minigbm: cros_gralloc: remove unnecessary information from handle
[android-x86/external-minigbm.git] / cros_gralloc / cros_gralloc_module.cc
1 /*
2  * Copyright 2016 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.h"
8
9 #include <sys/mman.h>
10 #include <xf86drm.h>
11
12 int cros_gralloc_validate_reference(struct cros_gralloc_module *mod,
13                                     struct cros_gralloc_handle *hnd,
14                                     struct cros_gralloc_bo **bo)
15 {
16         if (!mod->handles.count(hnd))
17                 return CROS_GRALLOC_ERROR_BAD_HANDLE;
18
19         *bo = mod->handles[hnd].bo;
20         return CROS_GRALLOC_ERROR_NONE;
21 }
22
23 int cros_gralloc_decrement_reference_count(struct cros_gralloc_module *mod,
24                                            struct cros_gralloc_bo *bo)
25 {
26         if (bo->refcount <= 0) {
27                 cros_gralloc_error("The reference count is <= 0.");
28                 assert(0);
29         }
30
31         if (!--bo->refcount) {
32                 mod->buffers.erase(drv_bo_get_plane_handle(bo->bo, 0).u32);
33                 drv_bo_destroy(bo->bo);
34
35                 if (bo->hnd) {
36                         mod->handles.erase(bo->hnd);
37                         native_handle_close(&bo->hnd->base);
38                         delete bo->hnd;
39                 }
40
41                 delete bo;
42         }
43
44         return CROS_GRALLOC_ERROR_NONE;
45 }
46
47 static int cros_gralloc_register_buffer(struct gralloc_module_t const* module,
48                                         buffer_handle_t handle)
49 {
50         uint32_t id;
51         struct cros_gralloc_bo *bo;
52         auto hnd = (struct cros_gralloc_handle *) handle;
53         auto mod = (struct cros_gralloc_module *) module;
54         std::lock_guard<std::mutex> lock(mod->mutex);
55
56         if (cros_gralloc_validate_handle(hnd)) {
57                 cros_gralloc_error("Invalid handle.");
58                 return CROS_GRALLOC_ERROR_BAD_HANDLE;
59         }
60
61         if (!mod->drv) {
62                 if (cros_gralloc_rendernode_open(&mod->drv)) {
63                         cros_gralloc_error("Failed to open render node.");
64                         return CROS_GRALLOC_ERROR_NO_RESOURCES;
65                 }
66         }
67
68         if (!cros_gralloc_validate_reference(mod, hnd, &bo)) {
69                 bo->refcount++;
70                 mod->handles[hnd].registrations++;
71                 return CROS_GRALLOC_ERROR_NONE;
72         }
73
74         if (drmPrimeFDToHandle(drv_get_fd(mod->drv), hnd->fds[0], &id)) {
75                 cros_gralloc_error("drmPrimeFDToHandle failed.");
76                 return CROS_GRALLOC_ERROR_BAD_HANDLE;
77         }
78
79         if (mod->buffers.count(id)) {
80                 bo = mod->buffers[id];
81                 bo->refcount++;
82         } else {
83                 struct drv_import_fd_data data;
84                 size_t num_planes = drv_num_planes_from_format(hnd->format);
85
86                 data.format = hnd->format;
87                 data.width = hnd->width;
88                 data.height = hnd->height;
89                 for (size_t p = 0; p < num_planes; p++) {
90                         data.fds[p] = hnd->fds[p];
91                         data.strides[p] = hnd->strides[p];
92                         data.offsets[p] = hnd->offsets[p];
93                         data.sizes[p] = hnd->sizes[p];
94                         data.format_modifiers[p] = static_cast<uint64_t>
95                                 (hnd->format_modifiers[p]) << 32;
96                         data.format_modifiers[p] |= hnd->format_modifiers[p+1];
97                 }
98
99                 bo = new cros_gralloc_bo();
100
101                 bo->bo = drv_bo_import(mod->drv, &data);
102                 if (!bo->bo) {
103                         delete bo;
104                         return CROS_GRALLOC_ERROR_NO_RESOURCES;
105                 }
106
107                 id = drv_bo_get_plane_handle(bo->bo, 0).u32;
108                 mod->buffers[id] = bo;
109
110                 bo->refcount = 1;
111         }
112
113         mod->handles[hnd].bo = bo;
114         mod->handles[hnd].registrations = 1;
115
116         return CROS_GRALLOC_ERROR_NONE;
117 }
118
119 static int cros_gralloc_unregister_buffer(struct gralloc_module_t const* module,
120                                           buffer_handle_t handle)
121 {
122         struct cros_gralloc_bo *bo;
123         auto hnd = (struct cros_gralloc_handle *) handle;
124         auto mod = (struct cros_gralloc_module *) module;
125         std::lock_guard<std::mutex> lock(mod->mutex);
126
127         if (cros_gralloc_validate_handle(hnd)) {
128                 cros_gralloc_error("Invalid handle.");
129                 return CROS_GRALLOC_ERROR_BAD_HANDLE;
130         }
131
132         if (cros_gralloc_validate_reference(mod, hnd, &bo)) {
133                 cros_gralloc_error("Invalid Reference.");
134                 return CROS_GRALLOC_ERROR_BAD_HANDLE;
135         }
136
137         if (mod->handles[hnd].registrations <= 0) {
138                 cros_gralloc_error("Handle not registered.");
139                 return CROS_GRALLOC_ERROR_BAD_HANDLE;
140         }
141
142         mod->handles[hnd].registrations--;
143
144         if (!mod->handles[hnd].registrations)
145                 mod->handles.erase(hnd);
146
147         return cros_gralloc_decrement_reference_count(mod, bo);
148 }
149
150 static int cros_gralloc_lock(struct gralloc_module_t const* module,
151                              buffer_handle_t handle, int usage, int l, int t,
152                              int w, int h, void** vaddr)
153 {
154         struct cros_gralloc_bo *bo;
155         auto mod = (struct cros_gralloc_module *) module;
156         auto hnd = (struct cros_gralloc_handle *) handle;
157         std::lock_guard<std::mutex> lock(mod->mutex);
158
159         if (cros_gralloc_validate_handle(hnd)) {
160                 cros_gralloc_error("Invalid handle.");
161                 return CROS_GRALLOC_ERROR_BAD_HANDLE;
162         }
163
164         if (cros_gralloc_validate_reference(mod, hnd, &bo)) {
165                 cros_gralloc_error("Invalid Reference.");
166                 return CROS_GRALLOC_ERROR_BAD_HANDLE;
167         }
168
169         if ((hnd->droid_format == HAL_PIXEL_FORMAT_YCbCr_420_888)) {
170                 cros_gralloc_error("HAL_PIXEL_FORMAT_YCbCr_*_888 format not "
171                                    "compatible.");
172                 return CROS_GRALLOC_ERROR_BAD_HANDLE;
173         }
174
175         if (sw_access() & usage) {
176                 *vaddr = drv_bo_map(bo->bo, 0, 0, drv_bo_get_width(bo->bo),
177                                    drv_bo_get_height(bo->bo), 0, &bo->map_data,
178                                    0);
179
180                 if (*vaddr == MAP_FAILED) {
181                         cros_gralloc_error("Mapping failed.");
182                         return CROS_GRALLOC_ERROR_UNSUPPORTED;
183                 }
184         }
185
186         return CROS_GRALLOC_ERROR_NONE;
187 }
188
189 static int cros_gralloc_unlock(struct gralloc_module_t const* module,
190                                buffer_handle_t handle)
191 {
192         struct cros_gralloc_bo *bo;
193         auto hnd = (struct cros_gralloc_handle *) handle;
194         auto mod = (struct cros_gralloc_module *) module;
195         std::lock_guard<std::mutex> lock(mod->mutex);
196
197         if (cros_gralloc_validate_handle(hnd)) {
198                 cros_gralloc_error("Invalid handle.");
199                 return CROS_GRALLOC_ERROR_BAD_HANDLE;
200         }
201
202         if (cros_gralloc_validate_reference(mod, hnd, &bo)) {
203                 cros_gralloc_error("Invalid Reference.");
204                 return CROS_GRALLOC_ERROR_BAD_HANDLE;
205         }
206
207         if (bo->map_data)
208                 drv_bo_unmap(bo->bo, bo->map_data);
209
210         return CROS_GRALLOC_ERROR_NONE;
211 }
212
213 static int cros_gralloc_perform(struct gralloc_module_t const* module,
214                                 int op, ... )
215 {
216         va_list args;
217         struct cros_gralloc_bo *bo;
218         int32_t *out_format;
219         uint64_t *out_store;
220         buffer_handle_t handle;
221         uint32_t *out_width, *out_height, *out_stride;
222         auto mod = (struct cros_gralloc_module *) module;
223         std::lock_guard<std::mutex> lock(mod->mutex);
224
225         switch (op) {
226         case GRALLOC_DRM_GET_STRIDE:
227         case GRALLOC_DRM_GET_FORMAT:
228         case GRALLOC_DRM_GET_DIMENSIONS:
229         case GRALLOC_DRM_GET_BACKING_STORE:
230                 break;
231         default:
232                 return CROS_GRALLOC_ERROR_UNSUPPORTED;
233         }
234
235         va_start(args, op);
236         handle = va_arg(args, buffer_handle_t);
237         auto hnd = (struct cros_gralloc_handle *) handle;
238
239         if (cros_gralloc_validate_handle(hnd)) {
240                 cros_gralloc_error("Invalid handle.");
241                 return CROS_GRALLOC_ERROR_BAD_HANDLE;
242         }
243
244         if (cros_gralloc_validate_reference(mod, hnd, &bo)) {
245                 cros_gralloc_error("Invalid Reference.");
246                 return CROS_GRALLOC_ERROR_BAD_HANDLE;
247         }
248
249         switch (op) {
250         case GRALLOC_DRM_GET_STRIDE:
251                 out_stride = va_arg(args, uint32_t *);
252                 *out_stride = hnd->pixel_stride;
253                 break;
254         case GRALLOC_DRM_GET_FORMAT:
255                 out_format = va_arg(args, int32_t *);
256                 *out_format = hnd->droid_format;
257                 break;
258         case GRALLOC_DRM_GET_DIMENSIONS:
259                 out_width = va_arg(args, uint32_t *);
260                 out_height = va_arg(args, uint32_t *);
261                 *out_width = hnd->width;
262                 *out_height = hnd->height;
263                 break;
264         case GRALLOC_DRM_GET_BACKING_STORE:
265                 out_store = va_arg(args, uint64_t *);
266                 *out_store = drv_bo_get_plane_handle(bo->bo, 0).u64;
267                 break;
268         default:
269                 return CROS_GRALLOC_ERROR_UNSUPPORTED;
270         }
271
272         va_end(args);
273
274         return CROS_GRALLOC_ERROR_NONE;
275 }
276
277 static int cros_gralloc_lock_ycbcr(struct gralloc_module_t const* module,
278                                    buffer_handle_t handle, int usage, int l,
279                                    int t, int w, int h,
280                                    struct android_ycbcr *ycbcr)
281 {
282         uint8_t *addr = NULL;
283         size_t offsets[DRV_MAX_PLANES];
284         struct cros_gralloc_bo *bo;
285         auto hnd = (struct cros_gralloc_handle *) handle;
286         auto mod = (struct cros_gralloc_module *) module;
287         std::lock_guard<std::mutex> lock(mod->mutex);
288
289         if (cros_gralloc_validate_handle(hnd)) {
290                 cros_gralloc_error("Invalid handle.");
291                 return CROS_GRALLOC_ERROR_BAD_HANDLE;
292         }
293
294         if (cros_gralloc_validate_reference(mod, hnd, &bo)) {
295                 cros_gralloc_error("Invalid Reference.");
296                 return CROS_GRALLOC_ERROR_BAD_HANDLE;
297         }
298
299         if ((hnd->droid_format != HAL_PIXEL_FORMAT_YCbCr_420_888) &&
300             (hnd->droid_format != HAL_PIXEL_FORMAT_YV12)) {
301                 cros_gralloc_error("Non-YUV format not compatible.");
302                 return CROS_GRALLOC_ERROR_BAD_HANDLE;
303         }
304
305         if (sw_access() & usage) {
306                 void *vaddr = drv_bo_map(bo->bo, 0, 0, drv_bo_get_width(bo->bo),
307                                          drv_bo_get_height(bo->bo), 0,
308                                          &bo->map_data, 0);
309
310                 if (vaddr == MAP_FAILED) {
311                         cros_gralloc_error("Mapping failed.");
312                         return CROS_GRALLOC_ERROR_UNSUPPORTED;
313                 }
314
315                 addr = static_cast<uint8_t*>(vaddr);
316         }
317
318         for (size_t p = 0; p < drv_bo_get_num_planes(bo->bo); p++)
319                 offsets[p] = drv_bo_get_plane_offset(bo->bo, p);
320
321         switch (hnd->format) {
322         case DRM_FORMAT_NV12:
323                 ycbcr->y = addr;
324                 ycbcr->cb = addr + offsets[1];
325                 ycbcr->cr = addr + offsets[1] + 1;
326                 ycbcr->ystride = drv_bo_get_plane_stride(bo->bo, 0);
327                 ycbcr->cstride = drv_bo_get_plane_stride(bo->bo, 1);
328                 ycbcr->chroma_step = 2;
329                 break;
330         case DRM_FORMAT_YVU420:
331                 ycbcr->y = addr;
332                 ycbcr->cb = addr + offsets[2];
333                 ycbcr->cr = addr + offsets[1];
334                 ycbcr->ystride = drv_bo_get_plane_stride(bo->bo, 0);
335                 ycbcr->cstride = drv_bo_get_plane_stride(bo->bo, 1);
336                 ycbcr->chroma_step = 1;
337                 break;
338         case DRM_FORMAT_UYVY:
339                 ycbcr->y = addr + 1;
340                 ycbcr->cb = addr;
341                 ycbcr->cr = addr + 2;
342                 ycbcr->ystride = drv_bo_get_plane_stride(bo->bo, 0);
343                 ycbcr->cstride = drv_bo_get_plane_stride(bo->bo, 0);
344                 ycbcr->chroma_step = 2;
345                 break;
346         default:
347                 return CROS_GRALLOC_ERROR_UNSUPPORTED;
348         }
349
350         return CROS_GRALLOC_ERROR_NONE;
351 }
352
353 static struct hw_module_methods_t cros_gralloc_module_methods = {
354         .open = cros_gralloc_open
355 };
356
357 struct cros_gralloc_module HAL_MODULE_INFO_SYM = {
358         .base = {
359                 .common = {
360                         .tag = HARDWARE_MODULE_TAG,
361                         .module_api_version = GRALLOC_MODULE_API_VERSION_0_2,
362                         .hal_api_version = 0,
363                         .id = GRALLOC_HARDWARE_MODULE_ID,
364                         .name = "CrOS Gralloc",
365                         .author = "Chrome OS",
366                         .methods = &cros_gralloc_module_methods,
367                 },
368                 .registerBuffer = cros_gralloc_register_buffer,
369                 .unregisterBuffer = cros_gralloc_unregister_buffer,
370                 .lock = cros_gralloc_lock,
371                 .unlock = cros_gralloc_unlock,
372                 .perform = cros_gralloc_perform,
373                 .lock_ycbcr = cros_gralloc_lock_ycbcr,
374         },
375
376         .drv = NULL,
377 };