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, struct cros_gralloc_bo **bo)
15 if (!mod->handles.count(hnd))
16 return CROS_GRALLOC_ERROR_BAD_HANDLE;
18 *bo = mod->handles[hnd].bo;
19 return CROS_GRALLOC_ERROR_NONE;
22 int cros_gralloc_decrement_reference_count(struct cros_gralloc_module *mod,
23 struct cros_gralloc_bo *bo)
25 if (bo->refcount <= 0) {
26 cros_gralloc_error("The reference count is <= 0.");
30 if (!--bo->refcount) {
31 mod->buffers.erase(drv_bo_get_plane_handle(bo->bo, 0).u32);
32 drv_bo_destroy(bo->bo);
35 mod->handles.erase(bo->hnd);
36 native_handle_close(&bo->hnd->base);
43 return CROS_GRALLOC_ERROR_NONE;
46 static int cros_gralloc_register_buffer(struct gralloc_module_t const *module,
47 buffer_handle_t handle)
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);
55 if (cros_gralloc_validate_handle(hnd)) {
56 cros_gralloc_error("Invalid handle.");
57 return CROS_GRALLOC_ERROR_BAD_HANDLE;
61 if (cros_gralloc_rendernode_open(&mod->drv)) {
62 cros_gralloc_error("Failed to open render node.");
63 return CROS_GRALLOC_ERROR_NO_RESOURCES;
67 if (!cros_gralloc_validate_reference(mod, hnd, &bo)) {
69 mod->handles[hnd].registrations++;
70 return CROS_GRALLOC_ERROR_NONE;
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;
78 if (mod->buffers.count(id)) {
79 bo = mod->buffers[id];
82 struct drv_import_fd_data data;
83 data.format = hnd->format;
84 data.width = hnd->width;
85 data.height = hnd->height;
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];
97 bo = new cros_gralloc_bo();
98 bo->bo = drv_bo_import(mod->drv, &data);
101 return CROS_GRALLOC_ERROR_NO_RESOURCES;
104 id = drv_bo_get_plane_handle(bo->bo, 0).u32;
105 mod->buffers[id] = bo;
110 mod->handles[hnd].bo = bo;
111 mod->handles[hnd].registrations = 1;
113 return CROS_GRALLOC_ERROR_NONE;
116 static int cros_gralloc_unregister_buffer(struct gralloc_module_t const *module,
117 buffer_handle_t handle)
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);
124 if (cros_gralloc_validate_handle(hnd)) {
125 cros_gralloc_error("Invalid handle.");
126 return CROS_GRALLOC_ERROR_BAD_HANDLE;
129 if (cros_gralloc_validate_reference(mod, hnd, &bo)) {
130 cros_gralloc_error("Invalid Reference.");
131 return CROS_GRALLOC_ERROR_BAD_HANDLE;
134 if (mod->handles[hnd].registrations <= 0) {
135 cros_gralloc_error("Handle not registered.");
136 return CROS_GRALLOC_ERROR_BAD_HANDLE;
139 mod->handles[hnd].registrations--;
141 if (!mod->handles[hnd].registrations)
142 mod->handles.erase(hnd);
144 return cros_gralloc_decrement_reference_count(mod, bo);
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)
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);
155 if (cros_gralloc_validate_handle(hnd)) {
156 cros_gralloc_error("Invalid handle.");
157 return CROS_GRALLOC_ERROR_BAD_HANDLE;
160 if (cros_gralloc_validate_reference(mod, hnd, &bo)) {
161 cros_gralloc_error("Invalid Reference.");
162 return CROS_GRALLOC_ERROR_BAD_HANDLE;
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;
170 if (sw_access & usage) {
172 *vaddr = bo->map_data->addr;
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);
178 if (*vaddr == MAP_FAILED) {
179 cros_gralloc_error("Mapping failed.");
180 return CROS_GRALLOC_ERROR_UNSUPPORTED;
186 return CROS_GRALLOC_ERROR_NONE;
189 static int cros_gralloc_unlock(struct gralloc_module_t const *module, buffer_handle_t handle)
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);
196 if (cros_gralloc_validate_handle(hnd)) {
197 cros_gralloc_error("Invalid handle.");
198 return CROS_GRALLOC_ERROR_BAD_HANDLE;
201 if (cros_gralloc_validate_reference(mod, hnd, &bo)) {
202 cros_gralloc_error("Invalid Reference.");
203 return CROS_GRALLOC_ERROR_BAD_HANDLE;
206 if (!--bo->lockcount && bo->map_data) {
207 drv_bo_unmap(bo->bo, bo->map_data);
211 return CROS_GRALLOC_ERROR_NONE;
214 static int cros_gralloc_perform(struct gralloc_module_t const *module, int op, ...)
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, buffer_handle_t handle,
278 int usage, int l, int t, int w, int h,
279 struct android_ycbcr *ycbcr)
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);
288 if (cros_gralloc_validate_handle(hnd)) {
289 cros_gralloc_error("Invalid handle.");
290 return CROS_GRALLOC_ERROR_BAD_HANDLE;
293 if (cros_gralloc_validate_reference(mod, hnd, &bo)) {
294 cros_gralloc_error("Invalid Reference.");
295 return CROS_GRALLOC_ERROR_BAD_HANDLE;
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;
304 if (sw_access & usage) {
307 vaddr = bo->map_data->addr;
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);
313 if (vaddr == MAP_FAILED) {
314 cros_gralloc_error("Mapping failed.");
315 return CROS_GRALLOC_ERROR_UNSUPPORTED;
318 addr = static_cast<uint8_t *>(vaddr);
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);
324 switch (hnd->format) {
325 case DRM_FORMAT_NV12:
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;
333 case DRM_FORMAT_YVU420_ANDROID:
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;
341 case DRM_FORMAT_UYVY:
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;
350 return CROS_GRALLOC_ERROR_UNSUPPORTED;
355 return CROS_GRALLOC_ERROR_NONE;
358 static struct hw_module_methods_t cros_gralloc_module_methods = {.open = cros_gralloc_open };
360 struct cros_gralloc_module HAL_MODULE_INFO_SYM = {
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,
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,