/* * Copyright (C) 2019-2020 RockChip Limited. All rights reserved. * * 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. */ /* -------------------------------------------------------------------------------------------------------- * File: platform_gralloc4.c * * Desc: 具体实现 platform_gralloc4.h 定义的接口, 基于 IMapper 4.0. * * ----------------------------------------------------------------------------------- * < 习语 和 缩略语 > : * * ----------------------------------------------------------------------------------- * < 内部模块 or 对象的层次结构 > : * * ----------------------------------------------------------------------------------- * < 功能实现的基本流程 > : * * ----------------------------------------------------------------------------------- * < 关键标识符 > : * * ----------------------------------------------------------------------------------- * < 本模块实现依赖的外部模块 > : * ... * ----------------------------------------------------------------------------------- * Note: * * Author: ChenZhen * * Log: * init ----Fri Aug 28 10:17:46 2020 */ /* --------------------------------------------------------------------------------------------------------- * Include Files * --------------------------------------------------------------------------------------------------------- */ #define LOG_TAG "platform_gralloc4" // #define ENABLE_DEBUG_LOG #include #include #include #include "mali_gralloc_formats.h" #include #include "platform_gralloc4.h" #include #include #ifdef ANDROID_S #include #endif // #include using android::hardware::graphics::mapper::V4_0::Error; using android::hardware::graphics::mapper::V4_0::IMapper; using android::hardware::hidl_vec; using android::gralloc4::MetadataType_PlaneLayouts; using android::gralloc4::decodePlaneLayouts; using android::gralloc4::MetadataType_Usage; using android::gralloc4::decodeUsage; using android::gralloc4::MetadataType_PlaneLayouts; using android::gralloc4::decodePlaneLayouts; using android::gralloc4::MetadataType_PixelFormatFourCC; using android::gralloc4::decodePixelFormatFourCC; using android::gralloc4::MetadataType_PixelFormatModifier; using android::gralloc4::decodePixelFormatModifier; using android::gralloc4::MetadataType_PixelFormatRequested; using android::gralloc4::decodePixelFormatRequested; using android::gralloc4::MetadataType_AllocationSize; using android::gralloc4::decodeAllocationSize; using android::gralloc4::MetadataType_LayerCount; using android::gralloc4::decodeLayerCount; using android::gralloc4::MetadataType_Dataspace; using android::gralloc4::decodeDataspace; using android::gralloc4::MetadataType_Crop; using android::gralloc4::decodeCrop; using android::gralloc4::MetadataType_Width; using android::gralloc4::decodeWidth; using android::gralloc4::MetadataType_Height; using android::gralloc4::decodeHeight; using android::gralloc4::MetadataType_Name; using android::gralloc4::decodeName; using aidl::android::hardware::graphics::common::Dataspace; using aidl::android::hardware::graphics::common::PlaneLayout; using aidl::android::hardware::graphics::common::ExtendableType; using aidl::android::hardware::graphics::common::PlaneLayout; using aidl::android::hardware::graphics::common::Rect; using android::hardware::graphics::common::V1_2::PixelFormat; #define GRALLOC_ARM_METADATA_TYPE_NAME "arm.graphics.ArmMetadataType" const static IMapper::MetadataType ArmMetadataType_PLANE_FDS { GRALLOC_ARM_METADATA_TYPE_NAME, // static_cast(aidl::arm::graphics::ArmMetadataType::PLANE_FDS) 1 // 就是上面的 'PLANE_FDS' }; /* --------------------------------------------------------------------------------------------------------- * External Function Prototypes (referenced in this file) * --------------------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------------------- * Local Macros * --------------------------------------------------------------------------------------------------------- */ namespace gralloc4 { /* --------------------------------------------------------------------------------------------------------- * Local Typedefs * --------------------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------------------- * Local Function Prototypes * --------------------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------------------- * Local Variables * --------------------------------------------------------------------------------------------------------- */ static constexpr Error kTransactionError = Error::NO_RESOURCES; /* --------------------------------------------------------------------------------------------------------- * Global Variables * --------------------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------------------- * Local Functions Implementation * --------------------------------------------------------------------------------------------------------- */ static IMapper &get_service() { static android::sp cached_service = IMapper::getService(); return *cached_service; } template static int get_metadata(IMapper &mapper, buffer_handle_t handle, IMapper::MetadataType type, android::status_t (*decode)(const hidl_vec &, T *), T *value) { void *handle_arg = const_cast(handle); assert(handle_arg); assert(value); assert(decode); int err = 0; mapper.get(handle_arg, type, [&err, value, decode](Error error, const hidl_vec &metadata) { if (error != Error::NONE) { err = android::BAD_VALUE; return; } err = decode(metadata, value); }); return err; } /* * 参考 b_r25p1 gralloc 中的 drm_fourcc_from_handle() 实现. * 目前未考虑 'modifier' */ uint64_t get_internal_format_from_fourcc(uint32_t fourcc, uint64_t modifier) { /* Clean the modifier bits in the internal format. */ struct table_entry { uint64_t internal; // 不带 modifier_bits uint32_t fourcc; }; static table_entry table[] = { { MALI_GRALLOC_FORMAT_INTERNAL_RAW16, DRM_FORMAT_R16 }, { MALI_GRALLOC_FORMAT_INTERNAL_RGBA_8888, DRM_FORMAT_ABGR8888 }, { MALI_GRALLOC_FORMAT_INTERNAL_BGRA_8888, DRM_FORMAT_ARGB8888 }, { MALI_GRALLOC_FORMAT_INTERNAL_RGB_565, DRM_FORMAT_RGB565 }, { MALI_GRALLOC_FORMAT_INTERNAL_RGBX_8888, DRM_FORMAT_XBGR8888 }, { MALI_GRALLOC_FORMAT_INTERNAL_RGB_888, DRM_FORMAT_BGR888 }, { MALI_GRALLOC_FORMAT_INTERNAL_RGBA_1010102, DRM_FORMAT_ABGR2101010 }, { MALI_GRALLOC_FORMAT_INTERNAL_RGBA_16161616, DRM_FORMAT_ABGR16161616F }, { MALI_GRALLOC_FORMAT_INTERNAL_YV12, DRM_FORMAT_YVU420 }, { MALI_GRALLOC_FORMAT_INTERNAL_NV12, DRM_FORMAT_NV12 }, { MALI_GRALLOC_FORMAT_INTERNAL_NV16, DRM_FORMAT_NV16 }, { MALI_GRALLOC_FORMAT_INTERNAL_NV21, DRM_FORMAT_NV21 }, { MALI_GRALLOC_FORMAT_INTERNAL_Y0L2, DRM_FORMAT_Y0L2 }, { MALI_GRALLOC_FORMAT_INTERNAL_Y210, DRM_FORMAT_Y210 }, { MALI_GRALLOC_FORMAT_INTERNAL_P010, DRM_FORMAT_P010 }, { MALI_GRALLOC_FORMAT_INTERNAL_P210, DRM_FORMAT_P210 }, { MALI_GRALLOC_FORMAT_INTERNAL_Y410, DRM_FORMAT_Y410 }, { MALI_GRALLOC_FORMAT_INTERNAL_YUV422_8BIT, DRM_FORMAT_YUYV }, { MALI_GRALLOC_FORMAT_INTERNAL_YUV420_8BIT_I, DRM_FORMAT_YUV420_8BIT }, { MALI_GRALLOC_FORMAT_INTERNAL_YUV420_10BIT_I, DRM_FORMAT_YUV420_10BIT }, /* Deprecated legacy formats, mapped to MALI_GRALLOC_FORMAT_INTERNAL_YUV422_8BIT. */ { HAL_PIXEL_FORMAT_YCbCr_422_I, DRM_FORMAT_YUYV }, /* Deprecated legacy formats, mapped to MALI_GRALLOC_FORMAT_INTERNAL_NV21. */ { HAL_PIXEL_FORMAT_YCrCb_420_SP, DRM_FORMAT_NV21 }, /* Format introduced in Android P, mapped to MALI_GRALLOC_FORMAT_INTERNAL_P010. */ { HAL_PIXEL_FORMAT_YCBCR_P010, DRM_FORMAT_P010 }, }; for (size_t i = 0; i < sizeof(table) / sizeof(table[0]); i++) { if (table[i].fourcc == fourcc) { return table[i].internal; } } LOG_ALWAYS_FATAL("unexpected fourcc : 0x%x", fourcc); return 0; } android::status_t static decodeArmPlaneFds(const hidl_vec& input, std::vector* fds) { assert (fds != nullptr); int64_t size = 0; memcpy(&size, input.data(), sizeof(int64_t)); if (size < 0) { return android::BAD_VALUE; } fds->resize(size); const uint8_t *tmp = input.data() + sizeof(int64_t); memcpy(fds->data(), tmp, sizeof(int64_t) * size); return android::NO_ERROR; } /* --------------------------------------------------------------------------------------------------------- * Global Functions Implementation * --------------------------------------------------------------------------------------------------------- */ uint64_t get_internal_format(buffer_handle_t handle) { auto &mapper = get_service(); uint32_t fourcc; uint64_t modifier; int format_requested; /* 获取 format_fourcc. */ int err = get_metadata(mapper, handle, MetadataType_PixelFormatFourCC, decodePixelFormatFourCC, &fourcc); assert(err == android::NO_ERROR); // .trick : 目前的 gralloc 4.0 实现中, // 为 req_format HAL_PIXEL_FORMAT_YCrCb_NV12_10(rk_nv12_10) 分配的 buffer 的格式是 MALI_GRALLOC_FORMAT_INTERNAL_P010. // 预期 GPU 不应该且不会参与对这样的 buffer 的读写. // VPU 和 VOP 可处理这样的 buffer, 预期的格式仍旧是 rk_nv12_10, 且将从 width 获取 byte_stride. if ( DRM_FORMAT_P010 == fourcc ) { err = get_format_requested(handle, &format_requested); assert(err == android::NO_ERROR); if ( HAL_PIXEL_FORMAT_YCrCb_NV12_10 == format_requested ) { return HAL_PIXEL_FORMAT_YCrCb_NV12_10; } } /* 获取 format_modifier. */ err = get_metadata(mapper, handle, MetadataType_PixelFormatModifier, decodePixelFormatModifier, &modifier); assert(err == android::NO_ERROR); /* 从 fourcc 得到 internal_format. */ return (get_internal_format_from_fourcc(fourcc, modifier) ); } int get_pixel_format_modifier(buffer_handle_t handle, uint64_t* modifier) { auto &mapper = get_service(); int err = get_metadata(mapper, handle, MetadataType_PixelFormatModifier, decodePixelFormatModifier, modifier); if (err != android::OK) { ALOGE("err : %d", err); } return err; } bool does_use_afbc_format(buffer_handle_t handle) { uint64_t modifier; int err = get_pixel_format_modifier(handle, &modifier); if (err != android::OK) { ALOGE("err : %d", err); return false; } if ( AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 == (modifier & AFBC_FORMAT_MOD_BLOCK_SIZE_16x16) ) { D("buffer DOES uses AFBC format, modifier : 0x%" PRIx64, modifier); return true; } else { D("buffer does NOT use AFBC format, modifier : 0x%" PRIx64, modifier); return false; } } int get_width(buffer_handle_t handle, uint64_t* width) { auto &mapper = get_service(); int err = get_metadata(mapper, handle, MetadataType_Width, decodeWidth, width); if (err != android::OK) { ALOGE("err : %d", err); } return err; } int get_height(buffer_handle_t handle, uint64_t* height) { auto &mapper = get_service(); int err = get_metadata(mapper, handle, MetadataType_Height, decodeHeight, height); if (err != android::OK) { ALOGE("err : %d", err); } return err; } int get_pixel_stride(buffer_handle_t handle, int* pixel_stride) { auto &mapper = get_service(); std::vector layouts; int format_requested; int err = get_format_requested(handle, &format_requested); if (err != android::OK ) { ALOGE("err : %d", err); return err; } /* 若 'format_requested' "不是" HAL_PIXEL_FORMAT_YCrCb_NV12_10, 则 ... */ if ( format_requested != HAL_PIXEL_FORMAT_YCrCb_NV12_10 ) { err = get_metadata(mapper, handle, MetadataType_PlaneLayouts, decodePlaneLayouts, &layouts); if (err != android::OK || layouts.size() < 1) { ALOGE("Failed to get plane layouts. err : %d", err); return err; } if ( layouts.size() > 1 ) { V("it's not reasonable to get global pixel_stride of buffer with planes more than 1."); } if ( 0 == layouts[0].sampleIncrementInBits ) { ALOGE("sampleIncrementInBits is 0, unexpected."); return -1; } else { *pixel_stride = layouts[0].strideInBytes * 8 / layouts[0].sampleIncrementInBits; } } /* 否则, 即 'format_requested' "是" HAL_PIXEL_FORMAT_YCrCb_NV12_10, 则 ... */ else { uint64_t width; int byte_stride; err = get_width(handle, &width); if (err != android::OK ) { ALOGE("err : %d", err); return err; } // .trick : from CSY : 分配 rk_video_decoder 输出 buffers 时, 要求的 byte_stride of buffer in NV12_10, 已经通过 width 传入. // 原理上, NV12_10 的 pixel_stride 和 byte_stride 是不同的, 但是这里保留 之前 rk_drm_gralloc 的赋值方式. byte_stride = (int)width; *pixel_stride = byte_stride; } return err; } int get_byte_stride(buffer_handle_t handle, int* byte_stride) { auto &mapper = get_service(); std::vector layouts; int format_requested; int err = get_format_requested(handle, &format_requested); if (err != android::OK ) { ALOGE("err : %d", err); return err; } /* 若 'format_requested' "不是" HAL_PIXEL_FORMAT_YCrCb_NV12_10, 则 ... */ if ( format_requested != HAL_PIXEL_FORMAT_YCrCb_NV12_10 ) { err = get_metadata(mapper, handle, MetadataType_PlaneLayouts, decodePlaneLayouts, &layouts); if (err != android::OK || layouts.size() < 1) { ALOGE("Failed to get plane layouts. err : %d", err); return err; } if ( layouts.size() > 1 ) { V("it's not reasonable to get global byte_stride of buffer with planes more than 1."); } *byte_stride = (layouts[0].strideInBytes); } /* 否则, 即 'format_requested' "是" HAL_PIXEL_FORMAT_YCrCb_NV12_10, 则 ... */ else { uint64_t width; err = get_width(handle, &width); if (err != android::OK ) { ALOGE("err : %d", err); return err; } // .KP : from CSY : 分配 rk_video_decoder 输出 buffers 时, 要求的 byte_stride of buffer in NV12_10, 已经通过 width 传入. *byte_stride = (int)width; } return err; } int get_format_requested(buffer_handle_t handle, int* format_requested) { auto &mapper = get_service(); // android::PixelFormat format; // *format_requested PixelFormat format; // *format_requested int err = get_metadata(mapper, handle, MetadataType_PixelFormatRequested, decodePixelFormatRequested, &format); if (err != android::OK) { ALOGE("Failed to get pixel_format_requested. err : %d", err); return err; } *format_requested = (int)format; return err; } int get_usage(buffer_handle_t handle, uint64_t* usage) { auto &mapper = get_service(); int err = get_metadata(mapper, handle, MetadataType_Usage, decodeUsage, usage); if (err != android::OK) { ALOGE("Failed to get pixel_format_requested. err : %d", err); return err; } return err; } int get_allocation_size(buffer_handle_t handle, uint64_t* allocation_size) { auto &mapper = get_service(); int err = get_metadata(mapper, handle, MetadataType_AllocationSize, decodeAllocationSize, allocation_size); if (err != android::OK) { ALOGE("Failed to get allocation_size. err : %d", err); return err; } return err; } int get_share_fd(buffer_handle_t handle, int* share_fd) { auto &mapper = get_service(); std::vector fds; int err = get_metadata(mapper, handle, ArmMetadataType_PLANE_FDS, decodeArmPlaneFds, &fds); if (err != android::OK) { ALOGE("Failed to get plane_fds. err : %d", err); return err; } assert (fds.size() > 0); *share_fd = (int)(fds[0]); return err; } int get_name(buffer_handle_t handle, std::string &name) { auto &mapper = get_service(); int err = get_metadata(mapper, handle, MetadataType_Name, decodeName, &name); if (err != android::OK) { ALOGE("err : %d", err); } return err; } status_t importBuffer(buffer_handle_t rawHandle, buffer_handle_t* outHandle) { auto &mapper = get_service(); Error error; auto ret = mapper.importBuffer(android::hardware::hidl_handle(rawHandle), [&](const auto& tmpError, const auto& tmpBuffer) { error = tmpError; if (error != Error::NONE) { return; } *outHandle = static_cast(tmpBuffer); }); return static_cast((ret.isOk()) ? error : kTransactionError); } void freeBuffer(buffer_handle_t handle) { auto &mapper = get_service(); auto buffer = const_cast(handle); auto ret = mapper.freeBuffer(buffer); auto error = (ret.isOk()) ? static_cast(ret) : kTransactionError; } status_t lock(buffer_handle_t bufferHandle, uint64_t usage, int x, int y, int w, int h, void** outData) { auto &mapper = get_service(); auto buffer = const_cast(bufferHandle); IMapper::Rect accessRegion = {x, y, w, h}; android::hardware::hidl_handle acquireFenceHandle; // dummy Error error; auto ret = mapper.lock(buffer, usage, accessRegion, acquireFenceHandle, [&](const auto& tmpError, const auto& tmpData) { error = tmpError; if (error != Error::NONE) { return; } *outData = tmpData; }); error = (ret.isOk()) ? error : kTransactionError; ALOGW_IF(error != Error::NONE, "lock(%p, ...) failed: %d", bufferHandle, error); return static_cast(error); } void unlock(buffer_handle_t bufferHandle) { auto &mapper = get_service(); auto buffer = const_cast(bufferHandle); int releaseFence = -1; Error error; auto ret = mapper.unlock(buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) { error = tmpError; if (error != Error::NONE) { return; } auto fenceHandle = tmpReleaseFence.getNativeHandle(); // 预期 unlock() 不会返回有效的 release_fence. if (fenceHandle && fenceHandle->numFds == 1) { ALOGE("got unexpected valid fd of release_fence : %d", fenceHandle->data[0]); int fd = dup(fenceHandle->data[0]); if (fd >= 0) { releaseFence = fd; } else { ALOGD("failed to dup unlock release fence"); sync_wait(fenceHandle->data[0], -1); } } }); if (!ret.isOk()) { error = kTransactionError; } if (error != Error::NONE) { ALOGE("unlock(%p) failed with %d", buffer, error); } return; } } // namespace gralloc4