diff --git a/bundle.json b/bundle.json index 8bf6132633b76763a9b5413c180205e37eecbe6f..bb80e19446bd71a5132719119902d130f7a96ee0 100644 --- a/bundle.json +++ b/bundle.json @@ -36,7 +36,6 @@ "libexif", "qos_manager", "video_processing_engine", - "media_foundation", "skia" ], "third_party": [ diff --git a/frameworks/native/BUILD.gn b/frameworks/native/BUILD.gn index b545dacaed46d51bd308c08c6a185f2edb4b7fa5..aa42ec8ac98c140a5e653894111dd97ecbdced4a 100644 --- a/frameworks/native/BUILD.gn +++ b/frameworks/native/BUILD.gn @@ -111,6 +111,7 @@ ohos_shared_library("image_effect_impl") { "$image_effect_root_dir/frameworks/native/utils/common/effect_json_helper.cpp", "$image_effect_root_dir/frameworks/native/utils/common/memcpy_helper.cpp", "$image_effect_root_dir/frameworks/native/utils/common/string_helper.cpp", + "$image_effect_root_dir/frameworks/native/utils/common/any.cpp", "$image_effect_root_dir/frameworks/native/utils/dfx/error_code.cpp", "$image_effect_root_dir/frameworks/native/utils/dfx/event_report.cpp", "$image_effect_root_dir/frameworks/native/utils/format/format_helper.cpp", @@ -137,7 +138,6 @@ ohos_shared_library("image_effect_impl") { "libexif:libexif", "napi:ace_napi", "qos_manager:qos", - "media_foundation:media_foundation", "skia:skia_canvaskit", ] @@ -185,6 +185,7 @@ ohos_shared_library("image_effect") { "$image_effect_root_dir/frameworks/native/capi/image_effect.cpp", "$image_effect_root_dir/frameworks/native/capi/image_effect_filter.cpp", "$image_effect_root_dir/frameworks/native/capi/native_common_utils.cpp", + "$image_effect_root_dir/frameworks/native/utils/common/any.cpp", ] use_exceptions = true @@ -201,7 +202,6 @@ ohos_shared_library("image_effect") { "image_framework:picture", "image_framework:pixelmap", "napi:ace_napi", - "media_foundation:media_foundation", ] cflags_cc = [ diff --git a/frameworks/native/effect/base/effect_surface_adapter.cpp b/frameworks/native/effect/base/effect_surface_adapter.cpp index 007e829c96583fb65b353c1f4fe352036a76c09a..591216674f2eac5382a6f5e1eac07813ba514b00 100644 --- a/frameworks/native/effect/base/effect_surface_adapter.cpp +++ b/frameworks/native/effect/base/effect_surface_adapter.cpp @@ -33,13 +33,7 @@ EffectSurfaceAdapter::EffectSurfaceAdapter() EffectSurfaceAdapter::~EffectSurfaceAdapter() { - if (receiverConsumerSurface_) { - GSError result = receiverConsumerSurface_->UnregisterConsumerListener(); - EFFECT_LOGI("EffectSurfaceAdapter::~EffectSurfaceAdapter UnregisterConsumerListener. result=%{public}d", - result); - effectSurfaceFlag_ = DESTRUCTOR_EFFECT_SURFACE_CONSTANT; - receiverConsumerSurface_ = nullptr; - } + Destroy(); } ErrorCode EffectSurfaceAdapter::Initialize() @@ -63,9 +57,6 @@ ErrorCode EffectSurfaceAdapter::Initialize() return ErrorCode::ERR_IMAGE_EFFECT_RECEIVER_INIT_FAILED; } - // register consumer listener - receiverConsumerSurface_->RegisterConsumerListener(this); - auto surfaceUtils = SurfaceUtils::GetInstance(); auto ret = surfaceUtils->Add(fromProducerSurface_->GetUniqueId(), fromProducerSurface_); if (ret != SurfaceError::SURFACE_ERROR_OK) { @@ -80,35 +71,33 @@ ErrorCode EffectSurfaceAdapter::Initialize() sptr EffectSurfaceAdapter::GetProducerSurface() { - if (fromProducerSurface_) { - return fromProducerSurface_; - } + CHECK_AND_RETURN_RET_LOG(!fromProducerSurface_, fromProducerSurface_, + "EffectSurfaceAdapter::GetProducerSurface producerSurface exists."); - if (Initialize() != ErrorCode::SUCCESS) { - return nullptr; - } + auto ret = Initialize(); + CHECK_AND_RETURN_RET_LOG(ret == ErrorCode::SUCCESS, nullptr, + "EffectSurfaceAdapter::GetProducerSurface Initialize failed."); return fromProducerSurface_; } -bool EffectSurfaceAdapter::CheckEffectSurface() const -{ - return effectSurfaceFlag_ == STRUCT_EFFECT_SURFACE_CONSTANT; -} - sptr EffectSurfaceAdapter::GetConsumerSurface() { - if (receiverConsumerSurface_) { - return receiverConsumerSurface_; - } + CHECK_AND_RETURN_RET_LOG(!receiverConsumerSurface_, receiverConsumerSurface_, + "EffectSurfaceAdapter::GetConsumerSurface consumerSurface exists."); - if (Initialize() != ErrorCode::SUCCESS) { - return nullptr; - } + auto ret = Initialize(); + CHECK_AND_RETURN_RET_LOG(ret == ErrorCode::SUCCESS, nullptr, + "EffectSurfaceAdapter::GetConsumerSurface Initialize failed."); return receiverConsumerSurface_; } +bool EffectSurfaceAdapter::CheckEffectSurface() const +{ + return effectSurfaceFlag_ == STRUCT_EFFECT_SURFACE_CONSTANT; +} + GSError EffectSurfaceAdapter::AcquireConsumerSurfaceBuffer(sptr& buffer, sptr& syncFence, int64_t& timestamp, OHOS::Rect& damages) const { @@ -191,6 +180,17 @@ void EffectSurfaceAdapter::OnCleanCache(uint32_t* bufSeqNum) { (void)bufSeqNum; } + +void EffectSurfaceAdapter::Destroy() +{ + if (receiverConsumerSurface_) { + GSError result = receiverConsumerSurface_->UnregisterConsumerListener(); + EFFECT_LOGI("EffectSurfaceAdapter::Destroy UnregisterConsumerListener. result=%{public}d", + result); + effectSurfaceFlag_ = DESTRUCTOR_EFFECT_SURFACE_CONSTANT; + receiverConsumerSurface_ = nullptr; + } +} } } } \ No newline at end of file diff --git a/frameworks/native/effect/base/effect_surface_adapter.h b/frameworks/native/effect/base/effect_surface_adapter.h index c16dd64a0d528cbc5f13c37c07882fc82486d418..d9100f11a251d8098f723ffcc54c441140df43ad 100644 --- a/frameworks/native/effect/base/effect_surface_adapter.h +++ b/frameworks/native/effect/base/effect_surface_adapter.h @@ -32,7 +32,7 @@ using ConsumerBufferAvailable = std::function; /** * Adapter class for image effect surface operation. */ -class EffectSurfaceAdapter : public IBufferConsumerListenerClazz { +class EffectSurfaceAdapter : public IBufferConsumerListener { public: IMAGE_EFFECT_EXPORT EffectSurfaceAdapter(); IMAGE_EFFECT_EXPORT ~EffectSurfaceAdapter(); @@ -43,6 +43,12 @@ public: */ IMAGE_EFFECT_EXPORT sptr GetProducerSurface(); + /** + * Retrieves the receiver surface. + * @return Smart pointer to the receiver surface. + */ + IMAGE_EFFECT_EXPORT sptr GetReceiverSurface(); + /** * Checks if the effect surface is valid. * @return True if valid, false otherwise. @@ -137,6 +143,11 @@ public: void OnCleanCache(uint32_t* bufSeqNum) override; // Implementation of IBufferConsumerListener interface end + /** + * Deconstructor. + */ + void Destroy(); + private: /** * Initializes the EffectSurfaceAdapter. diff --git a/frameworks/native/effect/base/image_effect_inner.cpp b/frameworks/native/effect/base/image_effect_inner.cpp index 469f5b0c3c84c3dc78b7181839812f2a6781dee7..e64242677b8587eda7de801685d6292614ea05e7 100644 --- a/frameworks/native/effect/base/image_effect_inner.cpp +++ b/frameworks/native/effect/base/image_effect_inner.cpp @@ -83,7 +83,7 @@ private: void InitEffectContext(); public: - std::unique_ptr surfaceAdapter_; + sptr surfaceAdapter_; std::shared_ptr pipeline_; std::shared_ptr srcFilter_; std::shared_ptr sinkFilter_; @@ -242,7 +242,9 @@ ImageEffect::~ImageEffect() EFFECT_LOGE("ImageEffect::SwapBuffers attach fail %{public}d times", failureCount_); } imageEffectFlag_ = DESTRUCTOR_IMAGE_EFFECT_CONSTANT; - impl_->surfaceAdapter_ = nullptr; + if (impl_->surfaceAdapter_) { + impl_->surfaceAdapter_->Destroy(); + } m_renderThread->ClearTask(); auto task = std::make_shared>([this]() { this->DestroyEGLEnv(); }, COMMON_TASK_TAG, RequestTaskId()); @@ -1019,7 +1021,7 @@ ErrorCode ImageEffect::SetOutputSurface(sptr& surface) toProducerSurface_ = surface; if (impl_->surfaceAdapter_ == nullptr) { - impl_->surfaceAdapter_ = std::make_unique(); + impl_->surfaceAdapter_ = sptr::MakeSptr(); } impl_->surfaceAdapter_->SetOutputSurfaceDefaultUsage(toProducerSurface_->GetDefaultUsage()); @@ -1280,6 +1282,7 @@ void ImageEffect::ProcessSwapBuffers(BufferProcessInfo& bufferProcessInfo, int64 EFFECT_LOGD("ProcessSwapBuffers: inBuffer: %{public}d, outBuffer: %{public}d", inBuffer->GetSeqNum(), outBuffer->GetSeqNum()); + CHECK_AND_RETURN_LOG(impl_, "ProcessSwapBuffers: impl_ is nullptr"); ret = impl_->DetachConsumerSurfaceBuffer(inBuffer); if (ret != GSError::GSERROR_OK) { EFFECT_LOGE("ProcessSwapBuffers: DetachConsumerSurfaceBuffer failed. %{public}d", ret); @@ -1381,7 +1384,7 @@ sptr ImageEffect::GetInputSurface() } if (impl_->surfaceAdapter_ == nullptr) { - impl_->surfaceAdapter_ = std::make_unique(); + impl_->surfaceAdapter_ = sptr::MakeSptr(); } if (impl_->surfaceAdapter_) { @@ -1394,6 +1397,10 @@ sptr ImageEffect::GetInputSurface() if (impl_->surfaceAdapter_) { impl_->surfaceAdapter_->SetConsumerListener(std::move(consumerListener)); + // register consumer listener + auto receiverConsumerSurface = impl_->surfaceAdapter_->GetConsumerSurface(); + sptr listener = impl_->surfaceAdapter_; + receiverConsumerSurface->RegisterConsumerListener(listener); } auto consumerSurface = impl_->GetConsumerSurface(); @@ -1418,7 +1425,7 @@ ErrorCode ImageEffect::SetOutNativeWindow(OHNativeWindow *nativeWindow) outDateInfo_.dataType_ = DataType::NATIVE_WINDOW; impl_->effectContext_->renderEnvironment_->InitEngine(nativeWindow); if (impl_->surfaceAdapter_ == nullptr) { - impl_->surfaceAdapter_ = std::make_unique(); + impl_->surfaceAdapter_ = sptr::MakeSptr(); } impl_->surfaceAdapter_->SetOutputSurfaceDefaultUsage(toProducerSurface_->GetDefaultUsage()); diff --git a/frameworks/native/utils/common/any.cpp b/frameworks/native/utils/common/any.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ca9ce8fbb78020e640b90f5b2b277572fd15a12c --- /dev/null +++ b/frameworks/native/utils/common/any.cpp @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * 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. + */ + +#include "any.h" +#include + +namespace { +using namespace OHOS::Media; +using BaseTypesMap = std::map; + +const BaseTypesMap &GetBaseTypesMap() +{ + static const BaseTypesMap baseTypeMap([]() { + BaseTypesMap typeMap; + Any defaultBool = (bool)true; + typeMap[std::string(defaultBool.TypeName())] = AnyValueType::BOOL; + Any defaultInt32 = (int32_t)0; + typeMap[std::string(defaultInt32.TypeName())] = AnyValueType::INT32_T; + Any defaultInt64 = (int64_t)0; + typeMap[std::string(defaultInt64.TypeName())] = AnyValueType::INT64_T; + Any defaultFoalt = (float)0.0; + typeMap[std::string(defaultFoalt.TypeName())] = AnyValueType::FLOAT; + Any defaultDouble = (double)0.0; + typeMap[std::string(defaultDouble.TypeName())] = AnyValueType::DOUBLE; + Any defaultString = std::string(); + typeMap[std::string(defaultString.TypeName())] = AnyValueType::STRING; + Any defaultVecUint8 = std::vector(); + typeMap[std::string(defaultVecUint8.TypeName())] = AnyValueType::VECTOR_UINT8; + Any defaultVecInt32 = std::vector(); + typeMap[std::string(defaultVecInt32.TypeName())] = AnyValueType::VECTOR_INT32; + return typeMap; + }()); + return baseTypeMap; +} +} // namespace + +namespace OHOS { +namespace Media { +bool Any::BaseTypesToParcel(const Any *operand, MessageParcel &parcel) noexcept +{ + auto iter = GetBaseTypesMap().find(std::string(operand->TypeName())); + if (iter == GetBaseTypesMap().end()) { + parcel.WriteInt32(static_cast(AnyValueType::INVALID_TYPE)); + return false; + } + bool ret = parcel.WriteInt32(static_cast(iter->second)); + switch (iter->second) { + case AnyValueType::BOOL: + ret = ret && parcel.WriteBool(*AnyCast(operand)); + break; + case AnyValueType::INT32_T: + ret = ret && parcel.WriteInt32(*AnyCast(operand)); + break; + case AnyValueType::INT64_T: + ret = ret && parcel.WriteInt64(*AnyCast(operand)); + break; + case AnyValueType::FLOAT: + ret = ret && parcel.WriteFloat(*AnyCast(operand)); + break; + case AnyValueType::DOUBLE: + ret = ret && parcel.WriteDouble(*AnyCast(operand)); + break; + case AnyValueType::STRING: + ret = ret && parcel.WriteString(*AnyCast(operand)); + break; + case AnyValueType::VECTOR_UINT8: + ret = ret && parcel.WriteUInt8Vector(*AnyCast>(operand)); + break; + case AnyValueType::VECTOR_INT32: + ret = ret && parcel.WriteInt32Vector(*AnyCast>(operand)); + break; + default: { + parcel.WriteInt32(static_cast(AnyValueType::INVALID_TYPE)); + return false; + } + } + return ret; +} + +enum class StatusCodeFromParcel { + SUCCESS = 0, + ENUM_RETRY = 1, + NO_RETRY = 2, +}; + +static void BaseTypesVectorUint8(Any *operand, MessageParcel &parcel) +{ + std::vector val; + (void)parcel.ReadUInt8Vector(&val); + Any tmp(val); + operand->Swap(tmp); +} + +static void BaseTypesVectorInt32(Any *operand, MessageParcel &parcel) +{ + std::vector val; + (void)parcel.ReadInt32Vector(&val); + Any tmp(val); + operand->Swap(tmp); +} + +// returnValue : 0 -- success; 1 -- retry for enum type; 2 -- failed no retry +int Any::BaseTypesFromParcel(Any *operand, MessageParcel &parcel) noexcept +{ + AnyValueType type = static_cast(parcel.ReadInt32()); + switch (type) { + case AnyValueType::BOOL: { + Any tmp(parcel.ReadBool()); + operand->Swap(tmp); + break; + } + case AnyValueType::INT32_T: { + Any tmp(parcel.ReadInt32()); + operand->Swap(tmp); + break; + } + case AnyValueType::INT64_T: { + Any tmp(parcel.ReadInt64()); + operand->Swap(tmp); + break; + } + case AnyValueType::FLOAT: { + Any tmp(parcel.ReadFloat()); + operand->Swap(tmp); + break; + } + case AnyValueType::DOUBLE: { + Any tmp(parcel.ReadDouble()); + operand->Swap(tmp); + break; + } + case AnyValueType::STRING: { + Any tmp(parcel.ReadString()); + operand->Swap(tmp); + break; + } + case AnyValueType::VECTOR_UINT8: { + BaseTypesVectorUint8(operand, parcel); + break; + } + case AnyValueType::VECTOR_INT32: { + BaseTypesVectorInt32(operand, parcel); + break; + } + case AnyValueType::INVALID_TYPE: + return static_cast(StatusCodeFromParcel::ENUM_RETRY); + default: + return static_cast(StatusCodeFromParcel::NO_RETRY); + } + return static_cast(StatusCodeFromParcel::SUCCESS); +} + +/** + * Get TypeName From function info. + * Extract the Type name out of Function Info + * @param functionInfo Function Info + * @return Name of Type T ,Such as bool int float double std::vector etc. + * @example In windows with MEDIA_NO_OHOS define, + * FunctionInfo will be like
+ * static constexpr std::string_view OHOS::Media::Any::GetTypeName() + * [with T = bool; std::string_view = std::basic_string_view]
+ * with MEDIA_OHOS define, FunctionInfo will be like
+ * static std::string_view OHOS::Media::Any::GetTypeName() [T = std::vector]
+ * For EnumType , FunctionInfo will be like
+ * static std::string_view OHOS::Media::Any::GetTypeName() [T = OHOS::Media::Plugins::VideoEncodeBitrateMode] + */ +std::string_view Any::GetTypeNameFromFunctionInfo(const char* functionInfo) noexcept +{ + std::string_view stringInfo = functionInfo; + std::string_view retType = "Unknown"; + size_t beginIndex = stringInfo.find_first_of('='); + if (beginIndex == std::string::npos) { + return retType; + } else { + beginIndex += 2; // 2 表示右移两位 + } +#ifdef MEDIA_OHOS + size_t endIndex = stringInfo.find_last_of(']'); +#else + size_t endIndex = stringInfo.find_last_of(';'); +#endif + std::string_view typeNameRet(functionInfo + beginIndex, endIndex - beginIndex); + return typeNameRet; +} +} // namespace Media +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/inner_api/native/common/any.h b/interfaces/inner_api/native/common/any.h index 3e98166affcfce3c8e53544b1751aa38dfb1d8f8..80e8cbd86839b26719c9d0af6d936df7160b65da 100644 --- a/interfaces/inner_api/native/common/any.h +++ b/interfaces/inner_api/native/common/any.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2025 Huawei Device Co., Ltd. * 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 @@ -13,9 +13,942 @@ * limitations under the License. */ -#ifndef IMAGE_EFFECT_ANY_H -#define IMAGE_EFFECT_ANY_H +#ifndef HISTREAMER_PLUGIN_COMMON_ANY_H +#define HISTREAMER_PLUGIN_COMMON_ANY_H -#include "meta/any.h" +#ifndef HST_ANY_WITH_RTTI +#ifndef HST_ANY_WITH_NO_RTTI +#define HST_ANY_WITH_NO_RTTI +#endif +#else +#ifdef HST_ANY_WITH_NO_RTTI +#undef HST_ANY_WITH_NO_RTTI +#endif +#endif -#endif // IMAGE_EFFECT_ANY_H +#ifndef MEDIA_NO_OHOS +#ifndef MEDIA_OHOS +#define MEDIA_OHOS +#endif +#else +#ifdef MEDIA_OHOS +#undef MEDIA_OHOS +#endif +#endif + +#if defined(__clang__) || defined(__GNUC__) +#define CPP_STANDARD __cplusplus +#elif defined(_MSC_VER) +#define CPP_STANDARD _MSVC_LANG +#endif + +#if CPP_STANDARD >= 201103L + +#include +#include +#include "type_cast_ext.h" +#include "securec.h" +#include +#include "message_parcel.h" + +namespace { +#if CPP_STANDARD < 201402L +template +using decay_t = typename std::decay::type; + +template +using enable_if_t = typename std::enable_if::type; + +template +using conditional_t = typename std::conditional::type; + +template +using remove_cv_t = typename std::remove_cv::type; + +template +using remove_reference_t = typename std::remove_reference::type; +#else +using std::decay_t; +using std::enable_if_t; +using std::conditional_t; +using std::remove_cv_t; +using std::remove_reference_t; +#endif + +constexpr size_t STACK_STORAGE_SIZE = 2 * sizeof(void*); // NOLINT: global var + +template +struct IsTrivialStackStorable { + static constexpr bool value = + alignof(T) <= alignof(max_align_t) && std::is_trivially_copyable::value && sizeof(T) <= STACK_STORAGE_SIZE; +}; + +template +struct IsStackStorable { + static constexpr bool value = alignof(T) <= alignof(max_align_t) && std::is_nothrow_move_constructible::value && + sizeof(T) <= STACK_STORAGE_SIZE; +}; + +template +struct IsValidCast { + static constexpr bool value = std::is_reference::value || std::is_copy_constructible::value; +}; +} // namespace +namespace OHOS { +namespace Media { + +enum struct AnyValueType : int32_t { + INVALID_TYPE = 1, + BOOL, + INT8_T, + UINT8_T, + INT32_T, + UINT32_T, + INT64_T, + UINT64_T, + FLOAT, + DOUBLE, + VECTOR_UINT8, + VECTOR_UINT32, + STRING, + VECTOR_INT32, +}; +/** + * @brief BadAnyCast exception, which is thrown when error occurs in AnyCast + * + * @since 1.0 + * @version 1.0 + */ +class BadAnyCast : public std::bad_cast { +public: + const char* what() const noexcept override + { + return "bad any cast"; + } +}; +class Any; +template +inline typename std::enable_if::value, bool>::type MakeAnyFromParcel(Any& value, MessageParcel& parcel); +template +inline typename std::enable_if::value, bool>::type MakeAnyFromParcel(Any& value, MessageParcel& parcel) +{ + (void)value; + (void)parcel; + // current only support enum from parcel + return false; +} +template +inline typename std::enable_if::value, bool>::type WriteValueToParcel(const T &value, + MessageParcel &parcel) +{ + parcel.WriteInt32(static_cast(value)); + return true; +} +template +inline typename std::enable_if::value, bool>::type WriteValueToParcel(const T &value, + MessageParcel &parcel) +{ + (void)value; + (void)parcel; + // current only support write enum to parcel + return false; +} +template +inline typename std::enable_if::value, bool>::type WriteValueToParcelInt64(const T &value, + MessageParcel &parcel) +{ + parcel.WriteInt64(static_cast(value)); + return true; +} +template +inline typename std::enable_if::value, bool>::type WriteValueToParcelInt64(const T &value, + MessageParcel &parcel) +{ + (void)value; + (void)parcel; + // current only support write enum to parcel + return false; +} +/** + * @brief This class describes a type-safe container for arbitrary type values which are copy constructible. + * + * @since 1.0 + * @version 1.0 + */ +class Any final { +public: + constexpr Any() noexcept + { + } + + __attribute__((no_sanitize("cfi"))) Any(const Any &other) : functionTable_(other.functionTable_) + { + if (other.HasValue()) { + functionTable_->copy(storage_, other.storage_); + } + } + + __attribute__((no_sanitize("cfi"))) Any(Any &&other) noexcept : functionTable_(other.functionTable_) + { + if (other.HasValue()) { + functionTable_->move(storage_, other.storage_); + other.functionTable_ = nullptr; + } + } + + /** + * constructor from right reference value with type of ValueType. + * + * @tparam Type ValueType is not the same as Any itself. The decay type of ValueType must be copy constructible. + * @param value content + */ + template , Any>::value && + std::is_copy_constructible>::value, + bool> = true> + Any(ValueType&& value) // NOLINT: explicit + { + DoEmplace>(std::forward(value)); + } + + Any& operator=(const Any& other) + { + *this = Any(other); + return *this; + } + + Any& operator=(Any&& other) noexcept + { + Reset(); + MoveFrom(std::forward(other)); + return *this; + } + + /** + * Assigns contents to Any. + * + * @tparam ValueType Type ValueType is not the same as Any itself. The decay type of ValueType must be copy + * constructible. + * @param value content + * @return + */ + template , Any>::value && + std::is_copy_constructible>::value, + bool> = true> + Any& operator=(ValueType&& value) + { + *this = Any(std::forward(value)); + return *this; + } + + /** + * Get TypeName From function info. + * @return Name of Type T + */ + template + static constexpr std::string_view GetTypeName() noexcept + { + const char* functionInfo = __PRETTY_FUNCTION__ ; + return GetTypeNameFromFunctionInfo(functionInfo); + } + + template + static bool IsSameTypeWith(const Any& other) noexcept + { +#ifndef HST_ANY_WITH_NO_RTTI + return other.SameTypeWith(typeid(T)); +#else + return other.SameTypeWith(Any::GetTypeName()); +#endif + } + + ~Any() + { + Reset(); + } + + /** + * Emplace one content with type of ValueType into object. The content is constructed by args. + * + * @tparam ValueType The decay type of ValueType must be constructible from args and copy constructible. + * @tparam Args args type + * @param args args + * @return content with type of decay ValueType + */ + template , Args...>::value && + std::is_copy_constructible>::value, + bool> = true> + decay_t& Emplace(Args&&... args) + { + Reset(); + return DoEmplace>(std::forward(args)...); + } + + /** + * Emplace one content with type of ValueType into object. The content is constructed by il and args. + * + * @tparam ValueType type of conetent. The decay type of ValueType must be constructible from il and args and copy + * constructible + * @tparam U type of initializer list. + * @tparam Args type of other args + * @param il initializer list + * @param args args + * @return content with type of decay ValueType + */ + template , std::initializer_list&, Args...>::value && + std::is_copy_constructible>::value, + bool> = true> + decay_t& Emplace(std::initializer_list il, Args&&... args) + { + Reset(); + return DoEmplace>(il, std::forward(args)...); + } + + /** + * Destroy the inner content if exists. + */ + void __attribute__((no_sanitize("cfi"))) Reset() noexcept + { + if (HasValue()) { + functionTable_->destroy(storage_); + storage_.trivialStack_.fill(0); + } + functionTable_ = nullptr; + } + + /** + * swap contents of two any objects + * + * @param other object to swap with + */ + void Swap(Any& other) noexcept + { + Any tmp(std::move(*this)); + *this = std::move(other); + other = std::move(tmp); + } + + /** + * Checks whether the object has one content. + * + * @return true if object has one content, otherwise false. + */ + bool HasValue() const noexcept + { + return IsFunctionTableValid(); + } + +#ifndef HST_ANY_WITH_NO_RTTI + /** + * Get tye type_info of object + * + * @return type info of object + */ + const std::type_info& Type() const noexcept + { + if (!HasValue()) { + return typeid(void); + } + return functionTable_->type(); + } +#else + std::string_view __attribute__((no_sanitize("cfi"))) TypeName() const noexcept + { + if (!HasValue()) { + return "empty"; // no value + } + return functionTable_->type_name(); + } + bool __attribute__((no_sanitize("cfi"))) ToParcel(MessageParcel &parcel) const noexcept + { + if (!HasValue()) { + return false; // no value + } + return functionTable_->toParcel(this, parcel); + } + bool __attribute__((no_sanitize("cfi"))) FromParcel(MessageParcel &parcel) const noexcept + { + return functionTable_->fromParcel(const_cast(this), parcel); + } +#endif + +#ifndef HST_ANY_WITH_NO_RTTI + bool SameTypeWith(const std::type_info& otherInfo) const noexcept + { + if (functionTable_ == nullptr) { + return false; + } + return IsSameType(functionTable_->type(), otherInfo); + } +#else + bool __attribute__((no_sanitize("cfi"))) SameTypeWith(std::string_view otherTypeName) const noexcept + { + if (functionTable_ == nullptr) { + return false; + } + return IsSameType(functionTable_->type_name(), otherTypeName); + } +#endif + + bool __attribute__((no_sanitize("cfi"))) SameTypeWith(const Any &other) const noexcept + { +#ifndef HST_ANY_WITH_NO_RTTI + return IsSameType(functionTable_->type(), other.Type()); +#else + return IsSameType(functionTable_->type_name(), other.TypeName()); +#endif + } + +private: + template + friend const T* AnyCast(const Any* operand) noexcept; + template + friend T* AnyCast(Any* operand) noexcept; + template + friend bool AnyCast(const Any* operand, T& value) noexcept; + + union Storage { + using Stack = std::aligned_storage::value>::type; + using Heap = void*; + + std::array trivialStack_; + Stack nonTrivialStack_; + Heap heap_; + }; + + struct FunctionTable { +#ifndef HST_ANY_WITH_NO_RTTI + const std::type_info& (*type)() noexcept; +#else + std::string_view (*type_name)() noexcept; + bool (*toParcel)(const Any *operand, MessageParcel& parcel) noexcept; + bool (*fromParcel)(Any *operand, MessageParcel& parcel) noexcept; +#endif + void (*destroy)(Storage&) noexcept; + void (*copy)(Storage&, const Storage&) noexcept; + void (*move)(Storage&, Storage&) noexcept; + void* (*getPtr)(Storage&) noexcept; + const void* (*getConstPtr)(const Storage&) noexcept; + }; + static bool BaseTypesToParcel(const Any *operand, MessageParcel& parcel) noexcept; + // returnValue : 0 -- success; 1 -- retry enum; 2 -- failed no retry + static int BaseTypesFromParcel(Any *operand, MessageParcel& parcel) noexcept; + + static std::string_view GetTypeNameFromFunctionInfo(const char* functionInfo) noexcept; + + template + struct TrivialStackFunctionTable { +#ifndef HST_ANY_WITH_NO_RTTI + static const std::type_info& Type() noexcept + { + return typeid(T); + } +#else + static std::string_view TypeName() noexcept + { + return GetTypeName(); + } + // Only support parcel enum value to int32_t except base types + static bool ToParcel(const Any *operand, MessageParcel& parcel) noexcept + { + if (BaseTypesToParcel(operand, parcel)) { + return true; + } + if (sizeof(T) > sizeof(int64_t)) { // Only support enum + return false; + } + if (sizeof(T) == sizeof(int64_t)) { // support Int64 enum + T value; + if (AnyCast(operand, value)) { + WriteValueToParcelInt64(value, parcel); + return true; + } + return false; + } + T value; + if (AnyCast(operand, value)) { + WriteValueToParcel(value, parcel); + return true; + } + return false; + } + + static bool FromParcel(Any *operand, MessageParcel& parcel) noexcept + { + int ret = BaseTypesFromParcel(operand, parcel); + if (ret == 0) { + return true; + } + MakeAnyFromParcel(*operand, parcel); + return true; + } +#endif + + static void Destroy(Storage& storage) noexcept + { + reinterpret_cast(storage.trivialStack_.data())->~T(); + } + + static void Copy(Storage& dest, const Storage& source) noexcept + { + // memcpy_s will always success in this function + (void)memcpy_s(GetPtr(dest), sizeof(Storage), GetConstPtr(source), sizeof(Storage)); + } + + static void Move(Storage& dest, Storage& source) noexcept + { + Copy(dest, source); + source.trivialStack_.fill(0); + } + + static const void* GetConstPtr(const Storage& storage) noexcept + { + return reinterpret_cast(storage.trivialStack_.data()); + } + + static void* GetPtr(Storage& storage) noexcept + { + return reinterpret_cast(storage.trivialStack_.data()); + } + }; + + template + struct StackFunctionTable { +#ifndef HST_ANY_WITH_NO_RTTI + static const std::type_info& Type() noexcept + { + return typeid(T); + } +#else + static std::string_view TypeName() noexcept + { + return GetTypeName(); + } + // Only support parcel enum value to int32_t except base types + static bool ToParcel(const Any *operand, MessageParcel& parcel) noexcept + { + if (BaseTypesToParcel(operand, parcel)) { + return true; + } + if (sizeof(T) > sizeof(int64_t)) { // Only support enum + return false; + } + if (sizeof(T) == sizeof(int64_t)) { // support Int64 enum + T value; + if (AnyCast(operand, value)) { + WriteValueToParcelInt64(value, parcel); + return true; + } + return false; + } + T value; + if (AnyCast(operand, value)) { + WriteValueToParcel(value, parcel); + return true; + } + return false; + } + + static bool FromParcel(Any *operand, MessageParcel& parcel) noexcept + { + int ret = BaseTypesFromParcel(operand, parcel); + if (ret == 0) { + return true; + } + MakeAnyFromParcel(*operand, parcel); + return true; + } +#endif + + static void Destroy(Storage& storage) noexcept + { + reinterpret_cast(GetPtr(storage))->~T(); // NOLINT: cast + } + + static void Copy(Storage& dest, const Storage& source) noexcept + { + // NOLINTNEXTLINE: reinterpret_cast + new (reinterpret_cast(GetPtr(dest))) T(*reinterpret_cast(GetConstPtr(source))); + } + + static void Move(Storage& dest, Storage& source) noexcept + { + // NOLINTNEXTLINE: reinterpret_cast + new (reinterpret_cast(GetPtr(dest))) T(std::move(*reinterpret_cast(GetPtr(source)))); + Destroy(source); + } + + static const void* GetConstPtr(const Storage& storage) noexcept + { + return reinterpret_cast(&storage.nonTrivialStack_); + } + + static void* GetPtr(Storage& storage) noexcept + { + return reinterpret_cast(&storage.nonTrivialStack_); + } + }; + + template + struct HeapFunctionTable { +#ifndef HST_ANY_WITH_NO_RTTI + static const std::type_info& Type() noexcept + { + return typeid(T); + } +#else + static std::string_view TypeName() noexcept + { + return GetTypeName(); + } + // Only support parcel enum value to int32_t except base types + static bool ToParcel(const Any *operand, MessageParcel& parcel) noexcept + { + if (BaseTypesToParcel(operand, parcel)) { + return true; + } + if (sizeof(T) > sizeof(int64_t)) { // Only support enum + return false; + } + if (sizeof(T) == sizeof(int64_t)) { // support Int64 enum + T value; + if (AnyCast(operand, value)) { + WriteValueToParcelInt64(value, parcel); + return true; + } + return false; + } + T value; + if (AnyCast(operand, value)) { + WriteValueToParcel(value, parcel); + return true; + } + return false; + } + + static bool FromParcel(Any *operand, MessageParcel& parcel) noexcept + { + int ret = BaseTypesFromParcel(operand, parcel); + if (ret == 0) { + return true; + } + MakeAnyFromParcel(*operand, parcel); + return true; + } +#endif + + static void Destroy(Storage& storage) noexcept + { + delete reinterpret_cast(storage.heap_); // NOLINT: cast + storage.heap_ = nullptr; + } + static void Copy(Storage& dest, const Storage& source) noexcept + { + dest.heap_ = new T(*reinterpret_cast(source.heap_)); // NOLINT: cast + } + static void Move(Storage& dest, Storage& source) noexcept + { + dest.heap_ = source.heap_; + source.heap_ = nullptr; + } + static const void* GetConstPtr(const Storage& storage) noexcept + { + return storage.heap_; + } + static void* GetPtr(Storage& storage) noexcept + { + return storage.heap_; + } + }; + + template + static FunctionTable* GetFunctionTable() + { + using DecayedValueType = decay_t; + using DetailFunctionTable = + conditional_t::value, + TrivialStackFunctionTable, + conditional_t::value, + StackFunctionTable, HeapFunctionTable>>; + static FunctionTable table = { +#ifndef HST_ANY_WITH_NO_RTTI + .type = DetailFunctionTable::Type, +#else + .type_name = DetailFunctionTable::TypeName, + .toParcel = DetailFunctionTable::ToParcel, + .fromParcel = DetailFunctionTable::FromParcel, +#endif + .destroy = DetailFunctionTable::Destroy, + .copy = DetailFunctionTable::Copy, + .move = DetailFunctionTable::Move, + .getPtr = DetailFunctionTable::GetPtr, + .getConstPtr = DetailFunctionTable::GetConstPtr, + }; + return &table; + } + + bool IsFunctionTableValid() const noexcept + { + return functionTable_ != nullptr; + } + + template + DecayedValueType &__attribute__((no_sanitize("cfi"))) DoEmplace(Args &&...args) + { + functionTable_ = GetFunctionTable(); + DecayedValueType* ptr = nullptr; + if (IsTrivialStackStorable::value || IsStackStorable::value) { + ptr = reinterpret_cast(functionTable_->getPtr(storage_)); + new (ptr) DecayedValueType(std::forward(args)...); + } else { + storage_.heap_ = new DecayedValueType(std::forward(args)...); + ptr = reinterpret_cast(storage_.heap_); + } + return *ptr; + } + + void __attribute__((no_sanitize("cfi"))) MoveFrom(Any &&other) noexcept + { + if (other.HasValue()) { + functionTable_ = other.functionTable_; + functionTable_->move(storage_, other.storage_); + other.Reset(); + } + } + + template + ValueType* Cast() noexcept + { + using DecayedValueType = decay_t; + if (!IsFunctionTableValid()) { + return nullptr; + } +#ifndef HST_ANY_WITH_NO_RTTI + if (!SameTypeWith(typeid(DecayedValueType))) { +#else + if (!SameTypeWith(Any::GetTypeName())) { +#endif + return nullptr; + } + return IsTrivialStackStorable::value + ? reinterpret_cast(storage_.trivialStack_.data()) + : (IsStackStorable::value + ? reinterpret_cast(&storage_.nonTrivialStack_) + : reinterpret_cast(storage_.heap_)); + } + template + const ValueType* Cast() const noexcept + { + using DecayedValueType = decay_t; + if (!IsFunctionTableValid()) { + return nullptr; + } +#ifndef HST_ANY_WITH_NO_RTTI + if (!SameTypeWith(typeid(DecayedValueType))) { +#else + if (!SameTypeWith(Any::GetTypeName())) { +#endif + return nullptr; + } + return IsTrivialStackStorable::value + ? reinterpret_cast(storage_.trivialStack_.data()) + : (IsStackStorable::value + ? reinterpret_cast(&storage_.nonTrivialStack_) + : reinterpret_cast(storage_.heap_)); + } + +private: + Storage storage_ {}; + FunctionTable* functionTable_ {nullptr}; +}; + +/** + * cast one Any pointer into ValueType pointer + * + * @tparam ValueType target value type + * @param operand any object + * @return nullptr if type mismatch, operand is nullptr, or valueType is function/array. Otherwise, a pointer to the + * const value contained by operand. + */ +template +const ValueType* AnyCast(const Any* operand) noexcept +{ + static_assert(!std::is_void::value, "ValueType of any_cast must not be void"); + if (std::is_function::value || std::is_array::value || operand == nullptr) { + return nullptr; + } + return operand->Cast(); +} + + /** + * cast one Any pointer into ValueType object + * + * @tparam ValueType target value type + * @param operand any object + * @param value ValueType + * @return false if type mismatch, operand is nullptr, or valueType is function/array. Otherwise, true to the + * value contained by operand. + */ +template +bool AnyCast(const Any* operand, ValueType& value) noexcept +{ + static_assert(!std::is_void::value, "ValueType of any_cast must not be void"); + if (std::is_function::value || std::is_array::value || operand == nullptr) { + return false; + } +#ifndef HST_ANY_WITH_NO_RTTI + if (!operand->SameTypeWith(typeid(ValueType))) { +#else + if (!operand->SameTypeWith(Any::GetTypeName())) { +#endif + return false; + } else { + auto casted_value = operand->Cast(); + if (casted_value != nullptr) { + value = *casted_value; + return true; + } + return false; + } +} + +/** + * cast one Any pointer into ValueType pointer + * + * @tparam ValueType target value type + * @param operand any object + * @return nullptr if type mismatch, operand is nullptr, or valueType is function/array. Otherwise, a pointer to the + * value contained by operand. + */ +template +ValueType* AnyCast(Any* operand) noexcept +{ + static_assert(!std::is_void::value, "ValueType of any_cast must not be void"); + if (std::is_function::value || std::is_array::value || operand == nullptr) { + return nullptr; + } + return operand->Cast(); +} + +/** + * cast one Any object into ValueType object + * + * @tparam ValueType target value type. It must match both conditions: + * 1. ValueType must be reference or constructible + * 2. Let U be remove_cv_t>, then std::is_constructible must be true + * @param operand any object + * @return throws BadAnyCast exception if type mismatch, operand is nullptr, or valueType is function/array. Otherwise, + * one object of ValueType contained in Any. + */ +template +ValueType AnyCast(const Any& other) +{ + using U = remove_cv_t>; + static_assert(IsValidCast::value, "template argument must be a reference or has copy constructors"); + static_assert(std::is_constructible::value, + "any_cast(const any&) requires ValueType constructable from const " + "remove_cv_t>&"); + auto ptr = AnyCast(&other); + return static_cast(*ptr); +} + +/** + * cast one Any object into ValueType object + * + * @tparam ValueType target value type. It must match both conditions: + * 1. ValueType must be reference or constructible + * 2. Let U be remove_cv_t>, then std::is_constructible must be true + * @param operand any object + * @return throws BadAnyCast exception if type mismatch, operand is nullptr, or valueType is function/array. Otherwise, + * one object of ValueType contained in Any. + */ +template +ValueType AnyCast(Any& other) +{ + using U = remove_cv_t>; + static_assert(IsValidCast::value, "template argument must be a reference or has copy constructors"); + static_assert(std::is_constructible::value, + "any_cast(const any&) requires ValueType constructable from " + "remove_cv_t>&"); + auto ptr = AnyCast(&other); + return static_cast(*ptr); +} + +/** + * cast one Any object into ValueType object + * + * @tparam ValueType target value type. It must match both conditions: + * 1. ValueType must be reference or constructible + * 2. Let U be remove_cv_t>, then std::is_constructible must be true + * @param operand any object + * @return throws BadAnyCast exception if type mismatch, operand is nullptr, or valueType is function/array. Otherwise, + * one object of ValueType contained in Any. + */ +template +ValueType AnyCast(Any&& other) +{ + using U = remove_cv_t>; + static_assert(IsValidCast::value, "template argument must be a reference or has copy constructors"); + static_assert(std::is_constructible::value, + "any_cast(const any&) requires ValueType constructable from " + "remove_cv_t>"); + auto ptr = AnyCast(&other); + return static_cast(std::move(*ptr)); +} + +/** + * Constructs Any object, whose content is constructed by args. The content type is T. + * + * @tparam T type of Any's content + * @tparam Args type of args + * @param args args used to construct the content + * @return Any object + */ +template +Any MakeAny(Args&&... args) +{ + Any tmp; + tmp.Emplace(std::forward(args)...); + return tmp; +} + +/** + * Constructs Any object, whose content is constructed by il and args. The content type is T. + * + * @tparam T type of Any's content + * @tparam U type of initializer list + * @tparam Args type of args + * @param il initializer list + * @param args args + * @return Any object + */ +template +Any MakeAny(std::initializer_list il, Args&&... args) +{ + Any tmp; + tmp.Emplace(il, std::forward(args)...); + return tmp; +} + +template +inline typename std::enable_if::value, bool>::type MakeAnyFromParcel(Any& value, MessageParcel +& parcel) +{ + if (sizeof(T) == sizeof(int64_t)) { + value.Emplace(static_cast(parcel.ReadInt64())); + return true; + } + value.Emplace(static_cast(parcel.ReadInt32())); + return true; +} +} // namespace Media +} // namespace OHOS +#endif +namespace std { +inline void swap(OHOS::Media::Any& lhs, OHOS::Media::Any& rhs) noexcept +{ + lhs.Swap(rhs); +} +} // namespace std +#endif // HISTREAMER_PLUGIN_COMMON_ANY_H \ No newline at end of file diff --git a/interfaces/inner_api/native/common/type_cast_ext.h b/interfaces/inner_api/native/common/type_cast_ext.h new file mode 100644 index 0000000000000000000000000000000000000000..82bf354fb0aea2e882d62e9ff78f950269bcccb2 --- /dev/null +++ b/interfaces/inner_api/native/common/type_cast_ext.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * 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. + */ +#ifndef HISTREAMER_PLUGIN_TYPE_INFO_EXT_H +#define HISTREAMER_PLUGIN_TYPE_INFO_EXT_H + +#include +#include +#include +#include +#include + +namespace OHOS { +namespace Media { +#ifndef HST_ANY_WITH_NO_RTTI +/** + * This function is used to compare two type_info. Besides the basic compare using operator == of type_info, + * we also consider types with the same names are the same types. + * @param t1 type + * @param t2 type + * @return true if t1 and t2 are the same type. otherwise, false. + */ +inline bool IsSameType(const std::type_info &t1, const std::type_info &t2) noexcept +{ + if (t1 == t2) { + return true; + } + auto t1Length = strlen(t1.name()); + if (t1Length == strlen(t2.name()) && strncmp(t1.name(), t2.name(), t1Length) == 0) { + return true; + } + return false; +} +#else +inline bool IsSameType(std::string_view t1, std::string_view t2) noexcept +{ + return std::string(t1) == std::string(t2); +} +#endif + +/** + * This function is used to reinterpret cast one shared_ptr into another shared_ptr. + * @tparam T type + * @tparam U type + * @param ptr pointer + * @return cast result + */ +template +inline std::shared_ptr ReinterpretPointerCast(const std::shared_ptr &ptr) noexcept +{ + return std::shared_ptr(ptr, reinterpret_cast(ptr.get())); +} +} // Media +} // OHOS + +#endif // HISTREAMER_PLUGIN_TYPE_INFO_EXT_H \ No newline at end of file diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index df35c1b819f71b0fc3b137f706b54a7748b8390c..4a2d36fbcf56a38a9ed47f39745f31abf3c38b09 100644 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -14,7 +14,7 @@ import("//build/test.gni") import("//foundation/multimedia/image_effect/config.gni") -module_output_path = "image_effect/image_effect_unittest" +module_output_path = "image_effect/image_effect/test" base_include_dirs = [ "$image_effect_root_dir/interfaces/inner_api/native/memory", @@ -37,6 +37,7 @@ base_sources = [ "$image_effect_root_dir/frameworks/native/efilter/filterimpl/crop/crop_efilter.cpp", "$image_effect_root_dir/frameworks/native/utils/common/common_utils.cpp", "$image_effect_root_dir/frameworks/native/utils/common/effect_json_helper.cpp", + "$image_effect_root_dir/frameworks/native/utils/common/any.cpp", "$image_effect_root_dir/frameworks/native/utils/dfx/error_code.cpp", ] @@ -103,7 +104,6 @@ ohos_unittest("image_effect_unittest") { "libexif:libexif", "googletest:gmock_main", "googletest:gtest_main", - "media_foundation:media_foundation", ] use_exceptions = true diff --git a/test/unittest/TestRenderEnvironment.cpp b/test/unittest/TestRenderEnvironment.cpp index 12fd3963d6a7be2bf06b39f401fc233263140d31..569a87019fae9107503fb288d43f18988d8b854c 100644 --- a/test/unittest/TestRenderEnvironment.cpp +++ b/test/unittest/TestRenderEnvironment.cpp @@ -80,41 +80,6 @@ public: std::shared_ptr renderEnvironment; }; -HWTEST_F(TestRenderEnvironment, TestRenderEnvironment001, TestSize.Level1) -{ - std::shared_ptr output; - renderEnvironment->outType_ = DataType::NATIVE_WINDOW; - effectBuffer->bufferInfo_->width_ = 2 * WIDTH; - renderEnvironment->GenTex(effectBuffer, output); - - effectBuffer->bufferInfo_->formatType_ = IEffectFormat::DEFAULT; - renderEnvironment->GenTex(effectBuffer, output); - - RenderTexturePtr texptr = renderEnvironment->RequestBuffer(WIDTH, HEIGHT); - EXPECT_NE(texptr, nullptr); - renderEnvironment->ConvertTextureToBuffer(texptr, effectBuffer.get()); - - GLenum internalFormat = GL_RG8; - size_t ret = GLUtils::GetInternalFormatPixelByteSize(internalFormat); - EXPECT_EQ(ret, 0); - - internalFormat = GL_R8; - ret = GLUtils::GetInternalFormatPixelByteSize(internalFormat); - EXPECT_EQ(ret, 1); - - internalFormat = GL_RGB565; - ret = GLUtils::GetInternalFormatPixelByteSize(internalFormat); - EXPECT_EQ(ret, 2); - - internalFormat = GL_RGBA4; - ret = GLUtils::GetInternalFormatPixelByteSize(internalFormat); - EXPECT_EQ(ret, 2); - - internalFormat = GL_RGBA16F; - ret = GLUtils::GetInternalFormatPixelByteSize(internalFormat); - EXPECT_EQ(ret, 8); -} - HWTEST_F(TestRenderEnvironment, TestRenderEnvironment002, TestSize.Level1) { IEffectFormat format = IEffectFormat::YUVNV12;