/* * Copyright (c) 2011-2018, 2020 The Linux Foundation. All rights reserved. * Not a Contribution * * Copyright (C) 2010 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 DEBUG 0 #include "gr_buf_mgr.h" #include #include #include #include #include #include #include #include #include #include #include #include "gr_adreno_info.h" #include "gr_buf_descriptor.h" #include "gr_priv_handle.h" #include "gr_utils.h" #include "qdMetaData.h" #include "qd_utils.h" namespace gralloc { using aidl::android::hardware::graphics::common::BlendMode; using aidl::android::hardware::graphics::common::Cta861_3; using aidl::android::hardware::graphics::common::Dataspace; using aidl::android::hardware::graphics::common::PlaneLayout; using aidl::android::hardware::graphics::common::PlaneLayoutComponent; using aidl::android::hardware::graphics::common::Rect; using aidl::android::hardware::graphics::common::Smpte2086; using aidl::android::hardware::graphics::common::StandardMetadataType; using aidl::android::hardware::graphics::common::XyColor; using ::android::hardware::graphics::common::V1_2::PixelFormat; static BufferInfo GetBufferInfo(const BufferDescriptor &descriptor) { return BufferInfo(descriptor.GetWidth(), descriptor.GetHeight(), descriptor.GetFormat(), descriptor.GetUsage()); } static uint64_t getMetaDataSize(uint64_t reserved_region_size) { // Only include the reserved region size when using Metadata_t V2 #ifndef METADATA_V2 reserved_region_size = 0; #endif return static_cast(ROUND_UP_PAGESIZE(sizeof(MetaData_t) + reserved_region_size)); } static void unmapAndReset(private_handle_t *handle, uint64_t reserved_region_size = 0) { if (private_handle_t::validate(handle) == 0 && handle->base_metadata) { munmap(reinterpret_cast(handle->base_metadata), getMetaDataSize(reserved_region_size)); handle->base_metadata = 0; } } static int validateAndMap(private_handle_t *handle, uint64_t reserved_region_size = 0) { if (private_handle_t::validate(handle)) { ALOGE("%s: Private handle is invalid - handle:%p", __func__, handle); return -1; } if (handle->fd_metadata < 0) { // Silently return, metadata cannot be used return -1; } if (!handle->base_metadata) { uint64_t size = getMetaDataSize(reserved_region_size); void *base = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, handle->fd_metadata, 0); if (base == reinterpret_cast(MAP_FAILED)) { ALOGE("%s: metadata mmap failed - handle:%p fd: %d err: %s", __func__, handle, handle->fd_metadata, strerror(errno)); return -1; } handle->base_metadata = (uintptr_t)base; #ifdef METADATA_V2 // The allocator process gets the reserved region size from the BufferDescriptor. // When importing to another process, the reserved size is unknown until mapping the metadata, // hence the re-mapping below auto metadata = reinterpret_cast(handle->base_metadata); if (reserved_region_size == 0 && metadata->reservedSize) { size = getMetaDataSize(metadata->reservedSize); unmapAndReset(handle); void *new_base = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd_metadata, 0); if (new_base == reinterpret_cast(MAP_FAILED)) { ALOGE("%s: metadata mmap failed - handle:%p fd: %d err: %s", __func__, handle, handle->fd_metadata, strerror(errno)); return -1; } handle->base_metadata = (uintptr_t)new_base; } #endif } return 0; } static Error dataspaceToColorMetadata(Dataspace dataspace, ColorMetaData *color_metadata) { ColorMetaData out; uint32_t primaries = (uint32_t)dataspace & (uint32_t)Dataspace::STANDARD_MASK; uint32_t transfer = (uint32_t)dataspace & (uint32_t)Dataspace::TRANSFER_MASK; uint32_t range = (uint32_t)dataspace & (uint32_t)Dataspace::RANGE_MASK; switch (primaries) { case (uint32_t)Dataspace::STANDARD_BT709: out.colorPrimaries = ColorPrimaries_BT709_5; break; // TODO(tbalacha): verify this is equivalent case (uint32_t)Dataspace::STANDARD_BT470M: out.colorPrimaries = ColorPrimaries_BT470_6M; break; case (uint32_t)Dataspace::STANDARD_BT601_625: case (uint32_t)Dataspace::STANDARD_BT601_625_UNADJUSTED: out.colorPrimaries = ColorPrimaries_BT601_6_625; break; case (uint32_t)Dataspace::STANDARD_BT601_525: case (uint32_t)Dataspace::STANDARD_BT601_525_UNADJUSTED: out.colorPrimaries = ColorPrimaries_BT601_6_525; break; case (uint32_t)Dataspace::STANDARD_FILM: out.colorPrimaries = ColorPrimaries_GenericFilm; break; case (uint32_t)Dataspace::STANDARD_BT2020: out.colorPrimaries = ColorPrimaries_BT2020; break; case (uint32_t)Dataspace::STANDARD_ADOBE_RGB: out.colorPrimaries = ColorPrimaries_AdobeRGB; break; case (uint32_t)Dataspace::STANDARD_DCI_P3: out.colorPrimaries = ColorPrimaries_DCIP3; break; default: return Error::UNSUPPORTED; /* ColorPrimaries_SMPTE_240M; ColorPrimaries_SMPTE_ST428; ColorPrimaries_EBU3213; */ } switch (transfer) { case (uint32_t)Dataspace::TRANSFER_SRGB: out.transfer = Transfer_sRGB; break; case (uint32_t)Dataspace::TRANSFER_GAMMA2_2: out.transfer = Transfer_Gamma2_2; break; case (uint32_t)Dataspace::TRANSFER_GAMMA2_8: out.transfer = Transfer_Gamma2_8; break; case (uint32_t)Dataspace::TRANSFER_SMPTE_170M: out.transfer = Transfer_SMPTE_170M; break; case (uint32_t)Dataspace::TRANSFER_LINEAR: out.transfer = Transfer_Linear; break; case (uint32_t)Dataspace::TRANSFER_HLG: out.transfer = Transfer_HLG; break; default: return Error::UNSUPPORTED; /* Transfer_SMPTE_240M Transfer_Log Transfer_Log_Sqrt Transfer_XvYCC Transfer_BT1361 Transfer_sYCC Transfer_BT2020_2_1 Transfer_BT2020_2_2 Transfer_SMPTE_ST2084 Transfer_ST_428 */ } switch (range) { case (uint32_t)Dataspace::RANGE_FULL: out.range = Range_Full; break; case (uint32_t)Dataspace::RANGE_LIMITED: out.range = Range_Limited; break; case (uint32_t)Dataspace::RANGE_EXTENDED: out.range = Range_Extended; break; default: return Error::UNSUPPORTED; } color_metadata->colorPrimaries = out.colorPrimaries; color_metadata->transfer = out.transfer; color_metadata->range = out.range; return Error::NONE; } static Error colorMetadataToDataspace(ColorMetaData color_metadata, Dataspace *dataspace) { Dataspace primaries, transfer, range = Dataspace::UNKNOWN; switch (color_metadata.colorPrimaries) { case ColorPrimaries_BT709_5: primaries = Dataspace::STANDARD_BT709; break; // TODO(tbalacha): verify this is equivalent case ColorPrimaries_BT470_6M: primaries = Dataspace::STANDARD_BT470M; break; case ColorPrimaries_BT601_6_625: primaries = Dataspace::STANDARD_BT601_625; break; case ColorPrimaries_BT601_6_525: primaries = Dataspace::STANDARD_BT601_525; break; case ColorPrimaries_GenericFilm: primaries = Dataspace::STANDARD_FILM; break; case ColorPrimaries_BT2020: primaries = Dataspace::STANDARD_BT2020; break; case ColorPrimaries_AdobeRGB: primaries = Dataspace::STANDARD_ADOBE_RGB; break; case ColorPrimaries_DCIP3: primaries = Dataspace::STANDARD_DCI_P3; break; default: return Error::UNSUPPORTED; /* ColorPrimaries_SMPTE_240M; ColorPrimaries_SMPTE_ST428; ColorPrimaries_EBU3213; */ } switch (color_metadata.transfer) { case Transfer_sRGB: transfer = Dataspace::TRANSFER_SRGB; break; case Transfer_Gamma2_2: transfer = Dataspace::TRANSFER_GAMMA2_2; break; case Transfer_Gamma2_8: transfer = Dataspace::TRANSFER_GAMMA2_8; break; case Transfer_SMPTE_170M: transfer = Dataspace::TRANSFER_SMPTE_170M; break; case Transfer_Linear: transfer = Dataspace::TRANSFER_LINEAR; break; case Transfer_HLG: transfer = Dataspace::TRANSFER_HLG; break; default: return Error::UNSUPPORTED; /* Transfer_SMPTE_240M Transfer_Log Transfer_Log_Sqrt Transfer_XvYCC Transfer_BT1361 Transfer_sYCC Transfer_BT2020_2_1 Transfer_BT2020_2_2 Transfer_SMPTE_ST2084 Transfer_ST_428 */ } switch (color_metadata.range) { case Range_Full: range = Dataspace::RANGE_FULL; break; case Range_Limited: range = Dataspace::RANGE_LIMITED; break; case Range_Extended: range = Dataspace::RANGE_EXTENDED; break; default: return Error::UNSUPPORTED; } *dataspace = (Dataspace)((uint32_t)primaries | (uint32_t)transfer | (uint32_t)range); return Error::NONE; } static Error getComponentSizeAndOffset(int32_t format, PlaneLayoutComponent &comp) { switch (format) { case static_cast(HAL_PIXEL_FORMAT_RGBA_8888): case static_cast(HAL_PIXEL_FORMAT_RGBX_8888): case static_cast(HAL_PIXEL_FORMAT_RGB_888): comp.sizeInBits = 8; if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_R.value) { comp.offsetInBits = 0; } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_G.value) { comp.offsetInBits = 8; } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_B.value) { comp.offsetInBits = 16; } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_A.value && format != HAL_PIXEL_FORMAT_RGB_888) { comp.offsetInBits = 24; } else { return Error::BAD_VALUE; } break; case static_cast(HAL_PIXEL_FORMAT_RGB_565): if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_R.value) { comp.offsetInBits = 0; comp.sizeInBits = 5; } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_G.value) { comp.offsetInBits = 5; comp.sizeInBits = 6; } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_B.value) { comp.offsetInBits = 11; comp.sizeInBits = 5; } else { return Error::BAD_VALUE; } break; case static_cast(HAL_PIXEL_FORMAT_BGR_565): if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_R.value) { comp.offsetInBits = 11; comp.sizeInBits = 5; } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_G.value) { comp.offsetInBits = 5; comp.sizeInBits = 6; } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_B.value) { comp.offsetInBits = 0; comp.sizeInBits = 5; } else { return Error::BAD_VALUE; } break; case static_cast(HAL_PIXEL_FORMAT_BGRA_8888): case static_cast(HAL_PIXEL_FORMAT_BGRX_8888): case static_cast(HAL_PIXEL_FORMAT_BGR_888): comp.sizeInBits = 8; if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_R.value) { comp.offsetInBits = 16; } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_G.value) { comp.offsetInBits = 8; } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_B.value) { comp.offsetInBits = 0; } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_A.value && format != HAL_PIXEL_FORMAT_BGR_888) { comp.offsetInBits = 24; } else { return Error::BAD_VALUE; } break; case static_cast(HAL_PIXEL_FORMAT_RGBA_5551): if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_R.value) { comp.sizeInBits = 5; comp.offsetInBits = 0; } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_G.value) { comp.sizeInBits = 5; comp.offsetInBits = 5; } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_B.value) { comp.sizeInBits = 5; comp.offsetInBits = 10; } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_A.value) { comp.sizeInBits = 1; comp.offsetInBits = 15; } else { return Error::BAD_VALUE; } break; case static_cast(HAL_PIXEL_FORMAT_RGBA_4444): if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_R.value) { comp.sizeInBits = 4; comp.offsetInBits = 0; } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_G.value) { comp.sizeInBits = 4; comp.offsetInBits = 4; } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_B.value) { comp.sizeInBits = 4; comp.offsetInBits = 8; } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_A.value) { comp.sizeInBits = 4; comp.offsetInBits = 12; } else { return Error::BAD_VALUE; } break; case static_cast(HAL_PIXEL_FORMAT_R_8): case static_cast(HAL_PIXEL_FORMAT_RG_88): comp.sizeInBits = 8; if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_R.value) { comp.offsetInBits = 0; } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_G.value && format != HAL_PIXEL_FORMAT_R_8) { comp.offsetInBits = 8; } else { return Error::BAD_VALUE; } break; case static_cast(HAL_PIXEL_FORMAT_RGBA_1010102): case static_cast(HAL_PIXEL_FORMAT_RGBX_1010102): if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_R.value) { comp.sizeInBits = 10; comp.offsetInBits = 0; } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_G.value) { comp.sizeInBits = 10; comp.offsetInBits = 10; } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_B.value) { comp.sizeInBits = 10; comp.offsetInBits = 20; } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_A.value) { comp.sizeInBits = 2; comp.offsetInBits = 30; } else { return Error::BAD_VALUE; } break; case static_cast(HAL_PIXEL_FORMAT_ARGB_2101010): case static_cast(HAL_PIXEL_FORMAT_XRGB_2101010): if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_R.value) { comp.sizeInBits = 10; comp.offsetInBits = 2; } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_G.value) { comp.sizeInBits = 10; comp.offsetInBits = 12; } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_B.value) { comp.sizeInBits = 10; comp.offsetInBits = 22; } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_A.value) { comp.sizeInBits = 2; comp.offsetInBits = 0; } else { return Error::BAD_VALUE; } break; case static_cast(HAL_PIXEL_FORMAT_BGRA_1010102): case static_cast(HAL_PIXEL_FORMAT_BGRX_1010102): if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_R.value) { comp.sizeInBits = 10; comp.offsetInBits = 20; } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_G.value) { comp.sizeInBits = 10; comp.offsetInBits = 10; } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_B.value) { comp.sizeInBits = 10; comp.offsetInBits = 0; } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_A.value) { comp.sizeInBits = 2; comp.offsetInBits = 30; } else { return Error::BAD_VALUE; } break; case static_cast(HAL_PIXEL_FORMAT_ABGR_2101010): case static_cast(HAL_PIXEL_FORMAT_XBGR_2101010): if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_R.value) { comp.sizeInBits = 10; comp.offsetInBits = 22; } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_G.value) { comp.sizeInBits = 10; comp.offsetInBits = 12; } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_B.value) { comp.sizeInBits = 10; comp.offsetInBits = 2; } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_A.value) { comp.sizeInBits = 2; comp.offsetInBits = 0; } else { return Error::BAD_VALUE; } break; case static_cast(HAL_PIXEL_FORMAT_RGBA_FP16): if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_R.value) { comp.sizeInBits = 16; comp.offsetInBits = 0; } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_G.value) { comp.sizeInBits = 16; comp.offsetInBits = 16; } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_B.value) { comp.sizeInBits = 16; comp.offsetInBits = 32; } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_A.value) { comp.sizeInBits = 16; comp.offsetInBits = 48; } else { return Error::BAD_VALUE; } break; case static_cast(HAL_PIXEL_FORMAT_YCbCr_420_SP): case static_cast(HAL_PIXEL_FORMAT_YCbCr_422_SP): case static_cast(HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS): case static_cast(HAL_PIXEL_FORMAT_NV12_ENCODEABLE): comp.sizeInBits = 8; if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_Y.value || comp.type.value == android::gralloc4::PlaneLayoutComponentType_CB.value) { comp.offsetInBits = 0; } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_CR.value) { comp.offsetInBits = 8; } else { return Error::BAD_VALUE; } break; case static_cast(HAL_PIXEL_FORMAT_YCrCb_420_SP): case static_cast(HAL_PIXEL_FORMAT_YCrCb_422_SP): case static_cast(HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO): case static_cast(HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS): case static_cast(HAL_PIXEL_FORMAT_NV21_ZSL): comp.sizeInBits = 8; if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_Y.value || comp.type.value == android::gralloc4::PlaneLayoutComponentType_CR.value) { comp.offsetInBits = 0; } else if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_CB.value) { comp.offsetInBits = 8; } else { return Error::BAD_VALUE; } break; case static_cast(HAL_PIXEL_FORMAT_Y16): if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_Y.value) { comp.offsetInBits = 0; comp.sizeInBits = 16; } else { return Error::BAD_VALUE; } break; case static_cast(HAL_PIXEL_FORMAT_YV12): if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_Y.value || comp.type.value == android::gralloc4::PlaneLayoutComponentType_CB.value || comp.type.value == android::gralloc4::PlaneLayoutComponentType_CR.value) { comp.offsetInBits = 0; comp.sizeInBits = 8; } else { return Error::BAD_VALUE; } break; case static_cast(HAL_PIXEL_FORMAT_Y8): if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_Y.value) { comp.offsetInBits = 0; comp.sizeInBits = 8; } else { return Error::BAD_VALUE; } break; case static_cast(HAL_PIXEL_FORMAT_YCbCr_420_P010): if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_Y.value || comp.type.value == android::gralloc4::PlaneLayoutComponentType_CB.value || comp.type.value == android::gralloc4::PlaneLayoutComponentType_CR.value) { comp.offsetInBits = 0; comp.sizeInBits = 10; } else { return Error::BAD_VALUE; } break; case static_cast(HAL_PIXEL_FORMAT_RAW16): if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_RAW.value) { comp.offsetInBits = 0; comp.sizeInBits = 16; } else { return Error::BAD_VALUE; } break; case static_cast(HAL_PIXEL_FORMAT_RAW12): case static_cast(HAL_PIXEL_FORMAT_RAW10): case static_cast(HAL_PIXEL_FORMAT_BLOB): if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_RAW.value) { comp.offsetInBits = 0; comp.sizeInBits = -1; } else { return Error::BAD_VALUE; } break; case static_cast(HAL_PIXEL_FORMAT_RAW8): if (comp.type.value == android::gralloc4::PlaneLayoutComponentType_RAW.value) { comp.offsetInBits = 0; comp.sizeInBits = 8; } else { return Error::BAD_VALUE; } break; default: ALOGE("Offset and size in bits unknown for format %d", format); return Error::UNSUPPORTED; } return Error::NONE; } static void grallocToStandardPlaneLayoutComponentType(uint32_t in, std::vector *components, int32_t format) { PlaneLayoutComponent comp; comp.offsetInBits = -1; comp.sizeInBits = -1; if (in & PLANE_COMPONENT_Y) { comp.type = android::gralloc4::PlaneLayoutComponentType_Y; if (getComponentSizeAndOffset(format, comp) == Error::NONE) components->push_back(comp); } if (in & PLANE_COMPONENT_Cb) { comp.type = android::gralloc4::PlaneLayoutComponentType_CB; if (getComponentSizeAndOffset(format, comp) == Error::NONE) components->push_back(comp); } if (in & PLANE_COMPONENT_Cr) { comp.type = android::gralloc4::PlaneLayoutComponentType_CR; if (getComponentSizeAndOffset(format, comp) == Error::NONE) components->push_back(comp); } if (in & PLANE_COMPONENT_R) { comp.type = android::gralloc4::PlaneLayoutComponentType_R; if (getComponentSizeAndOffset(format, comp) == Error::NONE) components->push_back(comp); } if (in & PLANE_COMPONENT_G) { comp.type = android::gralloc4::PlaneLayoutComponentType_G; if (getComponentSizeAndOffset(format, comp) == Error::NONE) components->push_back(comp); } if (in & PLANE_COMPONENT_B) { comp.type = android::gralloc4::PlaneLayoutComponentType_B; if (getComponentSizeAndOffset(format, comp) == Error::NONE) components->push_back(comp); } if (in & PLANE_COMPONENT_A) { comp.type = android::gralloc4::PlaneLayoutComponentType_A; if (getComponentSizeAndOffset(format, comp) == Error::NONE) components->push_back(comp); } if (in & PLANE_COMPONENT_RAW) { comp.type = android::gralloc4::PlaneLayoutComponentType_RAW; if (getComponentSizeAndOffset(format, comp) == Error::NONE) components->push_back(comp); } if (in & PLANE_COMPONENT_META) { comp.type = qtigralloc::PlaneLayoutComponentType_Meta; components->push_back(comp); } } static Error getFormatLayout(private_handle_t *handle, std::vector *out) { std::vector plane_info; int plane_count = 0; BufferInfo info(handle->unaligned_width, handle->unaligned_height, handle->format, handle->usage); gralloc::PlaneLayoutInfo plane_layout[8] = {}; if (gralloc::IsYuvFormat(handle->format)) { gralloc::GetYUVPlaneInfo(info, handle->format, handle->width, handle->height, handle->flags, &plane_count, plane_layout); } else if (gralloc::IsUncompressedRGBFormat(handle->format) || gralloc::IsCompressedRGBFormat(handle->format)) { gralloc::GetRGBPlaneInfo(info, handle->format, handle->width, handle->height, handle->flags, &plane_count, plane_layout); } else { return Error::BAD_BUFFER; } plane_info.resize(plane_count); for (int i = 0; i < plane_count; i++) { std::vector components; grallocToStandardPlaneLayoutComponentType(plane_layout[i].component, &plane_info[i].components, handle->format); plane_info[i].horizontalSubsampling = (1ull << plane_layout[i].h_subsampling); plane_info[i].verticalSubsampling = (1ull << plane_layout[i].v_subsampling); plane_info[i].offsetInBytes = static_cast(plane_layout[i].offset); plane_info[i].sampleIncrementInBits = static_cast(plane_layout[i].step * 8); plane_info[i].strideInBytes = static_cast(plane_layout[i].stride_bytes); plane_info[i].totalSizeInBytes = static_cast(plane_layout[i].size); plane_info[i].widthInSamples = handle->unaligned_width >> plane_layout[i].h_subsampling; plane_info[i].heightInSamples = handle->unaligned_height >> plane_layout[i].v_subsampling; } *out = plane_info; return Error::NONE; } BufferManager::BufferManager() : next_id_(0) { handles_map_.clear(); allocator_ = new Allocator(); allocator_->Init(); } BufferManager *BufferManager::GetInstance() { static BufferManager *instance = new BufferManager(); return instance; } BufferManager::~BufferManager() { if (allocator_) { delete allocator_; } } void BufferManager::SetGrallocDebugProperties(gralloc::GrallocProperties props) { allocator_->SetProperties(props); AdrenoMemInfo::GetInstance()->AdrenoSetProperties(props); } Error BufferManager::FreeBuffer(std::shared_ptr buf) { auto hnd = buf->handle; ALOGD_IF(DEBUG, "FreeBuffer handle:%p", hnd); if (private_handle_t::validate(hnd) != 0) { ALOGE("FreeBuffer: Invalid handle: %p", hnd); return Error::BAD_BUFFER; } auto meta_size = getMetaDataSize(buf->reserved_size); if (allocator_->FreeBuffer(reinterpret_cast(hnd->base), hnd->size, hnd->offset, hnd->fd, buf->ion_handle_main) != 0) { return Error::BAD_BUFFER; } if (allocator_->FreeBuffer(reinterpret_cast(hnd->base_metadata), meta_size, hnd->offset_metadata, hnd->fd_metadata, buf->ion_handle_meta) != 0) { return Error::BAD_BUFFER; } private_handle_t *handle = const_cast(hnd); handle->fd = -1; handle->fd_metadata = -1; if (!(handle->flags & private_handle_t::PRIV_FLAGS_CLIENT_ALLOCATED)) { delete handle; } return Error::NONE; } Error BufferManager::ValidateBufferSize(private_handle_t const *hnd, BufferInfo info) { unsigned int size, alignedw, alignedh; info.format = GetImplDefinedFormat(info.usage, info.format); int ret = GetBufferSizeAndDimensions(info, &size, &alignedw, &alignedh); if (ret < 0) { return Error::BAD_BUFFER; } auto ion_fd_size = static_cast(lseek(hnd->fd, 0, SEEK_END)); if (size != ion_fd_size) { return Error::BAD_VALUE; } return Error::NONE; } void BufferManager::RegisterHandleLocked(const private_handle_t *hnd, int ion_handle, int ion_handle_meta) { auto buffer = std::make_shared(hnd, ion_handle, ion_handle_meta); if (hnd->base_metadata) { auto metadata = reinterpret_cast(hnd->base_metadata); #ifdef METADATA_V2 buffer->reserved_size = metadata->reservedSize; if (buffer->reserved_size > 0) { buffer->reserved_region_ptr = reinterpret_cast(hnd->base_metadata + sizeof(MetaData_t)); } else { buffer->reserved_region_ptr = nullptr; } #else buffer->reserved_region_ptr = reinterpret_cast(&(metadata->reservedRegion.data)); buffer->reserved_size = metadata->reservedRegion.size; #endif } handles_map_.emplace(std::make_pair(hnd, buffer)); } Error BufferManager::ImportHandleLocked(private_handle_t *hnd) { if (private_handle_t::validate(hnd) != 0) { ALOGE("ImportHandleLocked: Invalid handle: %p", hnd); return Error::BAD_BUFFER; } ALOGD_IF(DEBUG, "Importing handle:%p id: %" PRIu64, hnd, hnd->id); int ion_handle = allocator_->ImportBuffer(hnd->fd); if (ion_handle < 0) { ALOGE("Failed to import ion buffer: hnd: %p, fd:%d, id:%" PRIu64, hnd, hnd->fd, hnd->id); return Error::BAD_BUFFER; } int ion_handle_meta = allocator_->ImportBuffer(hnd->fd_metadata); if (ion_handle_meta < 0) { ALOGE("Failed to import ion metadata buffer: hnd: %p, fd:%d, id:%" PRIu64, hnd, hnd->fd, hnd->id); return Error::BAD_BUFFER; } // Initialize members that aren't transported hnd->size = static_cast(lseek(hnd->fd, 0, SEEK_END)); hnd->offset = 0; hnd->offset_metadata = 0; hnd->base = 0; hnd->base_metadata = 0; hnd->gpuaddr = 0; if (validateAndMap(hnd)) { ALOGE("Failed to map metadata: hnd: %p, fd:%d, id:%" PRIu64, hnd, hnd->fd, hnd->id); return Error::BAD_BUFFER; } RegisterHandleLocked(hnd, ion_handle, ion_handle_meta); allocated_ += hnd->size; if (allocated_ >= kAllocThreshold) { kAllocThreshold += kMemoryOffset; BuffersDump(); } return Error::NONE; } std::shared_ptr BufferManager::GetBufferFromHandleLocked( const private_handle_t *hnd) { auto it = handles_map_.find(hnd); if (it != handles_map_.end()) { return it->second; } else { return nullptr; } } Error BufferManager::MapBuffer(private_handle_t const *handle) { private_handle_t *hnd = const_cast(handle); ALOGD_IF(DEBUG, "Map buffer handle:%p id: %" PRIu64, hnd, hnd->id); hnd->base = 0; if (allocator_->MapBuffer(reinterpret_cast(&hnd->base), hnd->size, hnd->offset, hnd->fd) != 0) { return Error::BAD_BUFFER; } return Error::NONE; } Error BufferManager::IsBufferImported(const private_handle_t *hnd) { std::lock_guard lock(buffer_lock_); auto buf = GetBufferFromHandleLocked(hnd); if (buf != nullptr) { return Error::NONE; } return Error::BAD_BUFFER; } Error BufferManager::RetainBuffer(private_handle_t const *hnd) { ALOGD_IF(DEBUG, "Retain buffer handle:%p id: %" PRIu64, hnd, hnd->id); auto err = Error::NONE; std::lock_guard lock(buffer_lock_); auto buf = GetBufferFromHandleLocked(hnd); if (buf != nullptr) { buf->IncRef(); } else { private_handle_t *handle = const_cast(hnd); err = ImportHandleLocked(handle); } return err; } Error BufferManager::ReleaseBuffer(private_handle_t const *hnd) { ALOGD_IF(DEBUG, "Release buffer handle:%p", hnd); std::lock_guard lock(buffer_lock_); auto buf = GetBufferFromHandleLocked(hnd); if (buf == nullptr) { ALOGE("Could not find handle: %p id: %" PRIu64, hnd, hnd->id); return Error::BAD_BUFFER; } else { if (buf->DecRef()) { handles_map_.erase(hnd); // Unmap, close ion handle and close fd if (allocated_ >= hnd->size) { allocated_ -= hnd->size; } FreeBuffer(buf); } } return Error::NONE; } Error BufferManager::LockBuffer(const private_handle_t *hnd, uint64_t usage) { std::lock_guard lock(buffer_lock_); auto err = Error::NONE; ALOGD_IF(DEBUG, "LockBuffer buffer handle:%p id: %" PRIu64, hnd, hnd->id); // If buffer is not meant for CPU return err if (!CpuCanAccess(usage)) { return Error::BAD_VALUE; } auto buf = GetBufferFromHandleLocked(hnd); if (buf == nullptr) { return Error::BAD_BUFFER; } if (hnd->base == 0) { // we need to map for real err = MapBuffer(hnd); } // Invalidate if CPU reads in software and there are non-CPU // writers. No need to do this for the metadata buffer as it is // only read/written in software. // todo use handle here if (err == Error::NONE && (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) && (hnd->flags & private_handle_t::PRIV_FLAGS_CACHED)) { if (allocator_->CleanBuffer(reinterpret_cast(hnd->base), hnd->size, hnd->offset, buf->ion_handle_main, CACHE_INVALIDATE, hnd->fd)) { return Error::BAD_BUFFER; } } // Mark the buffer to be flushed after CPU write. if (err == Error::NONE && CpuCanWrite(usage)) { private_handle_t *handle = const_cast(hnd); handle->flags |= private_handle_t::PRIV_FLAGS_NEEDS_FLUSH; } return err; } Error BufferManager::FlushBuffer(const private_handle_t *handle) { std::lock_guard lock(buffer_lock_); auto status = Error::NONE; private_handle_t *hnd = const_cast(handle); auto buf = GetBufferFromHandleLocked(hnd); if (buf == nullptr) { return Error::BAD_BUFFER; } if (allocator_->CleanBuffer(reinterpret_cast(hnd->base), hnd->size, hnd->offset, buf->ion_handle_main, CACHE_CLEAN, hnd->fd) != 0) { status = Error::BAD_BUFFER; } return status; } Error BufferManager::RereadBuffer(const private_handle_t *handle) { std::lock_guard lock(buffer_lock_); auto status = Error::NONE; private_handle_t *hnd = const_cast(handle); auto buf = GetBufferFromHandleLocked(hnd); if (buf == nullptr) { return Error::BAD_BUFFER; } if (allocator_->CleanBuffer(reinterpret_cast(hnd->base), hnd->size, hnd->offset, buf->ion_handle_main, CACHE_INVALIDATE, hnd->fd) != 0) { status = Error::BAD_BUFFER; } return status; } Error BufferManager::UnlockBuffer(const private_handle_t *handle) { std::lock_guard lock(buffer_lock_); auto status = Error::NONE; private_handle_t *hnd = const_cast(handle); auto buf = GetBufferFromHandleLocked(hnd); if (buf == nullptr) { return Error::BAD_BUFFER; } if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) { if (allocator_->CleanBuffer(reinterpret_cast(hnd->base), hnd->size, hnd->offset, buf->ion_handle_main, CACHE_CLEAN, hnd->fd) != 0) { status = Error::BAD_BUFFER; } hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH; } else { if (allocator_->CleanBuffer(reinterpret_cast(hnd->base), hnd->size, hnd->offset, buf->ion_handle_main, CACHE_READ_DONE, hnd->fd) != 0) { status = Error::BAD_BUFFER; } } return status; } Error BufferManager::AllocateBuffer(const BufferDescriptor &descriptor, buffer_handle_t *handle, unsigned int bufferSize, bool testAlloc) { if (!handle) return Error::BAD_BUFFER; std::lock_guard buffer_lock(buffer_lock_); uint64_t usage = descriptor.GetUsage(); int format = GetImplDefinedFormat(usage, descriptor.GetFormat()); uint32_t layer_count = descriptor.GetLayerCount(); unsigned int size; unsigned int alignedw, alignedh; int err = 0; int buffer_type = GetBufferType(format); BufferInfo info = GetBufferInfo(descriptor); info.format = format; info.layer_count = layer_count; GraphicsMetadata graphics_metadata = {}; err = GetBufferSizeAndDimensions(info, &size, &alignedw, &alignedh, &graphics_metadata); if (err < 0) { return Error::BAD_DESCRIPTOR; } if (testAlloc) { return Error::NONE; } size = (bufferSize >= size) ? bufferSize : size; uint64_t flags = 0; auto page_size = UINT(getpagesize()); AllocData data; data.align = GetDataAlignment(format, usage); data.size = size; data.handle = (uintptr_t)handle; data.uncached = UseUncached(format, usage); // Allocate buffer memory err = allocator_->AllocateMem(&data, usage, format); if (err) { ALOGE("gralloc failed to allocate err=%s format %d size %d WxH %dx%d usage %" PRIu64, strerror(-err), format, size, alignedw, alignedh, usage); return Error::NO_RESOURCES; } // Allocate memory for MetaData AllocData e_data; e_data.size = static_cast(getMetaDataSize(descriptor.GetReservedSize())); e_data.handle = data.handle; e_data.align = page_size; err = allocator_->AllocateMem(&e_data, 0, 0); if (err) { ALOGE("gralloc failed to allocate metadata error=%s", strerror(-err)); return Error::NO_RESOURCES; } flags = GetHandleFlags(format, usage); flags |= data.alloc_type; // Create handle private_handle_t *hnd = new private_handle_t( data.fd, e_data.fd, INT(flags), INT(alignedw), INT(alignedh), descriptor.GetWidth(), descriptor.GetHeight(), format, buffer_type, data.size, usage); hnd->id = ++next_id_; hnd->base = 0; hnd->base_metadata = 0; hnd->layer_count = layer_count; bool use_adreno_for_size = CanUseAdrenoForSize(buffer_type, usage); if (use_adreno_for_size) { setMetaDataAndUnmap(hnd, SET_GRAPHICS_METADATA, reinterpret_cast(&graphics_metadata)); } #ifdef METADATA_V2 auto error = validateAndMap(hnd, descriptor.GetReservedSize()); #else auto error = validateAndMap(hnd); #endif if (error != 0) { ALOGE("validateAndMap failed"); return Error::BAD_BUFFER; } auto metadata = reinterpret_cast(hnd->base_metadata); auto nameLength = std::min(descriptor.GetName().size(), size_t(MAX_NAME_LEN - 1)); nameLength = descriptor.GetName().copy(metadata->name, nameLength); metadata->name[nameLength] = '\0'; #ifdef METADATA_V2 metadata->reservedSize = descriptor.GetReservedSize(); #else metadata->reservedRegion.size = std::min(descriptor.GetReservedSize(), (uint64_t)RESERVED_REGION_SIZE); #endif metadata->crop.top = 0; metadata->crop.left = 0; metadata->crop.right = hnd->width; metadata->crop.bottom = hnd->height; unmapAndReset(hnd, descriptor.GetReservedSize()); *handle = hnd; RegisterHandleLocked(hnd, data.ion_handle, e_data.ion_handle); ALOGD_IF(DEBUG, "Allocated buffer handle: %p id: %" PRIu64, hnd, hnd->id); if (DEBUG) { private_handle_t::Dump(hnd); } return Error::NONE; } void BufferManager:: BuffersDump() { char timeStamp[32]; char hms[32]; uint64_t millis; struct timeval tv; struct tm ptm; gettimeofday(&tv, NULL); localtime_r(&tv.tv_sec, &ptm); strftime (hms, sizeof (hms), "%H:%M:%S", &ptm); millis = tv.tv_usec / 1000; snprintf(timeStamp, sizeof(timeStamp), "Timestamp: %s.%03" PRIu64, hms, millis); std::fstream fs; fs.open(file_dump_.kDumpFile, std::ios::app); if (!fs) { return; } fs << "============================" << std::endl; fs << timeStamp << std::endl; fs << "Total layers = " << handles_map_.size() << std::endl; uint64_t totalAllocationSize = 0; for (auto it : handles_map_) { auto buf = it.second; auto hnd = buf->handle; auto metadata = reinterpret_cast(hnd->base_metadata); fs << std::setw(80) << "Client:" << (metadata ? metadata->name: "No name"); fs << std::setw(20) << "WxH:" << std::setw(4) << hnd->width << " x " << std::setw(4) << hnd->height; fs << std::setw(20) << "Size: " << std::setw(9) << hnd->size << std::endl; totalAllocationSize += hnd->size; } fs << "Total allocation = " << totalAllocationSize/1024 << "KiB" << std::endl; file_dump_.position = fs.tellp(); if (file_dump_.position > (20 * 1024 * 1024)) { file_dump_.position = 0; } fs.close(); } Error BufferManager::Dump(std::ostringstream *os) { std::lock_guard buffer_lock(buffer_lock_); for (auto it : handles_map_) { auto buf = it.second; auto hnd = buf->handle; *os << "handle id: " << std::setw(4) << hnd->id; *os << " fd: " << std::setw(3) << hnd->fd; *os << " fd_meta: " << std::setw(3) << hnd->fd_metadata; *os << " wxh: " << std::setw(4) << hnd->width << " x " << std::setw(4) << hnd->height; *os << " uwxuh: " << std::setw(4) << hnd->unaligned_width << " x "; *os << std::setw(4) << hnd->unaligned_height; *os << " size: " << std::setw(9) << hnd->size; *os << std::hex << std::setfill('0'); *os << " priv_flags: " << "0x" << std::setw(8) << hnd->flags; *os << " usage: " << "0x" << std::setw(8) << hnd->usage; // TODO(user): get format string from qdutils *os << " format: " << "0x" << std::setw(8) << hnd->format; *os << std::dec << std::setfill(' ') << std::endl; } return Error::NONE; } // Get list of private handles in handles_map_ Error BufferManager::GetAllHandles(std::vector *out_handle_list) { std::lock_guard lock(buffer_lock_); if (handles_map_.empty()) { return Error::NO_RESOURCES; } out_handle_list->reserve(handles_map_.size()); for (auto handle : handles_map_) { out_handle_list->push_back(handle.first); } return Error::NONE; } Error BufferManager::GetReservedRegion(private_handle_t *handle, void **reserved_region, uint64_t *reserved_region_size) { std::lock_guard lock(buffer_lock_); if (!handle) return Error::BAD_BUFFER; auto buf = GetBufferFromHandleLocked(handle); if (buf == nullptr) return Error::BAD_BUFFER; if (!handle->base_metadata) { return Error::BAD_BUFFER; } *reserved_region = buf->reserved_region_ptr; *reserved_region_size = buf->reserved_size; return Error::NONE; } Error BufferManager::GetMetadata(private_handle_t *handle, int64_t metadatatype_value, hidl_vec *out) { std::lock_guard lock(buffer_lock_); if (!handle) return Error::BAD_BUFFER; auto buf = GetBufferFromHandleLocked(handle); if (buf == nullptr) return Error::BAD_BUFFER; if (!handle->base_metadata) { return Error::BAD_BUFFER; } auto metadata = reinterpret_cast(handle->base_metadata); Error error = Error::NONE; switch (metadatatype_value) { case (int64_t)StandardMetadataType::BUFFER_ID: android::gralloc4::encodeBufferId((uint64_t)handle->id, out); break; case (int64_t)StandardMetadataType::NAME: { std::string name(metadata->name); android::gralloc4::encodeName(name, out); break; } case (int64_t)StandardMetadataType::WIDTH: android::gralloc4::encodeWidth((uint64_t)handle->unaligned_width, out); break; case (int64_t)StandardMetadataType::HEIGHT: android::gralloc4::encodeHeight((uint64_t)handle->unaligned_height, out); break; case (int64_t)StandardMetadataType::LAYER_COUNT: android::gralloc4::encodeLayerCount((uint64_t)handle->layer_count, out); break; case (int64_t)StandardMetadataType::PIXEL_FORMAT_REQUESTED: // TODO(tbalacha): need to return IMPLEMENTATION_DEFINED, // which wouldn't be known from private_handle_t android::gralloc4::encodePixelFormatRequested((PixelFormat)handle->format, out); break; case (int64_t)StandardMetadataType::PIXEL_FORMAT_FOURCC: { uint32_t drm_format = 0; uint64_t drm_format_modifier = 0; GetDRMFormat(handle->format, handle->flags, &drm_format, &drm_format_modifier); android::gralloc4::encodePixelFormatFourCC(drm_format, out); break; } case (int64_t)StandardMetadataType::PIXEL_FORMAT_MODIFIER: { uint32_t drm_format = 0; uint64_t drm_format_modifier = 0; GetDRMFormat(handle->format, handle->flags, &drm_format, &drm_format_modifier); android::gralloc4::encodePixelFormatModifier(drm_format_modifier, out); break; } case (int64_t)StandardMetadataType::USAGE: android::gralloc4::encodeUsage((uint64_t)handle->usage, out); break; case (int64_t)StandardMetadataType::ALLOCATION_SIZE: android::gralloc4::encodeAllocationSize((uint64_t)handle->size, out); break; case (int64_t)StandardMetadataType::PROTECTED_CONTENT: { uint64_t protected_content = (handle->flags & qtigralloc::PRIV_FLAGS_SECURE_BUFFER) ? 1 : 0; android::gralloc4::encodeProtectedContent(protected_content, out); break; } case (int64_t)StandardMetadataType::CHROMA_SITING: android::gralloc4::encodeChromaSiting(android::gralloc4::ChromaSiting_None, out); break; case (int64_t)StandardMetadataType::DATASPACE: #ifdef METADATA_V2 if (metadata->isStandardMetadataSet[GET_STANDARD_METADATA_STATUS_INDEX(metadatatype_value)]) { #endif Dataspace dataspace; colorMetadataToDataspace(metadata->color, &dataspace); android::gralloc4::encodeDataspace(dataspace, out); #ifdef METADATA_V2 } else { android::gralloc4::encodeDataspace(Dataspace::UNKNOWN, out); } #endif break; case (int64_t)StandardMetadataType::INTERLACED: if (metadata->interlaced > 0) { android::gralloc4::encodeInterlaced(qtigralloc::Interlaced_Qti, out); } else { android::gralloc4::encodeInterlaced(android::gralloc4::Interlaced_None, out); } break; case (int64_t)StandardMetadataType::COMPRESSION: if (handle->flags & qtigralloc::PRIV_FLAGS_UBWC_ALIGNED || handle->flags & qtigralloc::PRIV_FLAGS_UBWC_ALIGNED_PI) { android::gralloc4::encodeCompression(qtigralloc::Compression_QtiUBWC, out); } else { android::gralloc4::encodeCompression(android::gralloc4::Compression_None, out); } break; case (int64_t)StandardMetadataType::PLANE_LAYOUTS: { std::vector plane_layouts; getFormatLayout(handle, &plane_layouts); android::gralloc4::encodePlaneLayouts(plane_layouts, out); break; } case (int64_t)StandardMetadataType::BLEND_MODE: android::gralloc4::encodeBlendMode((BlendMode)metadata->blendMode, out); break; case (int64_t)StandardMetadataType::SMPTE2086: { if (metadata->color.masteringDisplayInfo.colorVolumeSEIEnabled) { Smpte2086 mastering_display_values; mastering_display_values.primaryRed = { static_cast(metadata->color.masteringDisplayInfo.primaries.rgbPrimaries[0][0]) / 50000.0f, static_cast(metadata->color.masteringDisplayInfo.primaries.rgbPrimaries[0][1]) / 50000.0f}; mastering_display_values.primaryGreen = { static_cast(metadata->color.masteringDisplayInfo.primaries.rgbPrimaries[1][0]) / 50000.0f, static_cast(metadata->color.masteringDisplayInfo.primaries.rgbPrimaries[1][1]) / 50000.0f}; mastering_display_values.primaryBlue = { static_cast(metadata->color.masteringDisplayInfo.primaries.rgbPrimaries[2][0]) / 50000.0f, static_cast(metadata->color.masteringDisplayInfo.primaries.rgbPrimaries[2][1]) / 50000.0f}; mastering_display_values.whitePoint = { static_cast(metadata->color.masteringDisplayInfo.primaries.whitePoint[0]) / 50000.0f, static_cast(metadata->color.masteringDisplayInfo.primaries.whitePoint[1]) / 50000.0f}; mastering_display_values.maxLuminance = static_cast(metadata->color.masteringDisplayInfo.maxDisplayLuminance); mastering_display_values.minLuminance = static_cast(metadata->color.masteringDisplayInfo.minDisplayLuminance) / 10000.0f; android::gralloc4::encodeSmpte2086(mastering_display_values, out); } else { android::gralloc4::encodeSmpte2086(std::nullopt, out); } break; } case (int64_t)StandardMetadataType::CTA861_3: { if (metadata->color.contentLightLevel.lightLevelSEIEnabled) { Cta861_3 content_light_level; content_light_level.maxContentLightLevel = static_cast(metadata->color.contentLightLevel.maxContentLightLevel); content_light_level.maxFrameAverageLightLevel = static_cast(metadata->color.contentLightLevel.minPicAverageLightLevel) / 10000.0f; android::gralloc4::encodeCta861_3(content_light_level, out); } else { android::gralloc4::encodeCta861_3(std::nullopt, out); } break; } case (int64_t)StandardMetadataType::SMPTE2094_40: { if (metadata->color.dynamicMetaDataValid && metadata->color.dynamicMetaDataLen <= HDR_DYNAMIC_META_DATA_SZ) { std::vector dynamic_metadata_payload; dynamic_metadata_payload.resize(metadata->color.dynamicMetaDataLen); dynamic_metadata_payload.assign( metadata->color.dynamicMetaDataPayload, metadata->color.dynamicMetaDataPayload + metadata->color.dynamicMetaDataLen); android::gralloc4::encodeSmpte2094_40(dynamic_metadata_payload, out); } else { android::gralloc4::encodeSmpte2094_40(std::nullopt, out); } break; } case (int64_t)StandardMetadataType::CROP: { // Crop is the same for all planes std::vector out_crop = {{metadata->crop.left, metadata->crop.top, metadata->crop.right, metadata->crop.bottom}}; android::gralloc4::encodeCrop(out_crop, out); break; } case QTI_VT_TIMESTAMP: android::gralloc4::encodeUint64(qtigralloc::MetadataType_VTTimestamp, metadata->vtTimeStamp, out); break; case QTI_COLOR_METADATA: qtigralloc::encodeColorMetadata(metadata->color, out); break; case QTI_PP_PARAM_INTERLACED: android::gralloc4::encodeInt32(qtigralloc::MetadataType_PPParamInterlaced, metadata->interlaced, out); break; case QTI_VIDEO_PERF_MODE: android::gralloc4::encodeUint32(qtigralloc::MetadataType_VideoPerfMode, metadata->isVideoPerfMode, out); break; case QTI_GRAPHICS_METADATA: qtigralloc::encodeGraphicsMetadata(metadata->graphics_metadata, out); break; case QTI_UBWC_CR_STATS_INFO: qtigralloc::encodeUBWCStats(metadata->ubwcCRStats, out); break; case QTI_REFRESH_RATE: android::gralloc4::encodeFloat(qtigralloc::MetadataType_RefreshRate, metadata->refreshrate, out); break; case QTI_MAP_SECURE_BUFFER: android::gralloc4::encodeInt32(qtigralloc::MetadataType_MapSecureBuffer, metadata->mapSecureBuffer, out); break; case QTI_LINEAR_FORMAT: android::gralloc4::encodeUint32(qtigralloc::MetadataType_LinearFormat, metadata->linearFormat, out); break; case QTI_SINGLE_BUFFER_MODE: android::gralloc4::encodeUint32(qtigralloc::MetadataType_SingleBufferMode, metadata->isSingleBufferMode, out); break; case QTI_CVP_METADATA: qtigralloc::encodeCVPMetadata(metadata->cvpMetadata, out); break; case QTI_VIDEO_HISTOGRAM_STATS: qtigralloc::encodeVideoHistogramMetadata(metadata->video_histogram_stats, out); break; case QTI_FD: android::gralloc4::encodeInt32(qtigralloc::MetadataType_FD, handle->fd, out); break; case QTI_PRIVATE_FLAGS: android::gralloc4::encodeInt32(qtigralloc::MetadataType_PrivateFlags, handle->flags, out); break; case QTI_ALIGNED_WIDTH_IN_PIXELS: android::gralloc4::encodeUint32(qtigralloc::MetadataType_AlignedWidthInPixels, handle->width, out); break; case QTI_ALIGNED_HEIGHT_IN_PIXELS: android::gralloc4::encodeUint32(qtigralloc::MetadataType_AlignedHeightInPixels, handle->height, out); break; #ifdef METADATA_V2 case QTI_STANDARD_METADATA_STATUS: qtigralloc::encodeMetadataState(metadata->isStandardMetadataSet, out); break; case QTI_VENDOR_METADATA_STATUS: qtigralloc::encodeMetadataState(metadata->isVendorMetadataSet, out); break; #endif #ifdef QTI_BUFFER_TYPE case QTI_BUFFER_TYPE: android::gralloc4::encodeUint32(qtigralloc::MetadataType_BufferType, handle->buffer_type, out); break; #endif default: error = Error::UNSUPPORTED; } return error; } Error BufferManager::SetMetadata(private_handle_t *handle, int64_t metadatatype_value, hidl_vec in) { std::lock_guard lock(buffer_lock_); if (!handle) return Error::BAD_BUFFER; auto buf = GetBufferFromHandleLocked(handle); if (buf == nullptr) return Error::BAD_BUFFER; if (!handle->base_metadata) { return Error::BAD_BUFFER; } if (in.size() == 0) { return Error::UNSUPPORTED; } auto metadata = reinterpret_cast(handle->base_metadata); #ifdef METADATA_V2 // By default, set these to true // Reset to false for special cases below if (IS_VENDOR_METADATA_TYPE(metadatatype_value)) { metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(metadatatype_value)] = true; } else if (GET_STANDARD_METADATA_STATUS_INDEX(metadatatype_value) < METADATA_SET_SIZE) { metadata->isStandardMetadataSet[GET_STANDARD_METADATA_STATUS_INDEX(metadatatype_value)] = true; } #endif switch (metadatatype_value) { // These are constant (unchanged after allocation) case (int64_t)StandardMetadataType::BUFFER_ID: case (int64_t)StandardMetadataType::NAME: case (int64_t)StandardMetadataType::WIDTH: case (int64_t)StandardMetadataType::HEIGHT: case (int64_t)StandardMetadataType::LAYER_COUNT: case (int64_t)StandardMetadataType::PIXEL_FORMAT_REQUESTED: case (int64_t)StandardMetadataType::USAGE: return Error::BAD_VALUE; case (int64_t)StandardMetadataType::PIXEL_FORMAT_FOURCC: case (int64_t)StandardMetadataType::PIXEL_FORMAT_MODIFIER: case (int64_t)StandardMetadataType::PROTECTED_CONTENT: case (int64_t)StandardMetadataType::ALLOCATION_SIZE: case (int64_t)StandardMetadataType::PLANE_LAYOUTS: case (int64_t)StandardMetadataType::CHROMA_SITING: case (int64_t)StandardMetadataType::INTERLACED: case (int64_t)StandardMetadataType::COMPRESSION: case QTI_FD: case QTI_PRIVATE_FLAGS: case QTI_ALIGNED_WIDTH_IN_PIXELS: case QTI_ALIGNED_HEIGHT_IN_PIXELS: return Error::UNSUPPORTED; case (int64_t)StandardMetadataType::DATASPACE: Dataspace dataspace; android::gralloc4::decodeDataspace(in, &dataspace); dataspaceToColorMetadata(dataspace, &metadata->color); break; case (int64_t)StandardMetadataType::BLEND_MODE: BlendMode mode; android::gralloc4::decodeBlendMode(in, &mode); metadata->blendMode = (int32_t)mode; break; case (int64_t)StandardMetadataType::SMPTE2086: { std::optional mastering_display_values; android::gralloc4::decodeSmpte2086(in, &mastering_display_values); if (mastering_display_values != std::nullopt) { metadata->color.masteringDisplayInfo.colorVolumeSEIEnabled = true; metadata->color.masteringDisplayInfo.primaries.rgbPrimaries[0][0] = static_cast(mastering_display_values->primaryRed.x * 50000.0f); metadata->color.masteringDisplayInfo.primaries.rgbPrimaries[0][1] = static_cast(mastering_display_values->primaryRed.y * 50000.0f); metadata->color.masteringDisplayInfo.primaries.rgbPrimaries[1][0] = static_cast(mastering_display_values->primaryGreen.x * 50000.0f); metadata->color.masteringDisplayInfo.primaries.rgbPrimaries[1][1] = static_cast(mastering_display_values->primaryGreen.y * 50000.0f); metadata->color.masteringDisplayInfo.primaries.rgbPrimaries[2][0] = static_cast(mastering_display_values->primaryBlue.x * 50000.0f); metadata->color.masteringDisplayInfo.primaries.rgbPrimaries[2][1] = static_cast(mastering_display_values->primaryBlue.y * 50000.0f); metadata->color.masteringDisplayInfo.primaries.whitePoint[0] = static_cast(mastering_display_values->whitePoint.x * 50000.0f); metadata->color.masteringDisplayInfo.primaries.whitePoint[1] = static_cast(mastering_display_values->whitePoint.y * 50000.0f); metadata->color.masteringDisplayInfo.maxDisplayLuminance = static_cast(mastering_display_values->maxLuminance); metadata->color.masteringDisplayInfo.minDisplayLuminance = static_cast(mastering_display_values->minLuminance * 10000.0f); } else { #ifdef METADATA_V2 metadata->isStandardMetadataSet[GET_STANDARD_METADATA_STATUS_INDEX(metadatatype_value)] = false; #endif metadata->color.masteringDisplayInfo.colorVolumeSEIEnabled = false; } break; } case (int64_t)StandardMetadataType::CTA861_3: { std::optional content_light_level; android::gralloc4::decodeCta861_3(in, &content_light_level); if (content_light_level != std::nullopt) { metadata->color.contentLightLevel.lightLevelSEIEnabled = true; metadata->color.contentLightLevel.maxContentLightLevel = static_cast(content_light_level->maxContentLightLevel); metadata->color.contentLightLevel.minPicAverageLightLevel = static_cast(content_light_level->maxFrameAverageLightLevel * 10000.0f); } else { #ifdef METADATA_V2 metadata->isStandardMetadataSet[GET_STANDARD_METADATA_STATUS_INDEX(metadatatype_value)] = false; #endif metadata->color.contentLightLevel.lightLevelSEIEnabled = false; } break; } case (int64_t)StandardMetadataType::SMPTE2094_40: { std::optional> dynamic_metadata_payload; android::gralloc4::decodeSmpte2094_40(in, &dynamic_metadata_payload); if (dynamic_metadata_payload != std::nullopt) { if (dynamic_metadata_payload->size() > HDR_DYNAMIC_META_DATA_SZ || dynamic_metadata_payload->size() == 0) return Error::BAD_VALUE; metadata->color.dynamicMetaDataLen = dynamic_metadata_payload->size(); std::copy(dynamic_metadata_payload->begin(), dynamic_metadata_payload->end(), metadata->color.dynamicMetaDataPayload); metadata->color.dynamicMetaDataValid = true; } else { // Reset metadata by passing in std::nullopt #ifdef METADATA_V2 metadata->isStandardMetadataSet[GET_STANDARD_METADATA_STATUS_INDEX(metadatatype_value)] = false; #endif metadata->color.dynamicMetaDataValid = false; } break; } case (int64_t)StandardMetadataType::CROP: { std::vector in_crop; android::gralloc4::decodeCrop(in, &in_crop); if (in_crop.size() != 1) return Error::UNSUPPORTED; metadata->crop.left = in_crop[0].left; metadata->crop.top = in_crop[0].top; metadata->crop.right = in_crop[0].right; metadata->crop.bottom = in_crop[0].bottom; break; } case QTI_VT_TIMESTAMP: android::gralloc4::decodeUint64(qtigralloc::MetadataType_VTTimestamp, in, &metadata->vtTimeStamp); break; case QTI_COLOR_METADATA: ColorMetaData color; qtigralloc::decodeColorMetadata(in, &color); metadata->color = color; break; case QTI_PP_PARAM_INTERLACED: android::gralloc4::decodeInt32(qtigralloc::MetadataType_PPParamInterlaced, in, &metadata->interlaced); break; case QTI_VIDEO_PERF_MODE: android::gralloc4::decodeUint32(qtigralloc::MetadataType_VideoPerfMode, in, &metadata->isVideoPerfMode); break; case QTI_GRAPHICS_METADATA: qtigralloc::decodeGraphicsMetadata(in, &metadata->graphics_metadata); break; case QTI_UBWC_CR_STATS_INFO: qtigralloc::decodeUBWCStats(in, &metadata->ubwcCRStats[0]); break; case QTI_REFRESH_RATE: android::gralloc4::decodeFloat(qtigralloc::MetadataType_RefreshRate, in, &metadata->refreshrate); break; case QTI_MAP_SECURE_BUFFER: android::gralloc4::decodeInt32(qtigralloc::MetadataType_MapSecureBuffer, in, &metadata->mapSecureBuffer); break; case QTI_LINEAR_FORMAT: android::gralloc4::decodeUint32(qtigralloc::MetadataType_LinearFormat, in, &metadata->linearFormat); break; case QTI_SINGLE_BUFFER_MODE: android::gralloc4::decodeUint32(qtigralloc::MetadataType_SingleBufferMode, in, &metadata->isSingleBufferMode); break; case QTI_CVP_METADATA: qtigralloc::decodeCVPMetadata(in, &metadata->cvpMetadata); break; case QTI_VIDEO_HISTOGRAM_STATS: qtigralloc::decodeVideoHistogramMetadata(in, &metadata->video_histogram_stats); break; default: #ifdef METADATA_V2 if (IS_VENDOR_METADATA_TYPE(metadatatype_value)) { metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(metadatatype_value)] = false; } else if (GET_STANDARD_METADATA_STATUS_INDEX(metadatatype_value) < METADATA_SET_SIZE) { metadata->isStandardMetadataSet[GET_STANDARD_METADATA_STATUS_INDEX(metadatatype_value)] = false; } #endif return Error::BAD_VALUE; } return Error::NONE; } } // namespace gralloc