1 #include "gralloc4/gralloc_vendor_interface.h"
2 #include <vector>
3 #include <sys/stat.h>
4
5 #include "core/format_info.h"
6 #include "core/mali_gralloc_bufferdescriptor.h"
7 #include "core/mali_gralloc_bufferallocation.h"
8 #include "core/mali_gralloc_reference.h"
9 #include "allocator/mali_gralloc_ion.h"
10 #include "hidl_common/SharedMetadata.h"
11 #include "gralloc_priv.h"
12
13 namespace android::hardware::graphics::allocator::priv {
14
15 struct Descriptor {
16 unsigned int size = 0;
17 uint64_t producer_usage = 0;
18 uint64_t consumer_usage = 0;
19
20 struct PlaneDescriptor {
21 int fd = -1;
22 size_t size = 0;
23 off_t offset = 0;
24 int stride_byte = 0;
25 };
26 std::vector<PlaneDescriptor> planes;
27
28 int width = 0;
29 int height = 0;
30 int stride_pixel = 0;
31 int format = 0;
32 };
33
createDescriptor()34 Descriptor *createDescriptor() { return new Descriptor(); }
deleteDescriptor(Descriptor * descriptor)35 void deleteDescriptor(Descriptor *descriptor) { delete descriptor; }
36
setProducerUsage(Descriptor & descriptor,uint64_t usage)37 void setProducerUsage(Descriptor &descriptor, uint64_t usage) {
38 descriptor.producer_usage = usage;
39 }
40
setConsumerUsage(Descriptor & descriptor,uint64_t usage)41 void setConsumerUsage(Descriptor &descriptor, uint64_t usage) {
42 descriptor.consumer_usage = usage;
43 }
44
setPlaneCount(Descriptor & descriptor,int count)45 void setPlaneCount(Descriptor &descriptor, int count) {
46 descriptor.planes.resize(count);
47 }
48
setPlane(Descriptor & descriptor,int index,int fd,size_t size,off_t offset,int stride_byte)49 void setPlane(Descriptor &descriptor, int index, int fd, size_t size, off_t offset, int stride_byte) {
50 descriptor.planes[index].fd = fd;
51 descriptor.planes[index].size = size;
52 descriptor.planes[index].offset = offset;
53 descriptor.planes[index].stride_byte = stride_byte;
54 }
55
setWidth(Descriptor & descriptor,int width)56 void setWidth(Descriptor &descriptor, int width) {
57 descriptor.width = width;
58 }
59
setHeight(Descriptor & descriptor,int height)60 void setHeight(Descriptor &descriptor, int height) {
61 descriptor.height = height;
62 }
63
setStridePixel(Descriptor & descriptor,int stride_pixel)64 void setStridePixel(Descriptor &descriptor, int stride_pixel) {
65 descriptor.stride_pixel = stride_pixel;
66 }
67
setFormat(Descriptor & descriptor,int format)68 void setFormat(Descriptor &descriptor, int format) {
69 descriptor.format = format;
70 }
71
createNativeHandle(const Descriptor & descriptor)72 buffer_handle_t createNativeHandle(const Descriptor &descriptor) {
73 for (int i = 0; i < descriptor.planes.size(); ++i) {
74 struct stat st;
75 fstat(descriptor.planes[i].fd, &st);
76 off64_t fd_size = st.st_size;
77 if (fd_size < descriptor.planes[i].size) {
78 ALOGE("libGralloc4Wrapper: createNativeHandle failed: plane[%d] requested size greater than fd size.",
79 i);
80 return nullptr;
81 }
82 }
83
84 buffer_descriptor_t buffer_descriptor;
85
86 buffer_descriptor.pixel_stride = descriptor.stride_pixel;
87 buffer_descriptor.width = descriptor.width;
88 buffer_descriptor.height = descriptor.height;
89 buffer_descriptor.layer_count = 1;
90 buffer_descriptor.hal_format = buffer_descriptor.alloc_format
91 = descriptor.format;
92 buffer_descriptor.producer_usage = descriptor.producer_usage;
93 buffer_descriptor.consumer_usage = descriptor.consumer_usage;
94 buffer_descriptor.format_type = MALI_GRALLOC_FORMAT_TYPE_USAGE;
95 buffer_descriptor.signature = sizeof(buffer_descriptor_t);
96
97 buffer_descriptor.fd_count = buffer_descriptor.plane_count
98 = descriptor.planes.size();
99 for (int i = 0; i < descriptor.planes.size(); ++i) {
100 buffer_descriptor.alloc_sizes[i] = descriptor.planes[i].size;
101 }
102
103 auto format_index = get_format_index(descriptor.format);
104 if (format_index == -1) {
105 ALOGE("libGralloc4Wrapper: invalid format 0x%x",
106 descriptor.format);
107 return 0;
108 }
109 for (int i = 0; i < descriptor.planes.size(); ++i) {
110 uint8_t bpp = formats[format_index].bpp[i];
111 if (bpp == 0) {
112 ALOGE("libGralloc4Wrapper: format 0x%x has bpp[%d]=0",
113 descriptor.format, i);
114 return nullptr;
115 }
116 buffer_descriptor.plane_info[i] = {
117 .byte_stride = static_cast<uint32_t>((descriptor.planes[i].stride_byte * bpp) / 8),
118 .alloc_width = buffer_descriptor.width,
119 .alloc_height = buffer_descriptor.height,
120 };
121 }
122
123 if (mali_gralloc_derive_format_and_size(&buffer_descriptor)) {
124 ALOGE("libGralloc4Wrapper: mali_gralloc_derive_format_and_size failed");
125 return nullptr;
126 }
127
128 const gralloc_buffer_descriptor_t gralloc_buffer_descriptor =
129 reinterpret_cast<const gralloc_buffer_descriptor_t>(&buffer_descriptor);
130
131 buffer_handle_t tmp_buffer;
132 bool shared_backend;
133 // TODO(modan@, make mali_gralloc_ion_allocate accept multiple fds)
134 {
135 int result = mali_gralloc_buffer_allocate(&gralloc_buffer_descriptor, 1, &tmp_buffer,
136 &shared_backend, descriptor.planes[0].fd);
137 if (result < 0) {
138 ALOGE("mali_gralloc_buffer_allocate failed");
139 return nullptr;
140 }
141 }
142
143 private_handle_t *hnd = const_cast<private_handle_t *>(
144 static_cast<const private_handle_t *>(tmp_buffer));
145
146 hnd->imapper_version = HIDL_MAPPER_VERSION_SCALED;
147
148 hnd->reserved_region_size = buffer_descriptor.reserved_size;
149 hnd->attr_size = arm::mapper::common::shared_metadata_size() + hnd->reserved_region_size;
150
151 {
152 int result = mali_gralloc_ion_allocate_attr(hnd);
153 if (result < 0) {
154 ALOGE("mali_gralloc_ion_allocate_attr failed");
155 mali_gralloc_buffer_free(tmp_buffer);
156 return nullptr;
157 }
158 }
159
160 {
161 hnd->attr_base = mmap(nullptr, hnd->attr_size, PROT_READ | PROT_WRITE,
162 MAP_SHARED, hnd->get_share_attr_fd(), 0);
163 if (hnd->attr_base == MAP_FAILED) {
164 ALOGE("mmap hnd->get_share_attr_fd() failed");
165 mali_gralloc_buffer_free(tmp_buffer);
166 return nullptr;
167 }
168
169 memset(hnd->attr_base, 0, hnd->attr_size);
170
171 arm::mapper::common::shared_metadata_init(hnd->attr_base, buffer_descriptor.name);
172
173 const uint32_t base_format = buffer_descriptor.alloc_format & MALI_GRALLOC_INTFMT_FMT_MASK;
174 const uint64_t usage = buffer_descriptor.consumer_usage | buffer_descriptor.producer_usage;
175 android_dataspace_t dataspace;
176 get_format_dataspace(base_format, usage, hnd->width, hnd->height, &dataspace);
177
178 arm::mapper::common::set_dataspace(hnd, static_cast<arm::mapper::common::Dataspace>(dataspace));
179
180 munmap(hnd->attr_base, hnd->attr_size);
181 hnd->attr_base = 0;
182 }
183
184 // TODO(modan@, handle all plane offsets)
185 hnd->offset = hnd->plane_info[0].offset = descriptor.planes[0].offset;
186 hnd->layer_count = 1;
187
188 return tmp_buffer;
189 }
190
freeImportedHandle(void * handle)191 int freeImportedHandle(void *handle)
192 {
193 using android::hardware::graphics::mapper::V4_0::IMapper;
194 using android::hardware::graphics::mapper::V4_0::Error;
195
196 const private_handle_t *hnd = static_cast<private_handle_t *>(handle);
197
198 struct UnmapWork { void *base; size_t alloc_size; };
199 std::vector<UnmapWork> work(hnd->fd_count);
200
201 for (size_t i = 0; i < hnd->fd_count; ++i)
202 {
203 work[i].base = reinterpret_cast<void*>(hnd->bases[i]);
204 work[i].alloc_size = hnd->alloc_sizes[i];
205 }
206
207 static android::sp<IMapper> mapper = IMapper::getService();
208 if (!mapper)
209 {
210 ALOGE("libGralloc4Wrapper: %s failed to get a mapper", __func__);
211 return -1;
212 }
213
214 if (mapper->freeBuffer(handle) != Error::NONE)
215 {
216 ALOGE("libGralloc4Wrapper: %s couldn't freeBuffer(%p\n", __func__, handle);
217 return -1;
218 }
219
220 {
221 bool unmapFailed = false;
222 for (const UnmapWork &w : work)
223 {
224 if (!w.base) { continue; }
225 if (int ret = munmap(w.base, w.alloc_size); ret)
226 {
227 ALOGE("libGralloc4Wrapper: %s couldn't unmap address %p (size %zu): %s", __func__, w.base, w.alloc_size, strerror(ret));
228 unmapFailed = true;
229 }
230 }
231 if (unmapFailed) { return -1; }
232 }
233
234 return 0;
235 }
236
237 } // namespace android::hardware::graphics::allocator::priv
238