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.
7 #include "cros_gralloc.h"
12 int cros_gralloc_validate_reference(struct cros_gralloc_module *mod,
13 struct cros_gralloc_handle *hnd,
14 struct cros_gralloc_bo **bo)
16 if (!mod->handles.count(hnd))
17 return CROS_GRALLOC_ERROR_BAD_HANDLE;
19 *bo = mod->handles[hnd].bo;
20 return CROS_GRALLOC_ERROR_NONE;
23 int cros_gralloc_decrement_reference_count(struct cros_gralloc_module *mod,
24 struct cros_gralloc_bo *bo)
26 if (bo->refcount <= 0) {
27 cros_gralloc_error("The reference count is <= 0.");
31 if (!--bo->refcount) {
32 mod->buffers.erase(drv_bo_get_plane_handle(bo->bo, 0).u32);
33 drv_bo_destroy(bo->bo);
36 mod->handles.erase(bo->hnd);
37 native_handle_close(&bo->hnd->base);
44 return CROS_GRALLOC_ERROR_NONE;
47 static int cros_gralloc_register_buffer(struct gralloc_module_t const* module,
48 buffer_handle_t handle)
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);
56 if (cros_gralloc_validate_handle(hnd)) {
57 cros_gralloc_error("Invalid handle.");
58 return CROS_GRALLOC_ERROR_BAD_HANDLE;
62 if (cros_gralloc_rendernode_open(&mod->drv)) {
63 cros_gralloc_error("Failed to open render node.");
64 return CROS_GRALLOC_ERROR_NO_RESOURCES;
68 if (!cros_gralloc_validate_reference(mod, hnd, &bo)) {
70 mod->handles[hnd].registrations++;
71 return CROS_GRALLOC_ERROR_NONE;
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;
79 if (mod->buffers.count(id)) {
80 bo = mod->buffers[id];
83 struct drv_import_fd_data data;
84 size_t num_planes = drv_num_planes_from_format(hnd->format);
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];
99 bo = new cros_gralloc_bo();
101 bo->bo = drv_bo_import(mod->drv, &data);
104 return CROS_GRALLOC_ERROR_NO_RESOURCES;
107 id = drv_bo_get_plane_handle(bo->bo, 0).u32;
108 mod->buffers[id] = bo;
113 mod->handles[hnd].bo = bo;
114 mod->handles[hnd].registrations = 1;
116 return CROS_GRALLOC_ERROR_NONE;
119 static int cros_gralloc_unregister_buffer(struct gralloc_module_t const* module,
120 buffer_handle_t handle)
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);
127 if (cros_gralloc_validate_handle(hnd)) {
128 cros_gralloc_error("Invalid handle.");
129 return CROS_GRALLOC_ERROR_BAD_HANDLE;
132 if (cros_gralloc_validate_reference(mod, hnd, &bo)) {
133 cros_gralloc_error("Invalid Reference.");
134 return CROS_GRALLOC_ERROR_BAD_HANDLE;
137 if (mod->handles[hnd].registrations <= 0) {
138 cros_gralloc_error("Handle not registered.");
139 return CROS_GRALLOC_ERROR_BAD_HANDLE;
142 mod->handles[hnd].registrations--;
144 if (!mod->handles[hnd].registrations)
145 mod->handles.erase(hnd);
147 return cros_gralloc_decrement_reference_count(mod, bo);
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)
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);
159 if (cros_gralloc_validate_handle(hnd)) {
160 cros_gralloc_error("Invalid handle.");
161 return CROS_GRALLOC_ERROR_BAD_HANDLE;
164 if (cros_gralloc_validate_reference(mod, hnd, &bo)) {
165 cros_gralloc_error("Invalid Reference.");
166 return CROS_GRALLOC_ERROR_BAD_HANDLE;
169 if ((hnd->droid_format == HAL_PIXEL_FORMAT_YCbCr_420_888)) {
170 cros_gralloc_error("HAL_PIXEL_FORMAT_YCbCr_*_888 format not "
172 return CROS_GRALLOC_ERROR_BAD_HANDLE;
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,
180 if (*vaddr == MAP_FAILED) {
181 cros_gralloc_error("Mapping failed.");
182 return CROS_GRALLOC_ERROR_UNSUPPORTED;
186 return CROS_GRALLOC_ERROR_NONE;
189 static int cros_gralloc_unlock(struct gralloc_module_t const* module,
190 buffer_handle_t handle)
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);
197 if (cros_gralloc_validate_handle(hnd)) {
198 cros_gralloc_error("Invalid handle.");
199 return CROS_GRALLOC_ERROR_BAD_HANDLE;
202 if (cros_gralloc_validate_reference(mod, hnd, &bo)) {
203 cros_gralloc_error("Invalid Reference.");
204 return CROS_GRALLOC_ERROR_BAD_HANDLE;
208 drv_bo_unmap(bo->bo, bo->map_data);
210 return CROS_GRALLOC_ERROR_NONE;
213 static int cros_gralloc_perform(struct gralloc_module_t const* module,
217 struct cros_gralloc_bo *bo;
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);
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:
232 return CROS_GRALLOC_ERROR_UNSUPPORTED;
236 handle = va_arg(args, buffer_handle_t);
237 auto hnd = (struct cros_gralloc_handle *) handle;
239 if (cros_gralloc_validate_handle(hnd)) {
240 cros_gralloc_error("Invalid handle.");
241 return CROS_GRALLOC_ERROR_BAD_HANDLE;
244 if (cros_gralloc_validate_reference(mod, hnd, &bo)) {
245 cros_gralloc_error("Invalid Reference.");
246 return CROS_GRALLOC_ERROR_BAD_HANDLE;
250 case GRALLOC_DRM_GET_STRIDE:
251 out_stride = va_arg(args, uint32_t *);
252 *out_stride = hnd->pixel_stride;
254 case GRALLOC_DRM_GET_FORMAT:
255 out_format = va_arg(args, int32_t *);
256 *out_format = hnd->droid_format;
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;
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;
269 return CROS_GRALLOC_ERROR_UNSUPPORTED;
274 return CROS_GRALLOC_ERROR_NONE;
277 static int cros_gralloc_lock_ycbcr(struct gralloc_module_t const* module,
278 buffer_handle_t handle, int usage, int l,
280 struct android_ycbcr *ycbcr)
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);
289 if (cros_gralloc_validate_handle(hnd)) {
290 cros_gralloc_error("Invalid handle.");
291 return CROS_GRALLOC_ERROR_BAD_HANDLE;
294 if (cros_gralloc_validate_reference(mod, hnd, &bo)) {
295 cros_gralloc_error("Invalid Reference.");
296 return CROS_GRALLOC_ERROR_BAD_HANDLE;
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;
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,
310 if (vaddr == MAP_FAILED) {
311 cros_gralloc_error("Mapping failed.");
312 return CROS_GRALLOC_ERROR_UNSUPPORTED;
315 addr = static_cast<uint8_t*>(vaddr);
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);
321 switch (hnd->format) {
322 case DRM_FORMAT_NV12:
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;
330 case DRM_FORMAT_YVU420:
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;
338 case DRM_FORMAT_UYVY:
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;
347 return CROS_GRALLOC_ERROR_UNSUPPORTED;
350 return CROS_GRALLOC_ERROR_NONE;
353 static struct hw_module_methods_t cros_gralloc_module_methods = {
354 .open = cros_gralloc_open
357 struct cros_gralloc_module HAL_MODULE_INFO_SYM = {
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,
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,