OSDN Git Service

Merge remote-tracking branch 'aosp/upstream-master' into HEAD
[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, struct cros_gralloc_bo **bo)
14 {
15         if (!mod->handles.count(hnd))
16                 return CROS_GRALLOC_ERROR_BAD_HANDLE;
17
18         *bo = mod->handles[hnd].bo;
19         return CROS_GRALLOC_ERROR_NONE;
20 }
21
22 int cros_gralloc_decrement_reference_count(struct cros_gralloc_module *mod,
23                                            struct cros_gralloc_bo *bo)
24 {
25         if (bo->refcount <= 0) {
26                 cros_gralloc_error("The reference count is <= 0.");
27                 assert(0);
28         }
29
30         if (!--bo->refcount) {
31                 mod->buffers.erase(drv_bo_get_plane_handle(bo->bo, 0).u32);
32                 drv_bo_destroy(bo->bo);
33
34                 if (bo->hnd) {
35                         mod->handles.erase(bo->hnd);
36                         native_handle_close(&bo->hnd->base);
37                         delete bo->hnd;
38                 }
39
40                 delete bo;
41         }
42
43         return CROS_GRALLOC_ERROR_NONE;
44 }
45
46 static int cros_gralloc_register_buffer(struct gralloc_module_t const *module,
47                                         buffer_handle_t handle)
48 {
49         uint32_t id;
50         struct cros_gralloc_bo *bo;
51         auto hnd = (struct cros_gralloc_handle *)handle;
52         auto mod = (struct cros_gralloc_module *)module;
53         std::lock_guard<std::mutex> lock(mod->mutex);
54
55         if (cros_gralloc_validate_handle(hnd)) {
56                 cros_gralloc_error("Invalid handle.");
57                 return CROS_GRALLOC_ERROR_BAD_HANDLE;
58         }
59
60         if (!mod->drv) {
61                 if (cros_gralloc_rendernode_open(&mod->drv)) {
62                         cros_gralloc_error("Failed to open render node.");
63                         return CROS_GRALLOC_ERROR_NO_RESOURCES;
64                 }
65         }
66
67         if (!cros_gralloc_validate_reference(mod, hnd, &bo)) {
68                 bo->refcount++;
69                 mod->handles[hnd].registrations++;
70                 return CROS_GRALLOC_ERROR_NONE;
71         }
72
73         if (drmPrimeFDToHandle(drv_get_fd(mod->drv), hnd->fds[0], &id)) {
74                 cros_gralloc_error("drmPrimeFDToHandle failed.");
75                 return CROS_GRALLOC_ERROR_BAD_HANDLE;
76         }
77
78         if (mod->buffers.count(id)) {
79                 bo = mod->buffers[id];
80                 bo->refcount++;
81         } else {
82                 struct drv_import_fd_data data;
83                 data.format = hnd->format;
84                 data.width = hnd->width;
85                 data.height = hnd->height;
86
87                 memcpy(data.fds, hnd->fds, sizeof(data.fds));
88                 memcpy(data.strides, hnd->strides, sizeof(data.strides));
89                 memcpy(data.offsets, hnd->offsets, sizeof(data.offsets));
90                 memcpy(data.sizes, hnd->sizes, sizeof(data.sizes));
91                 for (uint32_t p = 0; p < DRV_MAX_PLANES; p++) {
92                         data.format_modifiers[p] =
93                             static_cast<uint64_t>(hnd->format_modifiers[2 * p]) << 32;
94                         data.format_modifiers[p] |= hnd->format_modifiers[2 * p + 1];
95                 }
96
97                 bo = new cros_gralloc_bo();
98                 bo->bo = drv_bo_import(mod->drv, &data);
99                 if (!bo->bo) {
100                         delete bo;
101                         return CROS_GRALLOC_ERROR_NO_RESOURCES;
102                 }
103
104                 id = drv_bo_get_plane_handle(bo->bo, 0).u32;
105                 mod->buffers[id] = bo;
106
107                 bo->refcount = 1;
108         }
109
110         mod->handles[hnd].bo = bo;
111         mod->handles[hnd].registrations = 1;
112
113         return CROS_GRALLOC_ERROR_NONE;
114 }
115
116 static int cros_gralloc_unregister_buffer(struct gralloc_module_t const *module,
117                                           buffer_handle_t handle)
118 {
119         struct cros_gralloc_bo *bo;
120         auto hnd = (struct cros_gralloc_handle *)handle;
121         auto mod = (struct cros_gralloc_module *)module;
122         std::lock_guard<std::mutex> lock(mod->mutex);
123
124         if (cros_gralloc_validate_handle(hnd)) {
125                 cros_gralloc_error("Invalid handle.");
126                 return CROS_GRALLOC_ERROR_BAD_HANDLE;
127         }
128
129         if (cros_gralloc_validate_reference(mod, hnd, &bo)) {
130                 cros_gralloc_error("Invalid Reference.");
131                 return CROS_GRALLOC_ERROR_BAD_HANDLE;
132         }
133
134         if (mod->handles[hnd].registrations <= 0) {
135                 cros_gralloc_error("Handle not registered.");
136                 return CROS_GRALLOC_ERROR_BAD_HANDLE;
137         }
138
139         mod->handles[hnd].registrations--;
140
141         if (!mod->handles[hnd].registrations)
142                 mod->handles.erase(hnd);
143
144         return cros_gralloc_decrement_reference_count(mod, bo);
145 }
146
147 static int cros_gralloc_lock(struct gralloc_module_t const *module, buffer_handle_t handle,
148                              int usage, int l, int t, int w, int h, void **vaddr)
149 {
150         struct cros_gralloc_bo *bo;
151         auto mod = (struct cros_gralloc_module *)module;
152         auto hnd = (struct cros_gralloc_handle *)handle;
153         std::lock_guard<std::mutex> lock(mod->mutex);
154
155         if (cros_gralloc_validate_handle(hnd)) {
156                 cros_gralloc_error("Invalid handle.");
157                 return CROS_GRALLOC_ERROR_BAD_HANDLE;
158         }
159
160         if (cros_gralloc_validate_reference(mod, hnd, &bo)) {
161                 cros_gralloc_error("Invalid Reference.");
162                 return CROS_GRALLOC_ERROR_BAD_HANDLE;
163         }
164
165         if ((hnd->droid_format == HAL_PIXEL_FORMAT_YCbCr_420_888)) {
166                 cros_gralloc_error("HAL_PIXEL_FORMAT_YCbCr_*_888 format not compatible.");
167                 return CROS_GRALLOC_ERROR_BAD_HANDLE;
168         }
169
170         if (sw_access & usage) {
171                 if (bo->map_data) {
172                         *vaddr = bo->map_data->addr;
173                 } else {
174                         *vaddr = drv_bo_map(bo->bo, 0, 0, drv_bo_get_width(bo->bo),
175                                             drv_bo_get_height(bo->bo), 0, &bo->map_data, 0);
176                 }
177
178                 if (*vaddr == MAP_FAILED) {
179                         cros_gralloc_error("Mapping failed.");
180                         return CROS_GRALLOC_ERROR_UNSUPPORTED;
181                 }
182         }
183
184         bo->lockcount++;
185
186         return CROS_GRALLOC_ERROR_NONE;
187 }
188
189 static int cros_gralloc_unlock(struct gralloc_module_t const *module, buffer_handle_t handle)
190 {
191         struct cros_gralloc_bo *bo;
192         auto hnd = (struct cros_gralloc_handle *)handle;
193         auto mod = (struct cros_gralloc_module *)module;
194         std::lock_guard<std::mutex> lock(mod->mutex);
195
196         if (cros_gralloc_validate_handle(hnd)) {
197                 cros_gralloc_error("Invalid handle.");
198                 return CROS_GRALLOC_ERROR_BAD_HANDLE;
199         }
200
201         if (cros_gralloc_validate_reference(mod, hnd, &bo)) {
202                 cros_gralloc_error("Invalid Reference.");
203                 return CROS_GRALLOC_ERROR_BAD_HANDLE;
204         }
205
206         if (!--bo->lockcount && bo->map_data) {
207                 drv_bo_unmap(bo->bo, bo->map_data);
208                 bo->map_data = NULL;
209         }
210
211         return CROS_GRALLOC_ERROR_NONE;
212 }
213
214 static int cros_gralloc_perform(struct gralloc_module_t const *module, 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, buffer_handle_t handle,
278                                    int usage, int l, int t, int w, int h,
279                                    struct android_ycbcr *ycbcr)
280 {
281         uint8_t *addr = NULL;
282         size_t offsets[DRV_MAX_PLANES];
283         struct cros_gralloc_bo *bo;
284         auto hnd = (struct cros_gralloc_handle *)handle;
285         auto mod = (struct cros_gralloc_module *)module;
286         std::lock_guard<std::mutex> lock(mod->mutex);
287
288         if (cros_gralloc_validate_handle(hnd)) {
289                 cros_gralloc_error("Invalid handle.");
290                 return CROS_GRALLOC_ERROR_BAD_HANDLE;
291         }
292
293         if (cros_gralloc_validate_reference(mod, hnd, &bo)) {
294                 cros_gralloc_error("Invalid Reference.");
295                 return CROS_GRALLOC_ERROR_BAD_HANDLE;
296         }
297
298         if ((hnd->droid_format != HAL_PIXEL_FORMAT_YCbCr_420_888) &&
299             (hnd->droid_format != HAL_PIXEL_FORMAT_YV12)) {
300                 cros_gralloc_error("Non-YUV format not compatible.");
301                 return CROS_GRALLOC_ERROR_BAD_HANDLE;
302         }
303
304         if (sw_access & usage) {
305                 void *vaddr;
306                 if (bo->map_data) {
307                         vaddr = bo->map_data->addr;
308                 } else {
309                         vaddr = drv_bo_map(bo->bo, 0, 0, drv_bo_get_width(bo->bo),
310                                            drv_bo_get_height(bo->bo), 0, &bo->map_data, 0);
311                 }
312
313                 if (vaddr == MAP_FAILED) {
314                         cros_gralloc_error("Mapping failed.");
315                         return CROS_GRALLOC_ERROR_UNSUPPORTED;
316                 }
317
318                 addr = static_cast<uint8_t *>(vaddr);
319         }
320
321         for (size_t p = 0; p < drv_bo_get_num_planes(bo->bo); p++)
322                 offsets[p] = drv_bo_get_plane_offset(bo->bo, p);
323
324         switch (hnd->format) {
325         case DRM_FORMAT_NV12:
326                 ycbcr->y = addr;
327                 ycbcr->cb = addr + offsets[1];
328                 ycbcr->cr = addr + offsets[1] + 1;
329                 ycbcr->ystride = drv_bo_get_plane_stride(bo->bo, 0);
330                 ycbcr->cstride = drv_bo_get_plane_stride(bo->bo, 1);
331                 ycbcr->chroma_step = 2;
332                 break;
333         case DRM_FORMAT_YVU420_ANDROID:
334                 ycbcr->y = addr;
335                 ycbcr->cb = addr + offsets[2];
336                 ycbcr->cr = addr + offsets[1];
337                 ycbcr->ystride = drv_bo_get_plane_stride(bo->bo, 0);
338                 ycbcr->cstride = drv_bo_get_plane_stride(bo->bo, 1);
339                 ycbcr->chroma_step = 1;
340                 break;
341         case DRM_FORMAT_UYVY:
342                 ycbcr->y = addr + 1;
343                 ycbcr->cb = addr;
344                 ycbcr->cr = addr + 2;
345                 ycbcr->ystride = drv_bo_get_plane_stride(bo->bo, 0);
346                 ycbcr->cstride = drv_bo_get_plane_stride(bo->bo, 0);
347                 ycbcr->chroma_step = 2;
348                 break;
349         default:
350                 return CROS_GRALLOC_ERROR_UNSUPPORTED;
351         }
352
353         bo->lockcount++;
354
355         return CROS_GRALLOC_ERROR_NONE;
356 }
357
358 static struct hw_module_methods_t cros_gralloc_module_methods = {.open = cros_gralloc_open };
359
360 struct cros_gralloc_module HAL_MODULE_INFO_SYM = {
361         .base =
362             {
363                 .common =
364                     {
365                         .tag = HARDWARE_MODULE_TAG,
366                         .module_api_version = GRALLOC_MODULE_API_VERSION_0_2,
367                         .hal_api_version = 0,
368                         .id = GRALLOC_HARDWARE_MODULE_ID,
369                         .name = "CrOS Gralloc",
370                         .author = "Chrome OS",
371                         .methods = &cros_gralloc_module_methods,
372                     },
373                 .registerBuffer = cros_gralloc_register_buffer,
374                 .unregisterBuffer = cros_gralloc_unregister_buffer,
375                 .lock = cros_gralloc_lock,
376                 .unlock = cros_gralloc_unlock,
377                 .perform = cros_gralloc_perform,
378                 .lock_ycbcr = cros_gralloc_lock_ycbcr,
379             },
380
381         .drv = NULL,
382 };