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"
9 static struct cros_gralloc_bo *cros_gralloc_bo_create(struct driver *drv,
10 int width, int height,
11 int format, int usage)
15 struct combination *combo;
16 struct cros_gralloc_bo *bo;
18 drv_format = cros_gralloc_convert_format(format);
19 drv_format = drv_resolve_format(drv, drv_format);
20 drv_usage = cros_gralloc_convert_flags(usage);
22 combo = drv_get_combination(drv, drv_format, drv_usage);
24 if (!combo && (usage & GRALLOC_USAGE_HW_COMPOSER)) {
25 drv_usage &= ~BO_USE_SCANOUT;
26 combo = drv_get_combination(drv, drv_format, drv_usage);
30 cros_gralloc_error("Unsupported combination -- HAL format: %u, "
31 "HAL flags: %u, drv_format: %4.4s, "
32 "drv_flags: %llu", format, usage,
33 reinterpret_cast<char*>(&drv_format),
38 bo = new cros_gralloc_bo();
39 memset(bo, 0, sizeof(*bo));
41 bo->bo = drv_bo_create(drv, width, height, drv_format, drv_usage);
44 cros_gralloc_error("Failed to create bo.");
49 * If there is a desire for more than one kernel buffer, this can be
50 * removed once the ArcCodec and Wayland service have the ability to
51 * send more than one fd. GL/Vulkan drivers may also have to modified.
53 if (drv_num_buffers_per_bo(bo->bo) != 1) {
54 drv_bo_destroy(bo->bo);
56 cros_gralloc_error("Can only support one buffer per bo.");
65 static struct cros_gralloc_handle *cros_gralloc_handle_from_bo(struct bo *bo)
69 struct cros_gralloc_handle *hnd;
71 hnd = new cros_gralloc_handle();
72 memset(hnd, 0, sizeof(*hnd));
74 num_planes = drv_bo_get_num_planes(bo);
76 hnd->base.version = sizeof(hnd->base);
77 hnd->base.numFds = num_planes;
78 hnd->base.numInts = num_ints_handle() - num_planes;
80 for (size_t p = 0; p < num_planes; p++) {
81 hnd->fds[p] = drv_bo_get_plane_fd(bo, p);
82 hnd->strides[p] = drv_bo_get_plane_stride(bo, p);
83 hnd->offsets[p] = drv_bo_get_plane_offset(bo, p);
84 hnd->sizes[p] = drv_bo_get_plane_size(bo, p);
86 mod = drv_bo_get_plane_format_modifier(bo, p);
87 hnd->format_modifiers[p] = static_cast<uint32_t>(mod >> 32);
88 hnd->format_modifiers[p+1] = static_cast<uint32_t>(mod);
91 hnd->width = drv_bo_get_width(bo);
92 hnd->height = drv_bo_get_height(bo);
93 hnd->format = drv_bo_get_format(bo);
95 hnd->magic = cros_gralloc_magic();
97 hnd->pixel_stride = hnd->strides[0];
98 hnd->pixel_stride /= drv_stride_from_format(hnd->format, 1, 0);
103 static int cros_gralloc_alloc(alloc_device_t *dev, int w, int h, int format,
104 int usage, buffer_handle_t *handle, int *stride)
106 auto mod = (struct cros_gralloc_module *) dev->common.module;
107 std::lock_guard<std::mutex> lock(mod->mutex);
109 auto bo = cros_gralloc_bo_create(mod->drv, w, h, format, usage);
111 return CROS_GRALLOC_ERROR_NO_RESOURCES;
113 auto hnd = cros_gralloc_handle_from_bo(bo->bo);
114 hnd->droid_format = static_cast<int32_t>(format);
115 hnd->usage = static_cast<int32_t>(usage);
117 mod->handles[hnd].registrations = 0;
118 mod->handles[hnd].bo = bo;
121 mod->buffers[drv_bo_get_plane_handle(bo->bo, 0).u32] = bo;
123 *stride = static_cast<int>(hnd->pixel_stride);
124 *handle = &hnd->base;
126 return CROS_GRALLOC_ERROR_NONE;
129 static int cros_gralloc_free(alloc_device_t *dev, buffer_handle_t handle)
131 struct cros_gralloc_bo *bo;
132 auto hnd = (struct cros_gralloc_handle *) handle;
133 auto mod = (struct cros_gralloc_module *) dev->common.module;
134 std::lock_guard<std::mutex> lock(mod->mutex);
136 if (cros_gralloc_validate_handle(hnd)) {
137 cros_gralloc_error("Invalid handle.");
138 return CROS_GRALLOC_ERROR_BAD_HANDLE;
141 if (cros_gralloc_validate_reference(mod, hnd, &bo)) {
142 cros_gralloc_error("Invalid Reference.");
143 return CROS_GRALLOC_ERROR_BAD_HANDLE;
146 if (mod->handles[hnd].registrations > 0) {
147 cros_gralloc_error("Deallocating before unregistering.");
148 return CROS_GRALLOC_ERROR_BAD_HANDLE;
151 return cros_gralloc_decrement_reference_count(mod, bo);
154 static int cros_gralloc_close(struct hw_device_t *dev)
156 auto mod = (struct cros_gralloc_module *) dev->module;
157 auto alloc = (struct alloc_device_t *) dev;
158 std::lock_guard<std::mutex> lock(mod->mutex);
161 drv_destroy(mod->drv);
165 mod->buffers.clear();
166 mod->handles.clear();
170 return CROS_GRALLOC_ERROR_NONE;
173 int cros_gralloc_open(const struct hw_module_t *mod, const char *name,
174 struct hw_device_t **dev)
176 auto module = (struct cros_gralloc_module *) mod;
177 std::lock_guard<std::mutex> lock(module->mutex);
180 return CROS_GRALLOC_ERROR_NONE;
182 if (strcmp(name, GRALLOC_HARDWARE_GPU0)) {
183 cros_gralloc_error("Incorrect device name - %s.", name);
184 return CROS_GRALLOC_ERROR_UNSUPPORTED;
187 if (cros_gralloc_rendernode_open(&module->drv)) {
188 cros_gralloc_error("Failed to open render node.");
189 return CROS_GRALLOC_ERROR_NO_RESOURCES;
192 auto alloc = new alloc_device_t();
193 memset(alloc, 0, sizeof(*alloc));
195 alloc->alloc = cros_gralloc_alloc;
196 alloc->free = cros_gralloc_free;
197 alloc->common.tag = HARDWARE_DEVICE_TAG;
198 alloc->common.version = 0;
199 alloc->common.module = (hw_module_t*) mod;
200 alloc->common.close = cros_gralloc_close;
202 *dev = &alloc->common;
204 return CROS_GRALLOC_ERROR_NONE;