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