/* * Copyright (c) Hisilicon Technologies Co., Ltd.. 2018-2019. All rights reserved. * Description: Gralloc * Author: Hisilicon * Created: 2019.11.07 */ #include "gralloc_attribute.h" #include #include #ifdef GRALLOC_NEED_SMMU_MAP #include "ion_ext.h" #endif #include "gralloc_ion.h" #include "mali_gralloc_formats.h" int gralloc_buffer_attr_allocate(const private_module_t *m, struct private_internal_handle_t *handle) { int ret; int attr_fd = -1; int attr_size = ATTR_BUFFER_SIZE; if (m == nullptr || handle == nullptr) { GRALLOC_ERROR_INFO(); return GRALLOC_FAILURE; } #ifdef GRALLOC_NEED_SMMU_MAP ion_user_handle_t attr_hnd = -1; void *attr_base = nullptr; ret = ion_alloc(m->client, attr_size, 0, ION_HEAP_SYSTEM_MASK, 0, &attr_hnd); #else ret = ion_alloc_fd(m->client, attr_size, 0, ION_HEAP_SMMU_MASK, 0, &attr_fd); #endif if (ret < 0) { GRALLOC_ERROR_INFO(); return GRALLOC_FAILURE; } #ifdef GRALLOC_NEED_SMMU_MAP ret = ion_share(m->client, attr_hnd, &attr_fd); if (ret < 0) { GRALLOC_ERROR_INFO(); ion_free(m->client, attr_hnd); close(attr_fd); handle->attr_hnd = -1; handle->attr_fd = -1; handle->attr_size = 0; return GRALLOC_FAILURE; } attr_base = mmap(nullptr, attr_size, PROT_READ | PROT_WRITE, MAP_SHARED, attr_fd, 0); if (attr_base != MAP_FAILED) { memset_s(attr_base, attr_size, 0, attr_size); munmap(attr_base, attr_size); } else { GRALLOC_ERROR_INFO(); ion_free(m->client, attr_hnd); close(attr_fd); handle->attr_hnd = -1; handle->attr_fd = -1; handle->attr_size = 0; return GRALLOC_FAILURE; } handle->attr_hnd = attr_hnd; #endif handle->attr_fd = attr_fd; handle->attr_size = attr_size; return GRALLOC_SUCCESS; } int gralloc_buffer_attr_free(const private_module_t *m, struct private_internal_handle_t *handle) { if (m == nullptr || handle == nullptr) { GRALLOC_ERROR_INFO(); return GRALLOC_FAILURE; } int attr_fd = handle->attr_fd; #ifdef GRALLOC_NEED_SMMU_MAP int ret = 0; ion_user_handle_t attr_hnd = handle->attr_hnd; if (attr_hnd != -1) { ret = ion_free(m->client, attr_hnd); if (ret < 0) { GRALLOC_ERROR_INFO(); return GRALLOC_FAILURE; } handle->attr_hnd = -1; } else { GRALLOC_ERROR_INFO(); return GRALLOC_FAILURE; } #endif GRALLOC_IGNORE(m); if (attr_fd != -1) { close(attr_fd); } handle->attr_fd = -1; handle->attr_size = 0; return GRALLOC_SUCCESS; } int gralloc_buffer_attr_map(const private_module_t *m, struct private_internal_handle_t *handle) { if (m == nullptr || handle == nullptr) { GRALLOC_ERROR_INFO(); return GRALLOC_FAILURE; } int attr_fd = handle->attr_fd; void *attr_base = nullptr; size_t attr_size = handle->attr_size; #ifdef GRALLOC_NEED_SMMU_MAP int ret; unsigned int attr_addr = (unsigned int)-1; ion_user_handle_t attr_hnd = -1; ret = ion_import(m->client, attr_fd, &attr_hnd); if (ret != 0) { GRALLOC_ERROR_INFO(); return GRALLOC_FAILURE; } ret = ion_map_iommu(m->client, attr_hnd, &attr_addr, &attr_size, 0); if (ret != 0) { GRALLOC_ERROR_INFO(); return GRALLOC_FAILURE; } if (attr_size <= 0) { GRALLOC_ERROR_INFO(); return GRALLOC_FAILURE; } handle->attr_hnd = attr_hnd; handle->attr_addr = attr_addr; handle->attr_size = attr_size; #endif attr_base = mmap(nullptr, attr_size, PROT_READ | PROT_WRITE, MAP_SHARED, attr_fd, 0); if (attr_base == MAP_FAILED) { GRALLOC_ERROR_INFO(); return GRALLOC_FAILURE; } handle->attr_base = attr_base; return GRALLOC_SUCCESS; } int gralloc_buffer_attr_unmap(const private_module_t *m, struct private_internal_handle_t *handle) { if (m == nullptr || handle == nullptr || handle->attr_base == nullptr) { GRALLOC_ERROR_INFO(); return GRALLOC_FAILURE; } munmap(handle->attr_base, handle->attr_size); handle->attr_base = MAP_FAILED; #ifdef GRALLOC_NEED_SMMU_MAP int ret; ion_user_handle_t attr_hnd = handle->attr_hnd; if (handle->attr_addr != (unsigned int)-1) { ret = ion_unmap_iommu(m->client, attr_hnd, 0); if (ret < 0) { GRALLOC_ERROR_INFO(); return GRALLOC_FAILURE; } ret = ion_free(m->client, attr_hnd); if (ret < 0) { GRALLOC_ERROR_INFO(); return GRALLOC_FAILURE; } } handle->attr_hnd = -1; handle->attr_addr = (unsigned int)-1; handle->attr_size = 0; #else GRALLOC_IGNORE(m); #endif return GRALLOC_SUCCESS; } int gralloc_init_attribute_buffer(const private_module_t *m, private_internal_handle_t *handle) { if (m == nullptr || handle == nullptr) { GRALLOC_ERROR_INFO(); return GRALLOC_FAILURE; } if (gralloc_buffer_attr_map(m, handle) != GRALLOC_SUCCESS) { return GRALLOC_FAILURE; } int val; /* init compression flag */ if ((handle->internal_format & MALI_GRALLOC_INTFMT_AFBC_BASIC) != 0) { val = COMPRESSION_FLAG_AFBC; } else if ((handle->internal_format & MALI_GRALLOC_INTFMT_HFBC_BASIC) != 0) { val = COMPRESSION_FLAG_HFBC; } else { val = COMPRESSION_FLAG_LINEAR; } if (gralloc_buffer_attr_write(reinterpret_cast(handle), GRALLOC_BUFFER_ATTR_COMPRESSION, &val) != GRALLOC_SUCCESS) { gralloc_buffer_attr_unmap(m, handle); return GRALLOC_FAILURE; } /* init attr private buffer for media */ struct attr_private_buffer buf = {-1, ATTR_REGION_SIZE, ATTR_MEDIA_PRIVATE_BUFFER_SIZE, nullptr}; if (gralloc_buffer_attr_write(reinterpret_cast(handle), GRALLOC_BUFFER_ATTR_MEDIA, &buf) != GRALLOC_SUCCESS) { gralloc_buffer_attr_unmap(m, handle); return GRALLOC_FAILURE; } gralloc_buffer_attr_unmap(m, handle); return GRALLOC_SUCCESS; }