/* * Copyright 2022 The Chromium OS Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "Allocator.h" #include #include #include #include #include #include #include "cros_gralloc/gralloc4/CrosGralloc4Utils.h" using aidl::android::hardware::common::NativeHandle; using BufferDescriptorInfo = android::hardware::graphics::mapper::V4_0::IMapper::BufferDescriptorInfo; namespace aidl::android::hardware::graphics::allocator::impl { namespace { inline ndk::ScopedAStatus ToBinderStatus(AllocationError error) { return ndk::ScopedAStatus::fromServiceSpecificError(static_cast(error)); } } // namespace bool Allocator::init() { mDriver = cros_gralloc_driver::get_instance(); return mDriver != nullptr; } // TODO(natsu): deduplicate with CrosGralloc4Allocator after the T release. ndk::ScopedAStatus Allocator::initializeMetadata( cros_gralloc_handle_t crosHandle, const struct cros_gralloc_buffer_descriptor& crosDescriptor) { if (!mDriver) { ALOGE("Failed to initializeMetadata. Driver is uninitialized.\n"); return ToBinderStatus(AllocationError::NO_RESOURCES); } if (!crosHandle) { ALOGE("Failed to initializeMetadata. Invalid handle.\n"); return ToBinderStatus(AllocationError::NO_RESOURCES); } void* addr; uint64_t size; int ret = mDriver->get_reserved_region(crosHandle, &addr, &size); if (ret) { ALOGE("Failed to getReservedRegion.\n"); return ToBinderStatus(AllocationError::NO_RESOURCES); } CrosGralloc4Metadata* crosMetadata = reinterpret_cast(addr); snprintf(crosMetadata->name, CROS_GRALLOC4_METADATA_MAX_NAME_SIZE, "%s", crosDescriptor.name.c_str()); crosMetadata->dataspace = common::Dataspace::UNKNOWN; crosMetadata->blendMode = common::BlendMode::INVALID; return ndk::ScopedAStatus::ok(); } void Allocator::releaseBufferAndHandle(native_handle_t* handle) { mDriver->release(handle); native_handle_close(handle); native_handle_delete(handle); } ndk::ScopedAStatus Allocator::allocate(const std::vector& descriptor, int32_t count, allocator::AllocationResult* outResult) { if (!mDriver) { ALOGE("Failed to allocate. Driver is uninitialized.\n"); return ToBinderStatus(AllocationError::NO_RESOURCES); } BufferDescriptorInfo description; int ret = ::android::gralloc4::decodeBufferDescriptorInfo(descriptor, &description); if (ret) { ALOGE("Failed to allocate. Failed to decode buffer descriptor: %d.\n", ret); return ToBinderStatus(AllocationError::BAD_DESCRIPTOR); } std::vector handles; handles.resize(count, nullptr); for (int32_t i = 0; i < count; i++) { ndk::ScopedAStatus status = allocate(description, &outResult->stride, &handles[i]); if (!status.isOk()) { for (int32_t j = 0; j < i; j++) { releaseBufferAndHandle(handles[j]); } return status; } } outResult->buffers.resize(count); for (int32_t i = 0; i < count; i++) { auto handle = handles[i]; outResult->buffers[i] = ::android::dupToAidl(handle); releaseBufferAndHandle(handle); } return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus Allocator::allocate(const BufferDescriptorInfo& descriptor, int32_t* outStride, native_handle_t** outHandle) { if (!mDriver) { ALOGE("Failed to allocate. Driver is uninitialized.\n"); return ToBinderStatus(AllocationError::NO_RESOURCES); } struct cros_gralloc_buffer_descriptor crosDescriptor; if (convertToCrosDescriptor(descriptor, &crosDescriptor)) { return ToBinderStatus(AllocationError::UNSUPPORTED); } crosDescriptor.reserved_region_size += sizeof(CrosGralloc4Metadata); if (!mDriver->is_supported(&crosDescriptor)) { const std::string drmFormatString = get_drm_format_string(crosDescriptor.drm_format); const std::string pixelFormatString = getPixelFormatString(descriptor.format); const std::string usageString = getUsageString(descriptor.usage); ALOGE("Failed to allocate. Unsupported combination: pixel format:%s, drm format:%s, " "usage:%s\n", pixelFormatString.c_str(), drmFormatString.c_str(), usageString.c_str()); return ToBinderStatus(AllocationError::UNSUPPORTED); } native_handle_t* handle; int ret = mDriver->allocate(&crosDescriptor, &handle); if (ret) { return ToBinderStatus(AllocationError::NO_RESOURCES); } cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(handle); auto status = initializeMetadata(crosHandle, crosDescriptor); if (!status.isOk()) { ALOGE("Failed to allocate. Failed to initialize gralloc buffer metadata."); releaseBufferAndHandle(handle); return status; } *outStride = static_cast(crosHandle->pixel_stride); *outHandle = handle; return ndk::ScopedAStatus::ok(); } ::ndk::SpAIBinder Allocator::createBinder() { auto binder = BnAllocator::createBinder(); AIBinder_setInheritRt(binder.get(), true); return binder; } } // namespace aidl::android::hardware::graphics::allocator::impl