OSDN Git Service

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