From afddb2218f6aff0f649e8b0458d02eff4e2a279d Mon Sep 17 00:00:00 2001 From: Jeevaka Prabu Badrappan Date: Mon, 19 Aug 2024 14:58:28 +0530 Subject: [PATCH] Changes to use IMapper5 stable-c mapper As IMapper4 is deprecated from Android15, changes done to use IMapper5 stable-c mapper. Tests done: - Android boot in GVT-d and BM config - adb reboot Tracked-On: OAM-124485 Signed-off-by: Jeevaka Prabu Badrappan --- android/Android.mk | 14 + meson.build | 6 +- src/util/u_gralloc/meson.build | 6 + src/util/u_gralloc/u_gralloc.c | 4 +- src/util/u_gralloc/u_gralloc_imapper5_api.cpp | 483 ++++++++++++++++++ src/util/u_gralloc/u_gralloc_internal.h | 2 +- 6 files changed, 511 insertions(+), 4 deletions(-) create mode 100644 src/util/u_gralloc/u_gralloc_imapper5_api.cpp diff --git a/android/Android.mk b/android/Android.mk index 339d7f25e73..864f893ba0f 100644 --- a/android/Android.mk +++ b/android/Android.mk @@ -118,6 +118,20 @@ LOCAL_SHARED_LIBRARIES += \ MESON_GEN_PKGCONFIGS += android.hardware.graphics.mapper:4.0 endif +ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 35; echo $$?), 0) +LOCAL_SHARED_LIBRARIES += \ + libbinder_ndk \ + libvndksupport \ + android.hardware.graphics.allocator-V2-ndk \ + +LOCAL_HEADER_LIBRARIES += \ + libimapper_stablec \ + libimapper_providerutils \ + libui_headers + +MESON_GEN_PKGCONFIGS += android.hardware.graphics.allocator-V2-ndk +endif + __MY_SHARED_LIBRARIES := $(LOCAL_SHARED_LIBRARIES) ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 30; echo $$?), 0) diff --git a/meson.build b/meson.build index de18e8272d0..1ded66f0f4a 100644 --- a/meson.build +++ b/meson.build @@ -888,6 +888,7 @@ endif if with_platform_android dep_android_mapper4 = null_dep + dep_android_mapper5 = null_dep if not with_android_stub dep_android = [ dependency('cutils'), @@ -900,9 +901,12 @@ if with_platform_android if get_option('platform-sdk-version') >= 26 dep_android += dependency('nativewindow') endif - if get_option('platform-sdk-version') >= 30 + if get_option('platform-sdk-version') >= 30 and get_option('platform-sdk-version') <= 34 dep_android_mapper4 = dependency('android.hardware.graphics.mapper', version : '>= 4.0', required : false) endif + if get_option('platform-sdk-version') >= 35 + dep_android_mapper5 = dependency('android.hardware.graphics.allocator-V2-ndk', required : false) + endif endif pre_args += [ '-DANDROID', diff --git a/src/util/u_gralloc/meson.build b/src/util/u_gralloc/meson.build index 913fc7c786d..e84458e7bd2 100644 --- a/src/util/u_gralloc/meson.build +++ b/src/util/u_gralloc/meson.build @@ -22,6 +22,12 @@ if dep_android_mapper4.found() cpp_args_for_u_gralloc += '-DUSE_IMAPPER4_METADATA_API' options_for_u_gralloc += 'cpp_std=c++17' endif +if dep_android_mapper5.found() + files_u_gralloc += files('u_gralloc_imapper5_api.cpp') + c_args_for_u_gralloc += '-DUSE_IMAPPER5_METADATA_API' + cpp_args_for_u_gralloc += '-DUSE_IMAPPER5_METADATA_API' + options_for_u_gralloc += 'cpp_std=c++17' +endif _libmesa_u_gralloc = static_library( '_mesa_u_gralloc', diff --git a/src/util/u_gralloc/u_gralloc.c b/src/util/u_gralloc/u_gralloc.c index b92057c515d..2aaba2034a0 100644 --- a/src/util/u_gralloc/u_gralloc.c +++ b/src/util/u_gralloc/u_gralloc.c @@ -25,9 +25,9 @@ static const struct u_grallocs { } u_grallocs[] = { /* Prefer the CrOS API as it is significantly faster than IMapper4 */ {.type = U_GRALLOC_TYPE_CROS, .create = u_gralloc_cros_api_create}, -#ifdef USE_IMAPPER4_METADATA_API +#if defined(USE_IMAPPER4_METADATA_API) || defined(USE_IMAPPER5_METADATA_API) {.type = U_GRALLOC_TYPE_GRALLOC4, .create = u_gralloc_imapper_api_create}, -#endif /* USE_IMAPPER4_METADATA_API */ +#endif /* USE_IMAPPER4_METADATA_API || USE_IMAPPER5_METADATA_API */ {.type = U_GRALLOC_TYPE_LIBDRM, .create = u_gralloc_libdrm_create}, {.type = U_GRALLOC_TYPE_QCOM, .create = u_gralloc_qcom_create}, {.type = U_GRALLOC_TYPE_FALLBACK, .create = u_gralloc_fallback_create}, diff --git a/src/util/u_gralloc/u_gralloc_imapper5_api.cpp b/src/util/u_gralloc/u_gralloc_imapper5_api.cpp new file mode 100644 index 00000000000..67b49916eec --- /dev/null +++ b/src/util/u_gralloc/u_gralloc_imapper5_api.cpp @@ -0,0 +1,483 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 2021 GlobalLogic Ukraine + * Copyright (C) 2021-2022 Roman Stratiienko (r.stratiienko@gmail.com) + * SPDX-License-Identifier: MIT + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "util/log.h" +#include "u_gralloc_internal.h" + +using namespace aidl::android::hardware::graphics::allocator; +using aidl::android::hardware::graphics::common::BufferUsage; +using aidl::android::hardware::graphics::common::StandardMetadataType; +using aidl::android::hardware::graphics::common::ChromaSiting; +using aidl::android::hardware::graphics::common::Dataspace; +using aidl::android::hardware::graphics::common::ExtendableType; +using aidl::android::hardware::graphics::common::PlaneLayout; +using aidl::android::hardware::graphics::common::PlaneLayoutComponent; +using aidl::android::hardware::graphics::common::PlaneLayoutComponentType; +using android::hardware::graphics::common::V1_2::PixelFormat; +using android::hardware::graphics::mapper::StandardMetadata; +using android::hardware::hidl_handle; + +static const auto kIAllocatorServiceName = IAllocator::descriptor + std::string("/default"); +static const auto kIAllocatorMinimumVersion = 2; + +typedef AIMapper_Error (*AIMapper_loadIMapperFn)(AIMapper *_Nullable *_Nonnull outImplementation); + +static std::shared_ptr waitForAllocator() { + if (__builtin_available(android 31, *)) { + if (!AServiceManager_isDeclared(kIAllocatorServiceName.c_str())) { + mesa_loge("AllocatorService not declared"); + return nullptr; + } + auto allocator = IAllocator::fromBinder( + ndk::SpAIBinder(AServiceManager_waitForService(kIAllocatorServiceName.c_str()))); + if (!allocator) { + mesa_loge("AIDL IAllocator declared but failed to get service"); + return nullptr; + } + + int32_t version = 0; + if (!allocator->getInterfaceVersion(&version).isOk()) { + mesa_loge("Failed to query interface version"); + return nullptr; + } + if (version < kIAllocatorMinimumVersion) { + mesa_loge("version is < kIAllocatorMinimumVersion"); + return nullptr; + } + return allocator; + } else { + mesa_loge("API level < 31"); + return nullptr; + } +} + +static void *loadIMapperLibrary() { + static void *imapperLibrary = []() -> void * { + auto allocator = waitForAllocator(); + if (allocator == nullptr) + return NULL; + + std::string mapperSuffix; + auto status = allocator->getIMapperLibrarySuffix(&mapperSuffix); + if (!status.isOk()) { + mesa_loge("Failed to get IMapper library suffix"); + return NULL; + } + std::string lib_name = "mapper." + mapperSuffix + ".so"; + mesa_logi("Loading mapper.%s.so", mapperSuffix.c_str()); + void *so = android_load_sphal_library(lib_name.c_str(), RTLD_LOCAL | RTLD_NOW); + if (!so) { + mesa_loge("Failed to load mapper.%s.so", mapperSuffix.c_str()); + } + return so; + }(); + return imapperLibrary; +} + +template +static auto getStandardMetadata(AIMapper *mapper, buffer_handle_t bufferHandle) + -> decltype(StandardMetadata::value::decode(NULL, 0)) { + using Value = typename StandardMetadata::value; + // TODO: Tune for common-case better + android::FatVector buffer; + int32_t sizeRequired = mapper->v5.getStandardMetadata(bufferHandle, + static_cast(T), + buffer.data(), buffer.size()); + if (sizeRequired < 0) { + ALOGW_IF(-AIMAPPER_ERROR_UNSUPPORTED != sizeRequired, + "Unexpected error %d from valid getStandardMetadata call", -sizeRequired); + return std::nullopt; + } + if ((size_t)sizeRequired > buffer.size()) { + buffer.resize(sizeRequired); + sizeRequired = mapper->v5.getStandardMetadata(bufferHandle, static_cast(T), + buffer.data(), buffer.size()); + } + if (sizeRequired < 0 || (size_t)sizeRequired > buffer.size()) { + mesa_logw("getStandardMetadata failed, received %d with buffer size %zd", sizeRequired, + buffer.size()); + // Generate a fail type + return std::nullopt; + } + return Value::decode(buffer.data(), sizeRequired); +} + +struct gralloc5 { + struct u_gralloc base; + AIMapper *mapper = NULL; +}; + +extern "C" { + +static buffer_handle_t import_buffer(struct u_gralloc *gralloc, const buffer_handle_t rawHandle) +{ + buffer_handle_t outBuffer = nullptr; + gralloc5 *gr = (gralloc5 *)gralloc; + + if (gr->mapper == nullptr) { + mesa_loge("mapper is null"); + } else { + AIMapper_Error error = gr->mapper->v5.importBuffer(hidl_handle(rawHandle), + &outBuffer); + if (error != AIMAPPER_ERROR_NONE) { + mesa_loge("importBuffer failed"); + } + } + + return outBuffer; +} + +static int free_buffer(struct u_gralloc *gralloc, const buffer_handle_t handle) +{ + gralloc5 *gr = (gralloc5 *)gralloc; + + if (gr->mapper == nullptr) { + mesa_loge("mapper is null"); + return -EINVAL; + } + + if (!handle) { + mesa_loge("buffer handle is null"); + return -EINVAL; + } + + AIMapper_Error error = gr->mapper->v5.freeBuffer(handle); + if (error != AIMAPPER_ERROR_NONE) { + mesa_loge("freeBuffer failed"); + return - EINVAL; + } + + return 0; +} + +static int +mapper_resolve_format(struct u_gralloc *gralloc, struct u_gralloc_buffer_handle *hnd, + int32_t *format) +{ + gralloc5 *gr = (gralloc5 *)gralloc; + int error = 0; + + if (gr->mapper == nullptr) { + mesa_loge("mapper is null"); + return -EINVAL; + } + + if (!hnd->handle) { + mesa_loge("buffer handle is null"); + return -EINVAL; + } + + auto importedHandle = import_buffer(gralloc, hnd->handle); + if (nullptr == importedHandle) { + mesa_loge("import_buffer failed"); + return -EINVAL; + } + + auto value = + getStandardMetadata(gr->mapper, + importedHandle); + if (!value.has_value()) { + mesa_loge("PIXEL_FORMAT_REQUESTED get failed"); + error = -EINVAL; + } else { + *format = static_cast>(*value); + } + + (void)free_buffer(gralloc, importedHandle); + return error; +} + +static int +mapper_get_buffer_basic_info(struct u_gralloc *gralloc, + struct u_gralloc_buffer_handle *hnd, + struct u_gralloc_buffer_basic_info *out) +{ + gralloc5 *gr = (gralloc5 *)gralloc; + int error = -EINVAL; + + if (gr->mapper == nullptr) { + mesa_loge("mapper is null"); + return -EINVAL; + } + + if (!hnd->handle) { + mesa_loge("buffer handle is null"); + return -EINVAL; + } + + auto importedHandle = import_buffer(gralloc, hnd->handle); + if (nullptr == importedHandle) { + mesa_loge("import_buffer failed"); + return -EINVAL; + } + + { + auto value = + getStandardMetadata(gr->mapper, + importedHandle); + if (!value.has_value()) { + mesa_loge("PIXEL_FORMAT_FOURCC get failed"); + goto out; + } + + out->drm_fourcc = *value; + } + + { + auto value = getStandardMetadata( + gr->mapper, + importedHandle); + if (!value.has_value()) { + mesa_loge("PIXEL_FORMAT_MODIFIER get failed"); + goto out; + } + + out->modifier = *value; + } + + { + auto layouts_opt = getStandardMetadata(gr->mapper, + importedHandle); + if (!(layouts_opt.has_value())) { + mesa_loge("PLANE_LAYOUTS get failed"); + goto out; + } else { + std::vector &layouts = *layouts_opt; + int fd_index = 0; + int droid_format = 0, resolve_format = 0; + enum chroma_order chroma_order = chroma_order::YCbCr; + int chroma_step = 0; + + out->num_planes = layouts.size(); + + + for (uint32_t i = 0; i < layouts.size(); i++) { + out->strides[i] = layouts[i].strideInBytes; + out->offsets[i] = layouts[i].offsetInBytes; + + /* offset == 0 means layer is located in different dma-buf */ + if (out->offsets[i] == 0 && i > 0) + fd_index++; + + if (fd_index >= hnd->handle->numFds) + goto out; + + out->fds[i] = hnd->handle->data[fd_index]; + } + + if (mapper_resolve_format(gralloc, hnd, &droid_format)) { + mesa_loge("mapper_resolve_format failed"); + goto out; + } + + if (is_hal_format_yuv(droid_format)) { + if (layouts[1].components[0].type == android::gralloc4::PlaneLayoutComponentType_CB) + chroma_order = chroma_order::YCbCr; + else + chroma_order = chroma_order::YCrCb; + + chroma_step = layouts[1].sampleIncrementInBits / 8; + resolve_format = get_fourcc_yuv(droid_format, chroma_order, chroma_step); + out->drm_fourcc = resolve_format; + + if (layouts.size() == 2) { + out->strides[2] = out->strides[1]; + out->offsets[2] = out->offsets[1] + (chroma_step/2); + } + } + } + } + + error = 0; +out: + (void)free_buffer(gralloc, importedHandle); + return error; +} + +static int +mapper_get_buffer_color_info(struct u_gralloc *gralloc, + struct u_gralloc_buffer_handle *hnd, + struct u_gralloc_buffer_color_info *out) +{ + gralloc5 *gr = (gralloc5 *)gralloc; + + if (gr->mapper == nullptr) { + mesa_loge("mapper is null"); + return -EINVAL; + } + + if (!hnd->handle) { + mesa_loge("buffer handle is null"); + return -EINVAL; + } + + int droid_format = 0; + + if (mapper_resolve_format(gralloc, hnd, &droid_format)) { + mesa_loge("mapper_resolve_format failed"); + return -EINVAL; + } + + if (is_hal_format_yuv(droid_format)) { + out->yuv_color_space = __DRI_YUV_COLOR_SPACE_ITU_REC601; + out->sample_range = __DRI_YUV_NARROW_RANGE; + out->horizontal_siting = __DRI_YUV_CHROMA_SITING_0; + out->vertical_siting = __DRI_YUV_CHROMA_SITING_0; + + return 0; + } + + auto importedHandle = import_buffer(gralloc, hnd->handle); + if (nullptr == importedHandle) { + mesa_loge("import_buffer failed"); + return -EINVAL; + } + + /* optional attributes */ + std::optional chroma_siting; + { + auto value = getStandardMetadata(gr->mapper, + importedHandle); + if (value.has_value()) { + ExtendableType chroma_siting_ext = *value; + + chroma_siting = + android::gralloc4::getStandardChromaSitingValue(chroma_siting_ext); + } + } + + { + auto value = getStandardMetadata(gr->mapper, + importedHandle); + if (value.has_value()) { + Dataspace dataspace = static_cast(*value); + + Dataspace standard = + (Dataspace)((int)dataspace & (uint32_t)Dataspace::STANDARD_MASK); + switch (standard) { + case Dataspace::STANDARD_BT709: + out->yuv_color_space = __DRI_YUV_COLOR_SPACE_ITU_REC709; + break; + case Dataspace::STANDARD_BT601_625: + case Dataspace::STANDARD_BT601_625_UNADJUSTED: + case Dataspace::STANDARD_BT601_525: + case Dataspace::STANDARD_BT601_525_UNADJUSTED: + out->yuv_color_space = __DRI_YUV_COLOR_SPACE_ITU_REC601; + break; + case Dataspace::STANDARD_BT2020: + case Dataspace::STANDARD_BT2020_CONSTANT_LUMINANCE: + out->yuv_color_space = __DRI_YUV_COLOR_SPACE_ITU_REC2020; + break; + default: + break; + } + + Dataspace range = + (Dataspace)((int)dataspace & (uint32_t)Dataspace::RANGE_MASK); + switch (range) { + case Dataspace::RANGE_FULL: + out->sample_range = __DRI_YUV_FULL_RANGE; + break; + case Dataspace::RANGE_LIMITED: + out->sample_range = __DRI_YUV_NARROW_RANGE; + break; + default: + break; + } + } + } + + if (chroma_siting) { + switch (*chroma_siting) { + case ChromaSiting::SITED_INTERSTITIAL: + out->horizontal_siting = __DRI_YUV_CHROMA_SITING_0_5; + out->vertical_siting = __DRI_YUV_CHROMA_SITING_0_5; + break; + case ChromaSiting::COSITED_HORIZONTAL: + out->horizontal_siting = __DRI_YUV_CHROMA_SITING_0; + out->vertical_siting = __DRI_YUV_CHROMA_SITING_0_5; + break; + default: + break; + } + } + + (void)free_buffer(gralloc, importedHandle); + return 0; +} + +static int +mapper_get_front_rendering_usage(struct u_gralloc *gralloc, + uint64_t *out_usage) +{ + assert(out_usage); +#if ANDROID_API_LEVEL >= 33 + *out_usage = static_cast(BufferUsage::FRONT_BUFFER); + + return 0; +#else + return -ENOTSUP; +#endif +} + +static int +destroy(struct u_gralloc *gralloc) +{ + gralloc5 *gr = (struct gralloc5 *)gralloc; + delete gr; + + return 0; +} + +struct u_gralloc * +u_gralloc_imapper_api_create() +{ + void *so = loadIMapperLibrary(); + if (!so) { + mesa_loge("loadIMapperLibrary failed"); + return NULL; + } + auto loadIMapper = (AIMapper_loadIMapperFn)dlsym(so, "AIMapper_loadIMapper"); + AIMapper *mapper = nullptr; + AIMapper_Error error = loadIMapper(&mapper); + if (error != AIMAPPER_ERROR_NONE) { + mesa_loge("AIMapper_loadIMapper failed %d", error); + return NULL; + } + + auto gr = new gralloc5; + gr->mapper = mapper; + gr->base.ops.get_buffer_basic_info = mapper_get_buffer_basic_info; + gr->base.ops.get_buffer_color_info = mapper_get_buffer_color_info; + gr->base.ops.get_front_rendering_usage = mapper_get_front_rendering_usage; + gr->base.ops.destroy = destroy; + + mesa_logi("Using IMapper5 API"); + + return &gr->base; +} + +} // extern "C" diff --git a/src/util/u_gralloc/u_gralloc_internal.h b/src/util/u_gralloc/u_gralloc_internal.h index e66ae7b8d43..3e9b0ac853b 100644 --- a/src/util/u_gralloc/u_gralloc_internal.h +++ b/src/util/u_gralloc/u_gralloc_internal.h @@ -37,7 +37,7 @@ struct u_gralloc { }; extern struct u_gralloc *u_gralloc_cros_api_create(void); -#ifdef USE_IMAPPER4_METADATA_API +#if defined(USE_IMAPPER4_METADATA_API) || defined(USE_IMAPPER5_METADATA_API) extern struct u_gralloc *u_gralloc_imapper_api_create(void); #endif extern struct u_gralloc *u_gralloc_qcom_create(void);