OSDN Git Service

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