blob: 7f0a50a62decee3e459336a4c027072b3a145233 [file] [log] [blame]
Gurchetan Singh2e786ad2016-08-24 18:31:23 -07001/*
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
9static struct cros_gralloc_bo *cros_gralloc_bo_create(struct driver *drv,
10 int width, int height,
11 int format, int usage)
12{
Gurchetan Singhf17c8132016-11-29 14:45:46 -080013 int32_t supported;
Gurchetan Singh2e786ad2016-08-24 18:31:23 -070014 uint64_t drv_usage;
Gurchetan Singhf3b22da2016-11-21 10:46:38 -080015 uint32_t drv_format;
Gurchetan Singh2e786ad2016-08-24 18:31:23 -070016 struct cros_gralloc_bo *bo;
17
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);
21
Gurchetan Singhf17c8132016-11-29 14:45:46 -080022 supported = drv_is_combination_supported(drv, drv_format, drv_usage,
23 DRM_FORMAT_MOD_NONE);
24
Gurchetan Singh4d22b4e2017-03-08 17:28:28 -080025 if (!supported && (usage & GRALLOC_USAGE_HW_COMPOSER)) {
Gurchetan Singhf17c8132016-11-29 14:45:46 -080026 drv_usage &= ~BO_USE_SCANOUT;
27 supported = drv_is_combination_supported(drv, drv_format,
28 drv_usage,
29 DRM_FORMAT_MOD_NONE);
30 }
31
Gurchetan Singh682d73b2016-12-27 10:25:18 -080032 if (!supported && (drv_usage & BO_USE_RENDERING) &&
33 (drv_usage && (BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN))) {
34 drv_usage &= ~BO_USE_RENDERING;
35 supported = drv_is_combination_supported(drv, drv_format,
36 drv_usage,
37 DRM_FORMAT_MOD_NONE);
38 }
39
Gurchetan Singhf17c8132016-11-29 14:45:46 -080040 if (!supported) {
Gurchetan Singh2e786ad2016-08-24 18:31:23 -070041 cros_gralloc_error("Unsupported combination -- HAL format: %u, "
Gurchetan Singhf17c8132016-11-29 14:45:46 -080042 "HAL flags: %u, drv_format: %u, "
43 "drv_flags: %llu", format, usage,
Gurchetan Singh2e786ad2016-08-24 18:31:23 -070044 drv_format, drv_usage);
45 return NULL;
46 }
47
48 bo = new cros_gralloc_bo();
49 memset(bo, 0, sizeof(*bo));
50
51 bo->bo = drv_bo_create(drv, width, height, drv_format, drv_usage);
52 if (!bo->bo) {
53 delete bo;
54 cros_gralloc_error("Failed to create bo.");
55 return NULL;
56 }
57
Gurchetan Singhc67f9e42016-11-28 15:25:26 -080058 /*
59 * If there is a desire for more than one kernel buffer, this can be
60 * removed once the ArcCodec and Wayland service have the ability to
61 * send more than one fd. GL/Vulkan drivers may also have to modified.
62 */
Gurchetan Singh2e786ad2016-08-24 18:31:23 -070063 if (drv_num_buffers_per_bo(bo->bo) != 1) {
64 drv_bo_destroy(bo->bo);
65 delete bo;
66 cros_gralloc_error("Can only support one buffer per bo.");
67 return NULL;
68 }
69
70 bo->refcount = 1;
71
72 return bo;
73}
74
75static struct cros_gralloc_handle *cros_gralloc_handle_from_bo(struct bo *bo)
76{
Gurchetan Singhc67f9e42016-11-28 15:25:26 -080077 uint64_t mod;
78 size_t num_planes;
Gurchetan Singh2e786ad2016-08-24 18:31:23 -070079 struct cros_gralloc_handle *hnd;
80
81 hnd = new cros_gralloc_handle();
82 memset(hnd, 0, sizeof(*hnd));
83
Gurchetan Singhc67f9e42016-11-28 15:25:26 -080084 num_planes = drv_bo_get_num_planes(bo);
Gurchetan Singh2e786ad2016-08-24 18:31:23 -070085
Gurchetan Singhc67f9e42016-11-28 15:25:26 -080086 hnd->base.version = sizeof(hnd->base);
87 hnd->base.numFds = num_planes;
88 hnd->base.numInts = num_ints_handle() - num_planes;
89
90 for (size_t p = 0; p < num_planes; p++) {
91 hnd->fds[p] = drv_bo_get_plane_fd(bo, p);
92 hnd->strides[p] = drv_bo_get_plane_stride(bo, p);
93 hnd->offsets[p] = drv_bo_get_plane_offset(bo, p);
94 hnd->sizes[p] = drv_bo_get_plane_size(bo, p);
95
96 mod = drv_bo_get_plane_format_modifier(bo, p);
97 hnd->format_modifiers[p] = static_cast<uint32_t>(mod >> 32);
98 hnd->format_modifiers[p+1] = static_cast<uint32_t>(mod);
Gurchetan Singh2e786ad2016-08-24 18:31:23 -070099 }
100
Gurchetan Singhc67f9e42016-11-28 15:25:26 -0800101 hnd->width = drv_bo_get_width(bo);
102 hnd->height = drv_bo_get_height(bo);
103 hnd->format = drv_bo_get_format(bo);
Gurchetan Singh2e786ad2016-08-24 18:31:23 -0700104
105 hnd->magic = cros_gralloc_magic();
Gurchetan Singh2e786ad2016-08-24 18:31:23 -0700106
Gurchetan Singhc67f9e42016-11-28 15:25:26 -0800107 hnd->pixel_stride = hnd->strides[0];
108 hnd->pixel_stride /= drv_stride_from_format(hnd->format, 1, 0);
Gurchetan Singh2e786ad2016-08-24 18:31:23 -0700109
110 return hnd;
111}
112
113static int cros_gralloc_alloc(alloc_device_t *dev, int w, int h, int format,
114 int usage, buffer_handle_t *handle, int *stride)
115{
116 auto mod = (struct cros_gralloc_module *) dev->common.module;
117 std::lock_guard<std::mutex> lock(mod->mutex);
118
119 auto bo = cros_gralloc_bo_create(mod->drv, w, h, format, usage);
120 if (!bo)
121 return CROS_GRALLOC_ERROR_NO_RESOURCES;
122
123 auto hnd = cros_gralloc_handle_from_bo(bo->bo);
Gurchetan Singhc67f9e42016-11-28 15:25:26 -0800124 hnd->droid_format = static_cast<int32_t>(format);
Gurchetan Singh2e786ad2016-08-24 18:31:23 -0700125 hnd->usage = static_cast<int32_t>(usage);
126
Gurchetan Singh9cbb4352016-12-05 11:02:55 -0800127 mod->handles[hnd].registrations = 0;
128 mod->handles[hnd].bo = bo;
Gurchetan Singh2e786ad2016-08-24 18:31:23 -0700129 bo->hnd = hnd;
130
Gurchetan Singh2e786ad2016-08-24 18:31:23 -0700131 mod->buffers[drv_bo_get_plane_handle(bo->bo, 0).u32] = bo;
132
133 *stride = static_cast<int>(hnd->pixel_stride);
134 *handle = &hnd->base;
135
136 return CROS_GRALLOC_ERROR_NONE;
137}
138
139static int cros_gralloc_free(alloc_device_t *dev, buffer_handle_t handle)
140{
141 struct cros_gralloc_bo *bo;
142 auto hnd = (struct cros_gralloc_handle *) handle;
143 auto mod = (struct cros_gralloc_module *) dev->common.module;
144 std::lock_guard<std::mutex> lock(mod->mutex);
145
146 if (cros_gralloc_validate_handle(hnd)) {
147 cros_gralloc_error("Invalid handle.");
148 return CROS_GRALLOC_ERROR_BAD_HANDLE;
149 }
150
151 if (cros_gralloc_validate_reference(mod, hnd, &bo)) {
152 cros_gralloc_error("Invalid Reference.");
153 return CROS_GRALLOC_ERROR_BAD_HANDLE;
154 }
155
Gurchetan Singh9cbb4352016-12-05 11:02:55 -0800156 if (mod->handles[hnd].registrations > 0) {
Gurchetan Singh2e786ad2016-08-24 18:31:23 -0700157 cros_gralloc_error("Deallocating before unregistering.");
158 return CROS_GRALLOC_ERROR_BAD_HANDLE;
159 }
160
161 return cros_gralloc_decrement_reference_count(mod, bo);
162}
163
164static int cros_gralloc_close(struct hw_device_t *dev)
165{
166 auto mod = (struct cros_gralloc_module *) dev->module;
167 auto alloc = (struct alloc_device_t *) dev;
168 std::lock_guard<std::mutex> lock(mod->mutex);
169
170 if (mod->drv) {
171 drv_destroy(mod->drv);
172 mod->drv = NULL;
173 }
174
175 mod->buffers.clear();
176 mod->handles.clear();
177
178 delete alloc;
179
180 return CROS_GRALLOC_ERROR_NONE;
181}
182
183int cros_gralloc_open(const struct hw_module_t *mod, const char *name,
184 struct hw_device_t **dev)
185{
186 auto module = (struct cros_gralloc_module *) mod;
187 std::lock_guard<std::mutex> lock(module->mutex);
188
189 if (module->drv)
190 return CROS_GRALLOC_ERROR_NONE;
191
192 if (strcmp(name, GRALLOC_HARDWARE_GPU0)) {
193 cros_gralloc_error("Incorrect device name - %s.", name);
194 return CROS_GRALLOC_ERROR_UNSUPPORTED;
195 }
196
197 if (cros_gralloc_rendernode_open(&module->drv)) {
198 cros_gralloc_error("Failed to open render node.");
199 return CROS_GRALLOC_ERROR_NO_RESOURCES;
200 }
201
202 auto alloc = new alloc_device_t();
203 memset(alloc, 0, sizeof(*alloc));
204
205 alloc->alloc = cros_gralloc_alloc;
206 alloc->free = cros_gralloc_free;
207 alloc->common.tag = HARDWARE_DEVICE_TAG;
208 alloc->common.version = 0;
209 alloc->common.module = (hw_module_t*) mod;
210 alloc->common.close = cros_gralloc_close;
211
212 *dev = &alloc->common;
213
214 return CROS_GRALLOC_ERROR_NONE;
215}