blob: f9b1b9ccb49e40a533dd34829ae0fc8eff03e02a [file] [log] [blame]
#include "gralloc4/gralloc_vendor_interface.h"
#include <vector>
#include <sys/stat.h>
#include "core/format_info.h"
#include "core/mali_gralloc_bufferdescriptor.h"
#include "core/mali_gralloc_bufferallocation.h"
#include "allocator/mali_gralloc_ion.h"
#include "hidl_common/SharedMetadata.h"
#include "gralloc_priv.h"
namespace android::hardware::graphics::allocator::priv {
struct Descriptor {
unsigned int size = 0;
uint64_t producer_usage = 0;
uint64_t consumer_usage = 0;
struct PlaneDescriptor {
int fd = -1;
size_t size = 0;
off_t offset = 0;
int stride_byte = 0;
};
std::vector<PlaneDescriptor> planes;
int width = 0;
int height = 0;
int stride_pixel = 0;
int format = 0;
};
Descriptor *createDescriptor() { return new Descriptor(); }
void deleteDescriptor(Descriptor *descriptor) { delete descriptor; }
void setProducerUsage(Descriptor &descriptor, uint64_t usage) {
descriptor.producer_usage = usage;
}
void setConsumerUsage(Descriptor &descriptor, uint64_t usage) {
descriptor.consumer_usage = usage;
}
void setPlaneCount(Descriptor &descriptor, int count) {
descriptor.planes.resize(count);
}
void setPlane(Descriptor &descriptor, int index, int fd, size_t size, off_t offset, int stride_byte) {
descriptor.planes[index].fd = fd;
descriptor.planes[index].size = size;
descriptor.planes[index].offset = offset;
descriptor.planes[index].stride_byte = stride_byte;
}
void setWidth(Descriptor &descriptor, int width) {
descriptor.width = width;
}
void setHeight(Descriptor &descriptor, int height) {
descriptor.height = height;
}
void setStridePixel(Descriptor &descriptor, int stride_pixel) {
descriptor.stride_pixel = stride_pixel;
}
void setFormat(Descriptor &descriptor, int format) {
descriptor.format = format;
}
buffer_handle_t createNativeHandle(const Descriptor &descriptor) {
for (int i = 0; i < descriptor.planes.size(); ++i) {
struct stat st;
fstat(descriptor.planes[i].fd, &st);
off64_t fd_size = st.st_size;
if (fd_size < descriptor.planes[i].size) {
ALOGE("libGralloc4Wrapper: createNativeHandle failed: plane[%d] requested size greater than fd size.",
i);
return nullptr;
}
}
buffer_descriptor_t buffer_descriptor;
buffer_descriptor.pixel_stride = descriptor.stride_pixel;
buffer_descriptor.width = descriptor.width;
buffer_descriptor.height = descriptor.height;
buffer_descriptor.layer_count = 1;
buffer_descriptor.hal_format = buffer_descriptor.alloc_format
= descriptor.format;
buffer_descriptor.producer_usage = descriptor.producer_usage;
buffer_descriptor.consumer_usage = descriptor.consumer_usage;
buffer_descriptor.format_type = MALI_GRALLOC_FORMAT_TYPE_USAGE;
buffer_descriptor.signature = sizeof(buffer_descriptor_t);
buffer_descriptor.fd_count = buffer_descriptor.plane_count
= descriptor.planes.size();
for (int i = 0; i < descriptor.planes.size(); ++i) {
buffer_descriptor.alloc_sizes[i] = descriptor.planes[i].size;
}
auto format_index = get_format_index(descriptor.format);
if (format_index == -1) {
ALOGE("libGralloc4Wrapper: invalid format 0x%x",
descriptor.format);
return 0;
}
for (int i = 0; i < descriptor.planes.size(); ++i) {
uint8_t bpp = formats[format_index].bpp[i];
if (bpp == 0) {
ALOGE("libGralloc4Wrapper: format 0x%x has bpp[%d]=0",
descriptor.format, i);
return nullptr;
}
buffer_descriptor.plane_info[i] = {
.byte_stride = static_cast<uint32_t>((descriptor.planes[i].stride_byte * bpp) / 8),
.alloc_width = buffer_descriptor.width,
.alloc_height = buffer_descriptor.height,
};
}
if (mali_gralloc_derive_format_and_size(&buffer_descriptor)) {
ALOGE("libGralloc4Wrapper: mali_gralloc_derive_format_and_size failed");
return nullptr;
}
const gralloc_buffer_descriptor_t gralloc_buffer_descriptor =
reinterpret_cast<const gralloc_buffer_descriptor_t>(&buffer_descriptor);
buffer_handle_t tmp_buffer;
bool shared_backend;
// TODO(modan@, make mali_gralloc_ion_allocate accept multiple fds)
{
int result = mali_gralloc_buffer_allocate(&gralloc_buffer_descriptor, 1, &tmp_buffer,
&shared_backend, descriptor.planes[0].fd);
if (result < 0) {
ALOGE("mali_gralloc_buffer_allocate failed");
return nullptr;
}
}
private_handle_t *hnd = const_cast<private_handle_t *>(
static_cast<const private_handle_t *>(tmp_buffer));
hnd->imapper_version = HIDL_MAPPER_VERSION_SCALED;
hnd->reserved_region_size = buffer_descriptor.reserved_size;
hnd->attr_size = arm::mapper::common::shared_metadata_size() + hnd->reserved_region_size;
{
int result = mali_gralloc_ion_allocate_attr(hnd);
if (result < 0) {
ALOGE("mali_gralloc_ion_allocate_attr failed");
mali_gralloc_buffer_free(tmp_buffer);
return nullptr;
}
}
{
auto metadata_vaddr = mmap(nullptr, hnd->attr_size, PROT_READ | PROT_WRITE,
MAP_SHARED, hnd->get_share_attr_fd(), 0);
if (metadata_vaddr == MAP_FAILED) {
ALOGE("mmap hnd->get_share_attr_fd() failed");
mali_gralloc_buffer_free(tmp_buffer);
return nullptr;
}
memset(metadata_vaddr, 0, hnd->attr_size);
arm::mapper::common::shared_metadata_init(metadata_vaddr, buffer_descriptor.name);
const uint32_t base_format = buffer_descriptor.alloc_format & MALI_GRALLOC_INTFMT_FMT_MASK;
const uint64_t usage = buffer_descriptor.consumer_usage | buffer_descriptor.producer_usage;
android_dataspace_t dataspace;
get_format_dataspace(base_format, usage, hnd->width, hnd->height, &dataspace);
{
using arm::mapper::common::aligned_optional;
using arm::mapper::common::Dataspace;
using arm::mapper::common::shared_metadata;
(static_cast<shared_metadata *>(metadata_vaddr))->dataspace =
aligned_optional(static_cast<Dataspace>(dataspace));
}
munmap(metadata_vaddr, hnd->attr_size);
}
// TODO(modan@, handle all plane offsets)
hnd->offset = hnd->plane_info[0].offset = descriptor.planes[0].offset;
hnd->layer_count = 1;
return tmp_buffer;
}
int freeImportedHandle(void *handle)
{
using android::hardware::graphics::mapper::V4_0::IMapper;
using android::hardware::graphics::mapper::V4_0::Error;
const private_handle_t *hnd = static_cast<private_handle_t *>(handle);
static android::sp<IMapper> mapper = IMapper::getService();
if (!mapper)
{
ALOGE("libGralloc4Wrapper: %s failed to get a mapper", __func__);
return -1;
}
if (mapper->freeBuffer(handle) != Error::NONE)
{
ALOGE("libGralloc4Wrapper: %s couldn't freeBuffer(%p\n", __func__, handle);
return -1;
}
return 0;
}
} // namespace android::hardware::graphics::allocator::priv