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