/* * Copyright (C) 2020 ARM Limited. All rights reserved. * * Copyright 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include #include "Allocator.h" #include "core/mali_gralloc_bufferallocation.h" #include "core/mali_gralloc_bufferdescriptor.h" #include "core/format_info.h" #include "allocator/mali_gralloc_ion.h" #include "gralloc_priv.h" #include "SharedMetadata.h" namespace arm { namespace allocator { namespace common { void allocate(const buffer_descriptor_t &bufferDescriptor, uint32_t count, IAllocator::allocate_cb hidl_cb, std::function fb_allocator) { #if DISABLE_FRAMEBUFFER_HAL GRALLOC_UNUSED(fb_allocator); #endif ATRACE_CALL(); Error error = Error::NONE; int stride = 0; std::vector grallocBuffers; gralloc_buffer_descriptor_t grallocBufferDescriptor[1]; grallocBufferDescriptor[0] = (gralloc_buffer_descriptor_t)(&bufferDescriptor); grallocBuffers.reserve(count); for (uint32_t i = 0; i < count; i++) { buffer_handle_t tmpBuffer = nullptr; int allocResult; #if (DISABLE_FRAMEBUFFER_HAL != 1) if (((bufferDescriptor.producer_usage & GRALLOC_USAGE_HW_FB) || (bufferDescriptor.consumer_usage & GRALLOC_USAGE_HW_FB)) && fb_allocator) { allocResult = fb_allocator(&bufferDescriptor, &tmpBuffer); } else #endif { allocResult = mali_gralloc_buffer_allocate(grallocBufferDescriptor, 1, &tmpBuffer, nullptr); if (allocResult != 0) { MALI_GRALLOC_LOGE("%s, buffer allocation failed with %d", __func__, allocResult); error = Error::NO_RESOURCES; break; } auto hnd = const_cast(reinterpret_cast(tmpBuffer)); hnd->imapper_version = HIDL_MAPPER_VERSION_SCALED; // 4k is rougly 7.9 MB with one byte per pixel. We are // assuming that the reserved region might be needed for // dynamic HDR and that represents the largest size. uint64_t max_reserved_region_size = 8ull * 1024 * 1024; hnd->reserved_region_size = bufferDescriptor.reserved_size; if (hnd->reserved_region_size > max_reserved_region_size) { MALI_GRALLOC_LOGE("%s, Requested reserved region size (%" PRIu64 ") is larger than allowed (%" PRIu64 ")", __func__, hnd->reserved_region_size, max_reserved_region_size); error = Error::BAD_VALUE; break; } hnd->attr_size = mapper::common::shared_metadata_size() + hnd->reserved_region_size; if (hnd->get_usage() & GRALLOC_USAGE_ROIINFO) { hnd->attr_size += 32768; } /* TODO: must do error checking */ mali_gralloc_ion_allocate_attr(hnd); /* TODO: error check for failure */ void* metadata_vaddr = mmap(nullptr, hnd->attr_size, PROT_READ | PROT_WRITE, MAP_SHARED, hnd->get_share_attr_fd(), 0); memset(metadata_vaddr, 0, hnd->attr_size); mapper::common::shared_metadata_init(metadata_vaddr, bufferDescriptor.name); const uint32_t base_format = bufferDescriptor.alloc_format & MALI_GRALLOC_INTFMT_FMT_MASK; const uint64_t usage = bufferDescriptor.consumer_usage | bufferDescriptor.producer_usage; android_dataspace_t dataspace; get_format_dataspace(base_format, usage, hnd->width, hnd->height, &dataspace); // TODO: set_dataspace API in mapper expects a buffer to be first imported before it can set the dataspace { using mapper::common::shared_metadata; using mapper::common::aligned_optional; using mapper::common::Dataspace; (static_cast(metadata_vaddr))->dataspace = aligned_optional(static_cast(dataspace)); } munmap(metadata_vaddr, hnd->attr_size); } int tmpStride = 0; tmpStride = bufferDescriptor.pixel_stride; if (stride == 0) { stride = tmpStride; } else if (stride != tmpStride) { /* Stride must be the same for all allocations */ mali_gralloc_buffer_free(tmpBuffer); stride = 0; error = Error::UNSUPPORTED; break; } grallocBuffers.emplace_back(hidl_handle(tmpBuffer)); } /* Populate the array of buffers for application consumption */ hidl_vec hidlBuffers; if (error == Error::NONE) { hidlBuffers.setToExternal(grallocBuffers.data(), grallocBuffers.size()); } hidl_cb(error, stride, hidlBuffers); /* The application should import the Gralloc buffers using IMapper for * further usage. Free the allocated buffers in IAllocator context */ for (const auto &buffer : grallocBuffers) { mali_gralloc_buffer_free(buffer.getNativeHandle()); } } } // namespace common } // namespace allocator } // namespace arm