From f85d3113b2b73b351fc50b2089447787c7f9a731 Mon Sep 17 00:00:00 2001 From: Roman Stratiienko Date: Tue, 15 Dec 2020 16:50:19 +0200 Subject: [PATCH] egl: android: add IMapper@4 metadata API buffer_info getter Starting from Android-11 Google introduces generalized API to access buffer information. This API is a part of IMapper@4 HAL. Signed-off-by: Roman Stratiienko Reviewed-by: Yiwei Zhang Part-of: --- android/Android.mk | 10 + meson.build | 4 + src/egl/drivers/dri2/platform_android.c | 16 +- src/egl/drivers/dri2/platform_android.h | 40 +++- .../drivers/dri2/platform_android_mapper.cpp | 211 ++++++++++++++++++ src/egl/meson.build | 7 + 6 files changed, 274 insertions(+), 14 deletions(-) create mode 100644 src/egl/drivers/dri2/platform_android_mapper.cpp diff --git a/android/Android.mk b/android/Android.mk index d5d2c68272f..243da8493af 100644 --- a/android/Android.mk +++ b/android/Android.mk @@ -78,6 +78,16 @@ MESON_LLVM_IRBUILDER_PATH := external/llvm-project/llvm/include/llvm/IR/IRBuilde LOCAL_SHARED_LIBRARIES += libLLVM11 endif +ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 30; echo $$?), 0) +LOCAL_SHARED_LIBRARIES += \ + android.hardware.graphics.mapper@4.0 \ + libgralloctypes \ + libhidlbase \ + libutils + +MESON_GEN_PKGCONFIGS += android.hardware.graphics.mapper:4.0 +endif + ifeq ($(TARGET_IS_64_BIT),true) LOCAL_MULTILIB := 64 else diff --git a/meson.build b/meson.build index 8d74b96a27b..74dc4ad0743 100644 --- a/meson.build +++ b/meson.build @@ -899,6 +899,7 @@ if with_android_stub and not with_platform_android endif if with_platform_android + dep_android_mapper4 = null_dep if not with_android_stub dep_android = [ dependency('cutils'), @@ -909,6 +910,9 @@ if with_platform_android if get_option('platform-sdk-version') >= 26 dep_android += dependency('nativewindow') endif + if get_option('platform-sdk-version') >= 30 + dep_android_mapper4 = dependency('android.hardware.graphics.mapper', version : '>= 4.0', required : false) + endif endif pre_args += [ '-DHAVE_ANDROID_PLATFORM', diff --git a/src/egl/drivers/dri2/platform_android.c b/src/egl/drivers/dri2/platform_android.c index 988e0a3c181..d211fd5aa40 100644 --- a/src/egl/drivers/dri2/platform_android.c +++ b/src/egl/drivers/dri2/platform_android.c @@ -187,19 +187,6 @@ get_native_buffer_name(struct ANativeWindowBuffer *buf) } #endif /* HAVE_DRM_GRALLOC */ -struct buffer_info { - uint32_t drm_fourcc; - int num_planes; - int fds[4]; - uint64_t modifier; - int offsets[4]; - int pitches[4]; - enum __DRIYUVColorSpace yuv_color_space; - enum __DRISampleRange sample_range; - enum __DRIChromaSiting horizontal_siting; - enum __DRIChromaSiting vertical_siting; -}; - static int get_yuv_buffer_info(_EGLDisplay *disp, struct ANativeWindowBuffer *buf, @@ -404,6 +391,9 @@ droid_create_image_from_native_buffer(_EGLDisplay *disp, unsigned error; do { + if (!mapper_metadata_get_buffer_info(buf, &buf_info)) + break; + if (!cros_get_buffer_info(disp, buf, &buf_info)) break; diff --git a/src/egl/drivers/dri2/platform_android.h b/src/egl/drivers/dri2/platform_android.h index fc72013510d..2bcf56fe90f 100644 --- a/src/egl/drivers/dri2/platform_android.h +++ b/src/egl/drivers/dri2/platform_android.h @@ -1,5 +1,6 @@ /* * Copyright © 2021, Google Inc. + * Copyright (C) 2021, GlobalLogic Ukraine * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,6 +25,12 @@ #ifndef EGL_ANDROID_INCLUDED #define EGL_ANDROID_INCLUDED +#include +#include +#include + +#include + #include "egl_dri2.h" #if ANDROID_API_LEVEL < 26 @@ -112,6 +119,37 @@ ANativeWindow_query(const struct ANativeWindow *window, } return window->query(window, (int)what, value); } -#endif +#endif // ANDROID_API_LEVEL < 26 +struct buffer_info { + uint32_t drm_fourcc; + int num_planes; + int fds[4]; + uint64_t modifier; + int offsets[4]; + int pitches[4]; + enum __DRIYUVColorSpace yuv_color_space; + enum __DRISampleRange sample_range; + enum __DRIChromaSiting horizontal_siting; + enum __DRIChromaSiting vertical_siting; +}; + +#ifdef USE_IMAPPER4_METADATA_API +#ifdef __cplusplus +extern "C" { #endif +extern int +mapper_metadata_get_buffer_info(struct ANativeWindowBuffer *buf, + struct buffer_info *out_buf_info); +#ifdef __cplusplus +} +#endif +#else +static inline int +mapper_metadata_get_buffer_info(struct ANativeWindowBuffer *buf, + struct buffer_info *out_buf_info) { + return -ENOTSUP; +} +#endif /* USE_IMAPPER4_METADATA_API */ + +#endif /* EGL_ANDROID_INCLUDED */ diff --git a/src/egl/drivers/dri2/platform_android_mapper.cpp b/src/egl/drivers/dri2/platform_android_mapper.cpp new file mode 100644 index 00000000000..8c3496c2bbb --- /dev/null +++ b/src/egl/drivers/dri2/platform_android_mapper.cpp @@ -0,0 +1,211 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 2021 GlobalLogic Ukraine + * Copyright (C) 2021 Roman Stratiienko (r.stratiienko@gmail.com) + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "platform_android.h" + +#include +#include +#include +#include +#include +#include +#include + +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::BufferUsage; +using android::hardware::graphics::mapper::V4_0::Error; +using android::hardware::graphics::mapper::V4_0::IMapper; +using android::hardware::hidl_handle; +using android::hardware::hidl_vec; +using MetadataType = + android::hardware::graphics::mapper::V4_0::IMapper::MetadataType; + +Error +GetMetadata(android::sp mapper, const native_handle_t *buffer, + MetadataType type, hidl_vec* metadata) +{ + Error error = Error::NONE; + + auto native_handle = const_cast(buffer); + + auto ret = mapper->get(native_handle, type, + [&](const auto& get_error, const auto& get_metadata) { + error = get_error; + *metadata = get_metadata; + }); + + if (!ret.isOk()) + error = Error::NO_RESOURCES; + + return error; +} + +std::optional> GetPlaneLayouts( + android::sp mapper, const native_handle_t *buffer) +{ + hidl_vec encoded_layouts; + + Error error = GetMetadata(mapper, buffer, + android::gralloc4::MetadataType_PlaneLayouts, + &encoded_layouts); + + if (error != Error::NONE) + return std::nullopt; + + std::vector plane_layouts; + + auto status = android::gralloc4::decodePlaneLayouts(encoded_layouts, &plane_layouts); + + if (status != android::OK) + return std::nullopt; + + return plane_layouts; +} + +extern "C" +{ + +int +mapper_metadata_get_buffer_info(struct ANativeWindowBuffer *buf, + struct buffer_info *out_buf_info) +{ + static android::sp mapper = IMapper::getService(); + struct buffer_info buf_info = *out_buf_info; + if (mapper == nullptr) + return -EINVAL; + + if (!buf->handle) + return -EINVAL; + + hidl_vec encoded_format; + auto err = GetMetadata(mapper, buf->handle, android::gralloc4::MetadataType_PixelFormatFourCC, &encoded_format); + if (err != Error::NONE) + return -EINVAL; + + auto status = android::gralloc4::decodePixelFormatFourCC(encoded_format, &buf_info.drm_fourcc); + if (status != android::OK) + return -EINVAL; + + hidl_vec encoded_modifier; + err = GetMetadata(mapper, buf->handle, android::gralloc4::MetadataType_PixelFormatModifier, &encoded_modifier); + if (err != Error::NONE) + return -EINVAL; + + status = android::gralloc4::decodePixelFormatModifier(encoded_modifier, &buf_info.modifier); + if (status != android::OK) + return -EINVAL; + + auto layouts_opt = GetPlaneLayouts(mapper, buf->handle); + + if (!layouts_opt) + return -EINVAL; + + std::vector& layouts = *layouts_opt; + + buf_info.num_planes = layouts.size(); + + bool per_plane_unique_fd = buf->handle->numFds == buf_info.num_planes; + + for (uint32_t i = 0; i < layouts.size(); i++) { + buf_info.fds[i] = per_plane_unique_fd ? buf->handle->data[i] : buf->handle->data[0]; + buf_info.pitches[i] = layouts[i].strideInBytes; + buf_info.offsets[i] = layouts[i].offsetInBytes; + } + + /* optional attributes */ + hidl_vec encoded_chroma_siting; + err = GetMetadata(mapper, buf->handle, android::gralloc4::MetadataType_ChromaSiting, &encoded_chroma_siting); + if (err == Error::NONE) { + ExtendableType chroma_siting_ext; + status = android::gralloc4::decodeChromaSiting(encoded_chroma_siting, &chroma_siting_ext); + if (status != android::OK) + return -EINVAL; + + ChromaSiting chroma_siting = android::gralloc4::getStandardChromaSitingValue(chroma_siting_ext); + switch (chroma_siting) { + case ChromaSiting::SITED_INTERSTITIAL: + buf_info.horizontal_siting = __DRI_YUV_CHROMA_SITING_0_5; + buf_info.vertical_siting = __DRI_YUV_CHROMA_SITING_0_5; + break; + case ChromaSiting::COSITED_HORIZONTAL: + buf_info.horizontal_siting = __DRI_YUV_CHROMA_SITING_0; + buf_info.vertical_siting = __DRI_YUV_CHROMA_SITING_0_5; + break; + default: + break; + } + } + + hidl_vec encoded_dataspace; + err = GetMetadata(mapper, buf->handle, android::gralloc4:: MetadataType_Dataspace, &encoded_dataspace); + if (err == Error::NONE) { + Dataspace dataspace; + status = android::gralloc4::decodeDataspace(encoded_dataspace, &dataspace); + if (status != android::OK) + return -EINVAL; + + Dataspace standard = (Dataspace)((int)dataspace & (uint32_t)Dataspace::STANDARD_MASK); + switch (standard) { + case Dataspace::STANDARD_BT709: + buf_info.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: + buf_info.yuv_color_space = __DRI_YUV_COLOR_SPACE_ITU_REC601; + break; + case Dataspace::STANDARD_BT2020: + case Dataspace::STANDARD_BT2020_CONSTANT_LUMINANCE: + buf_info.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: + buf_info.sample_range = __DRI_YUV_FULL_RANGE; + break; + case Dataspace::RANGE_LIMITED: + buf_info.sample_range = __DRI_YUV_NARROW_RANGE; + break; + default: + break; + } + } + + *out_buf_info = buf_info; + + return 0; +} + +} // extern "C" diff --git a/src/egl/meson.build b/src/egl/meson.build index 055cfcf75fb..ab8f4e1fdbe 100644 --- a/src/egl/meson.build +++ b/src/egl/meson.build @@ -22,6 +22,7 @@ inc_egl = include_directories('.', 'main') inc_egl_dri2 = include_directories('drivers/dri2') c_args_for_egl = [asan_c_args] +cpp_args_for_egl = [] link_for_egl = [] deps_for_egl = [] incs_for_egl = [inc_include, inc_src, inc_egl] @@ -125,6 +126,11 @@ if with_dri2 if with_platform_android deps_for_egl += dep_android files_egl += files('drivers/dri2/platform_android.c') + if dep_android_mapper4.found() + files_egl += files('drivers/dri2/platform_android_mapper.cpp') + c_args_for_egl += '-DUSE_IMAPPER4_METADATA_API' + cpp_args_for_egl += ['-std=c++17', '-DUSE_IMAPPER4_METADATA_API'] + endif endif elif with_platform_haiku incs_for_egl += inc_haikugl @@ -167,6 +173,7 @@ libegl = shared_library( c_args_for_egl, '-D_EGL_NATIVE_PLATFORM=_EGL_PLATFORM_@0@'.format(egl_native_platform.to_upper()), ], + cpp_args : [cpp_args_for_egl], gnu_symbol_visibility : 'hidden', include_directories : incs_for_egl, link_with : [link_for_egl, libglapi],