OSDN Git Service

540574418a0496f853880305b83cd2d32b294b28
[android-x86/external-minigbm.git] / cros_gralloc / cros_alloc_device.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 static struct cros_gralloc_bo *cros_gralloc_bo_create(struct driver *drv,
10                                                       int width, int height,
11                                                       int format, int usage)
12 {
13         int32_t supported;
14         uint64_t drv_usage;
15         uint32_t drv_format;
16         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
22         supported = drv_is_combination_supported(drv, drv_format, drv_usage,
23                                                  DRM_FORMAT_MOD_NONE);
24
25         if (!supported && (drv_usage & BO_USE_SCANOUT)) {
26                 drv_usage &= ~BO_USE_SCANOUT;
27                 supported = drv_is_combination_supported(drv, drv_format,
28                                                          drv_usage,
29                                                          DRM_FORMAT_MOD_NONE);
30         }
31
32         if (!supported) {
33                 cros_gralloc_error("Unsupported combination -- HAL format: %u, "
34                                    "HAL flags: %u, drv_format: %u, "
35                                    "drv_flags: %llu", format, usage,
36                                     drv_format, drv_usage);
37                 return NULL;
38         }
39
40         bo = new cros_gralloc_bo();
41         memset(bo, 0, sizeof(*bo));
42
43         bo->bo = drv_bo_create(drv, width, height, drv_format, drv_usage);
44         if (!bo->bo) {
45                 delete bo;
46                 cros_gralloc_error("Failed to create bo.");
47                 return NULL;
48         }
49
50         /*
51          * If there is a desire for more than one kernel buffer, this can be
52          * removed once the ArcCodec and Wayland service have the ability to
53          * send more than one fd. GL/Vulkan drivers may also have to modified.
54          */
55         if (drv_num_buffers_per_bo(bo->bo) != 1) {
56                 drv_bo_destroy(bo->bo);
57                 delete bo;
58                 cros_gralloc_error("Can only support one buffer per bo.");
59                 return NULL;
60         }
61
62         bo->refcount = 1;
63
64         return bo;
65 }
66
67 static struct cros_gralloc_handle *cros_gralloc_handle_from_bo(struct bo *bo)
68 {
69         uint64_t mod;
70         size_t num_planes;
71         struct cros_gralloc_handle *hnd;
72
73         hnd = new cros_gralloc_handle();
74         memset(hnd, 0, sizeof(*hnd));
75
76         num_planes = drv_bo_get_num_planes(bo);
77
78         hnd->base.version = sizeof(hnd->base);
79         hnd->base.numFds = num_planes;
80         hnd->base.numInts = num_ints_handle() - num_planes;
81
82         for (size_t p = 0; p < num_planes; p++) {
83                 hnd->fds[p] = drv_bo_get_plane_fd(bo, p);
84                 hnd->strides[p] = drv_bo_get_plane_stride(bo, p);
85                 hnd->offsets[p] = drv_bo_get_plane_offset(bo, p);
86                 hnd->sizes[p] = drv_bo_get_plane_size(bo, p);
87
88                 mod = drv_bo_get_plane_format_modifier(bo, p);
89                 hnd->format_modifiers[p] = static_cast<uint32_t>(mod >> 32);
90                 hnd->format_modifiers[p+1] = static_cast<uint32_t>(mod);
91         }
92
93         hnd->width = drv_bo_get_width(bo);
94         hnd->height = drv_bo_get_height(bo);
95         hnd->format = drv_bo_get_format(bo);
96
97         hnd->magic = cros_gralloc_magic();
98
99         hnd->pixel_stride = hnd->strides[0];
100         hnd->pixel_stride /= drv_stride_from_format(hnd->format, 1, 0);
101
102         return hnd;
103 }
104
105 static int cros_gralloc_alloc(alloc_device_t *dev, int w, int h, int format,
106                               int usage, buffer_handle_t *handle, int *stride)
107 {
108         auto mod = (struct cros_gralloc_module *) dev->common.module;
109         std::lock_guard<std::mutex> lock(mod->mutex);
110
111         auto bo = cros_gralloc_bo_create(mod->drv, w, h, format, usage);
112         if (!bo)
113                 return CROS_GRALLOC_ERROR_NO_RESOURCES;
114
115         auto hnd = cros_gralloc_handle_from_bo(bo->bo);
116         hnd->droid_format = static_cast<int32_t>(format);
117         hnd->usage = static_cast<int32_t>(usage);
118
119         mod->handles[hnd].registrations = 0;
120         mod->handles[hnd].bo = bo;
121         bo->hnd = hnd;
122
123         mod->buffers[drv_bo_get_plane_handle(bo->bo, 0).u32] = bo;
124
125         *stride = static_cast<int>(hnd->pixel_stride);
126         *handle = &hnd->base;
127
128         return CROS_GRALLOC_ERROR_NONE;
129 }
130
131 static int cros_gralloc_free(alloc_device_t *dev, buffer_handle_t handle)
132 {
133         struct cros_gralloc_bo *bo;
134         auto hnd = (struct cros_gralloc_handle *) handle;
135         auto mod = (struct cros_gralloc_module *) dev->common.module;
136         std::lock_guard<std::mutex> lock(mod->mutex);
137
138         if (cros_gralloc_validate_handle(hnd)) {
139                 cros_gralloc_error("Invalid handle.");
140                 return CROS_GRALLOC_ERROR_BAD_HANDLE;
141         }
142
143         if (cros_gralloc_validate_reference(mod, hnd, &bo)) {
144                 cros_gralloc_error("Invalid Reference.");
145                 return CROS_GRALLOC_ERROR_BAD_HANDLE;
146         }
147
148         if (mod->handles[hnd].registrations > 0) {
149                 cros_gralloc_error("Deallocating before unregistering.");
150                 return CROS_GRALLOC_ERROR_BAD_HANDLE;
151         }
152
153         return cros_gralloc_decrement_reference_count(mod, bo);
154 }
155
156 static int cros_gralloc_close(struct hw_device_t *dev)
157 {
158         auto mod = (struct cros_gralloc_module *) dev->module;
159         auto alloc = (struct alloc_device_t *) dev;
160         std::lock_guard<std::mutex> lock(mod->mutex);
161
162         if (mod->drv) {
163                 drv_destroy(mod->drv);
164                 mod->drv = NULL;
165         }
166
167         mod->buffers.clear();
168         mod->handles.clear();
169
170         delete alloc;
171
172         return CROS_GRALLOC_ERROR_NONE;
173 }
174
175 int cros_gralloc_open(const struct hw_module_t *mod, const char *name,
176                       struct hw_device_t **dev)
177 {
178         auto module = (struct cros_gralloc_module *) mod;
179         std::lock_guard<std::mutex> lock(module->mutex);
180
181         if (module->drv)
182                 return CROS_GRALLOC_ERROR_NONE;
183
184         if (strcmp(name, GRALLOC_HARDWARE_GPU0)) {
185                 cros_gralloc_error("Incorrect device name - %s.", name);
186                 return CROS_GRALLOC_ERROR_UNSUPPORTED;
187         }
188
189         if (cros_gralloc_rendernode_open(&module->drv)) {
190                 cros_gralloc_error("Failed to open render node.");
191                 return CROS_GRALLOC_ERROR_NO_RESOURCES;
192         }
193
194         auto alloc = new alloc_device_t();
195         memset(alloc, 0, sizeof(*alloc));
196
197         alloc->alloc = cros_gralloc_alloc;
198         alloc->free = cros_gralloc_free;
199         alloc->common.tag = HARDWARE_DEVICE_TAG;
200         alloc->common.version = 0;
201         alloc->common.module = (hw_module_t*) mod;
202         alloc->common.close = cros_gralloc_close;
203
204         *dev = &alloc->common;
205
206         return CROS_GRALLOC_ERROR_NONE;
207 }