X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Fvisuals%2Fanimated-image%2Fanimated-image-visual.cpp;h=a334e2f83bc4a0dff18822f7cbb0ecb9a6d92177;hp=30a0dfe06b8f79c5fcd8ece51bb21885a4136db7;hb=ba1c6fea08ea39ca92356ae4b39a952919398e7e;hpb=8cd8392e5982d60111b0a2a5d33457c06e8532f5 diff --git a/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp index 30a0dfe..a334e2f 100644 --- a/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp +++ b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,6 +46,8 @@ namespace Internal { namespace { +const int CUSTOM_PROPERTY_COUNT(10); // ltr, wrap, pixel area, crop to mask, mask texture ratio + border/corner + // stop behavior DALI_ENUM_TO_STRING_TABLE_BEGIN(STOP_BEHAVIOR) DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::Toolkit::DevelImageVisual::StopBehavior, CURRENT_FRAME) @@ -61,8 +63,27 @@ DALI_ENUM_TO_STRING_TABLE_BEGIN(WRAP_MODE) DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::WrapMode, MIRRORED_REPEAT) DALI_ENUM_TO_STRING_TABLE_END(WRAP_MODE) -const Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f); -constexpr auto LOOP_FOREVER = -1; +// load policies +DALI_ENUM_TO_STRING_TABLE_BEGIN(LOAD_POLICY) + DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::Toolkit::ImageVisual::LoadPolicy, IMMEDIATE) + DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::Toolkit::ImageVisual::LoadPolicy, ATTACHED) +DALI_ENUM_TO_STRING_TABLE_END(LOAD_POLICY) + +// release policies +DALI_ENUM_TO_STRING_TABLE_BEGIN(RELEASE_POLICY) + DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::Toolkit::ImageVisual::ReleasePolicy, DETACHED) + DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::Toolkit::ImageVisual::ReleasePolicy, DESTROYED) + DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::Toolkit::ImageVisual::ReleasePolicy, NEVER) +DALI_ENUM_TO_STRING_TABLE_END(RELEASE_POLICY) + +static constexpr uint32_t SINGLE_IMAGE_COUNT = 1u; +static constexpr uint32_t FIRST_FRAME_INDEX = 0u; +static constexpr uint16_t MINIMUM_CACHESIZE = 1; +static constexpr Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f); +static constexpr auto LOOP_FOREVER = -1; +static constexpr auto FIRST_LOOP = 0u; + +constexpr uint32_t TEXTURE_COUNT_FOR_GPU_ALPHA_MASK = 2u; #if defined(DEBUG_ENABLED) Debug::Filter* gAnimImgLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_ANIMATED_IMAGE"); @@ -74,18 +95,15 @@ Debug::Filter* gAnimImgLogFilter = Debug::Filter::New(Debug::NoLogging, false, " * * | New * | DoSetProperties() - * | LoadFirstBatch() - * | new cache - * | cache->LoadBatch() + * | OnInitialize() + * | CreateImageCache() * | * | DoSetOnScene() * | PrepareTextureSet() * | cache->FirstFrame() - * | CreateRenderer() (Doesn't become ready until first frame loads) - * | StartFirstFrame() * | * | FrameReady(textureSet) - * | start first frame: + * | StartFirstFrame: * | actor.AddRenderer * | start timer * | mRenderer.SetTextures(textureSet) @@ -95,8 +113,7 @@ Debug::Filter* gAnimImgLogFilter = Debug::Filter::New(Debug::NoLogging, false, " * | if front frame is ready, * | mRenderer.SetTextures( front frame's texture ) * | else - * | mWaitingForTexture=true - * | cache->LoadBatch() + * | Waiting for frame ready. * | * | FrameReady(textureSet) * | mRenderer.SetTextures(textureSet) @@ -110,11 +127,6 @@ AnimatedImageVisualPtr AnimatedImageVisual::New(VisualFactoryCache& factoryCache visual->InitializeAnimatedImage(imageUrl); visual->SetProperties(properties); - if(visual->mFrameCount > 0) - { - visual->LoadFirstBatch(); - } - visual->Initialize(); return visual; @@ -136,11 +148,6 @@ AnimatedImageVisualPtr AnimatedImageVisual::New(VisualFactoryCache& factoryCache visual->mFrameCount = imageUrls.Count(); visual->SetProperties(properties); - if(visual->mFrameCount > 0) - { - visual->LoadFirstBatch(); - } - visual->Initialize(); return visual; @@ -151,11 +158,6 @@ AnimatedImageVisualPtr AnimatedImageVisual::New(VisualFactoryCache& factoryCache AnimatedImageVisualPtr visual(new AnimatedImageVisual(factoryCache, shaderFactory)); visual->InitializeAnimatedImage(imageUrl); - if(visual->mFrameCount > 0) - { - visual->LoadFirstBatch(); - } - visual->Initialize(); return visual; @@ -165,11 +167,43 @@ void AnimatedImageVisual::InitializeAnimatedImage(const VisualUrl& imageUrl) { mImageUrl = imageUrl; mAnimatedImageLoading = AnimatedImageLoading::New(imageUrl.GetUrl(), imageUrl.IsLocalResource()); - mFrameCount = mAnimatedImageLoading.GetImageCount(); +} + +void AnimatedImageVisual::CreateImageCache() +{ + DALI_LOG_INFO(gAnimImgLogFilter, Debug::Concise, "AnimatedImageVisual::CreateImageCache() batchSize:%d cacheSize:%d\n", mBatchSize, mCacheSize); + + TextureManager& textureManager = mFactoryCache.GetTextureManager(); + + if(mAnimatedImageLoading) + { + mImageCache = new RollingAnimatedImageCache(textureManager, mAnimatedImageLoading, mMaskingData, *this, mCacheSize, mBatchSize, IsSynchronousLoadingRequired(),mFactoryCache.GetPreMultiplyOnLoad()); + } + else if(mImageUrls) + { + // Ensure the batch size and cache size are no bigger than the number of URLs, + // and that the cache is at least as big as the batch size. + uint16_t numUrls = mImageUrls->size(); + uint16_t batchSize = std::max(std::min(mBatchSize, numUrls), MINIMUM_CACHESIZE); + uint16_t cacheSize = std::max(std::min(std::max(batchSize, mCacheSize), numUrls), MINIMUM_CACHESIZE); + if(cacheSize < numUrls) + { + mImageCache = new RollingImageCache(textureManager, *mImageUrls, mMaskingData, *this, cacheSize, batchSize, mFrameDelay); + } + else + { + mImageCache = new FixedImageCache(textureManager, *mImageUrls, mMaskingData, *this, batchSize, mFrameDelay); + } + } + + if(!mImageCache) + { + DALI_LOG_ERROR("mImageCache is null\n"); + } } AnimatedImageVisual::AnimatedImageVisual(VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory) -: Visual::Base(factoryCache, Visual::FittingMode::FIT_KEEP_ASPECT_RATIO, Toolkit::Visual::ANIMATED_IMAGE), +: Visual::Base(factoryCache, Visual::FittingMode::FILL, Toolkit::Visual::ANIMATED_IMAGE), mFrameDelayTimer(), mPlacementActor(), mImageVisualShaderFactory(shaderFactory), @@ -177,27 +211,37 @@ AnimatedImageVisual::AnimatedImageVisual(VisualFactoryCache& factoryCache, Image mImageUrl(), mAnimatedImageLoading(), mFrameIndexForJumpTo(0), + mCurrentFrameIndex(FIRST_FRAME_INDEX), mImageUrls(NULL), mImageCache(NULL), mCacheSize(2), mBatchSize(2), mFrameDelay(100), mLoopCount(LOOP_FOREVER), - mCurrentLoopIndex(0), - mUrlIndex(0), + mCurrentLoopIndex(FIRST_LOOP), + mLoadPolicy(Toolkit::ImageVisual::LoadPolicy::ATTACHED), + mReleasePolicy(Toolkit::ImageVisual::ReleasePolicy::DETACHED), + mMaskingData(), mFrameCount(0), mImageSize(), + mActionStatus(DevelAnimatedImageVisual::Action::PLAY), mWrapModeU(WrapMode::DEFAULT), mWrapModeV(WrapMode::DEFAULT), - mActionStatus(DevelAnimatedImageVisual::Action::PLAY), mStopBehavior(DevelImageVisual::StopBehavior::CURRENT_FRAME), mStartFirstFrame(false), mIsJumpTo(false) { + EnablePreMultipliedAlpha(mFactoryCache.GetPreMultiplyOnLoad()); } AnimatedImageVisual::~AnimatedImageVisual() { + // AnimatedImageVisual destroyed so remove texture unless ReleasePolicy is set to never release + // If this is animated image, clear cache. Else if this is single frame image, this is affected be release policy. + if(mFrameCount > SINGLE_IMAGE_COUNT || mReleasePolicy != Toolkit::ImageVisual::ReleasePolicy::NEVER) + { + mImageCache->ClearCache(); + } delete mImageCache; delete mImageUrls; } @@ -206,13 +250,26 @@ void AnimatedImageVisual::GetNaturalSize(Vector2& naturalSize) { if(mImageSize.GetWidth() == 0 && mImageSize.GetHeight() == 0) { + if(mMaskingData && mMaskingData->mAlphaMaskUrl.IsValid() && + mMaskingData->mCropToMask) + { + ImageDimensions dimensions = Dali::GetClosestImageSize(mMaskingData->mAlphaMaskUrl.GetUrl()); + if(dimensions != ImageDimensions(0, 0)) + { + mImageSize = dimensions; + naturalSize.x = dimensions.GetWidth(); + naturalSize.y = dimensions.GetHeight(); + return; + } + } + if(mImageUrl.IsValid()) { mImageSize = mAnimatedImageLoading.GetImageSize(); } else if(mImageUrls && mImageUrls->size() > 0) { - mImageSize = Dali::GetClosestImageSize((*mImageUrls)[0].mUrl); + mImageSize = Dali::GetClosestImageSize((*mImageUrls)[0].mUrl.GetUrl()); } } @@ -238,7 +295,7 @@ void AnimatedImageVisual::DoCreatePropertyMap(Property::Map& map) const Property::Array urls; for(unsigned int i = 0; i < mImageUrls->size(); ++i) { - urls.Add((*mImageUrls)[i].mUrl); + urls.Add((*mImageUrls)[i].mUrl.GetUrl()); } Property::Value value(const_cast(urls)); map.Insert(Toolkit::ImageVisual::Property::URL, value); @@ -253,9 +310,20 @@ void AnimatedImageVisual::DoCreatePropertyMap(Property::Map& map) const map.Insert(Toolkit::ImageVisual::Property::FRAME_DELAY, static_cast(mFrameDelay)); map.Insert(Toolkit::DevelImageVisual::Property::LOOP_COUNT, static_cast(mLoopCount)); map.Insert(Toolkit::DevelImageVisual::Property::CURRENT_FRAME_NUMBER, (mImageCache) ? static_cast(mImageCache->GetCurrentFrameIndex()) : -1); - map.Insert(Toolkit::DevelImageVisual::Property::TOTAL_FRAME_NUMBER, (mImageCache) ? static_cast(mImageCache->GetTotalFrameCount()) : -1); + map.Insert(Toolkit::DevelImageVisual::Property::TOTAL_FRAME_NUMBER, (mImageCache) ? static_cast((mAnimatedImageLoading) ? mAnimatedImageLoading.GetImageCount() : mImageCache->GetTotalFrameCount()) : -1); map.Insert(Toolkit::DevelImageVisual::Property::STOP_BEHAVIOR, mStopBehavior); + + if(mMaskingData != nullptr) + { + map.Insert(Toolkit::ImageVisual::Property::ALPHA_MASK_URL, mMaskingData->mAlphaMaskUrl.GetUrl()); + map.Insert(Toolkit::ImageVisual::Property::MASK_CONTENT_SCALE, mMaskingData->mContentScaleFactor); + map.Insert(Toolkit::ImageVisual::Property::CROP_TO_MASK, mMaskingData->mCropToMask); + map.Insert(Toolkit::DevelImageVisual::Property::MASKING_TYPE, mMaskingData->mPreappliedMasking ? DevelImageVisual::MaskingType::MASKING_ON_LOADING : DevelImageVisual::MaskingType::MASKING_ON_RENDERING); + } + + map.Insert(Toolkit::ImageVisual::Property::LOAD_POLICY, mLoadPolicy); + map.Insert(Toolkit::ImageVisual::Property::RELEASE_POLICY, mReleasePolicy); } void AnimatedImageVisual::DoCreateInstancePropertyMap(Property::Map& map) const @@ -293,7 +361,8 @@ void AnimatedImageVisual::OnDoAction(const Dali::Property::Index actionId, const { // STOP reset functionality will actually be done in a future change // Stop will be executed on next timer tick - mActionStatus = DevelAnimatedImageVisual::Action::STOP; + mActionStatus = DevelAnimatedImageVisual::Action::STOP; + mCurrentLoopIndex = FIRST_LOOP; if(IsOnScene()) { DisplayNextFrame(); @@ -368,8 +437,41 @@ void AnimatedImageVisual::DoSetProperties(const Property::Map& propertyMap) { DoSetProperty(Toolkit::DevelImageVisual::Property::STOP_BEHAVIOR, keyValue.second); } + else if(keyValue.first == ALPHA_MASK_URL) + { + DoSetProperty(Toolkit::ImageVisual::Property::ALPHA_MASK_URL, keyValue.second); + } + else if(keyValue.first == MASK_CONTENT_SCALE_NAME) + { + DoSetProperty(Toolkit::ImageVisual::Property::MASK_CONTENT_SCALE, keyValue.second); + } + else if(keyValue.first == CROP_TO_MASK_NAME) + { + DoSetProperty(Toolkit::ImageVisual::Property::CROP_TO_MASK, keyValue.second); + } + else if(keyValue.first == MASKING_TYPE_NAME) + { + DoSetProperty(Toolkit::DevelImageVisual::Property::MASKING_TYPE, keyValue.second); + } + else if(keyValue.first == LOAD_POLICY_NAME) + { + DoSetProperty(Toolkit::ImageVisual::Property::LOAD_POLICY, keyValue.second); + } + else if(keyValue.first == RELEASE_POLICY_NAME) + { + DoSetProperty(Toolkit::ImageVisual::Property::RELEASE_POLICY, keyValue.second); + } + else if(keyValue.first == SYNCHRONOUS_LOADING) + { + DoSetProperty(Toolkit::ImageVisual::Property::SYNCHRONOUS_LOADING, keyValue.second); + } } } + // Load image immediately if LOAD_POLICY requires it + if(mLoadPolicy == Toolkit::ImageVisual::LoadPolicy::IMMEDIATE) + { + PrepareTextureSet(); + } } void AnimatedImageVisual::DoSetProperty(Property::Index index, @@ -449,6 +551,10 @@ void AnimatedImageVisual::DoSetProperty(Property::Index index, if(value.Get(frameDelay)) { mFrameDelay = frameDelay; + if(mImageCache) + { + mImageCache->SetInterval(static_cast(mFrameDelay)); + } } break; } @@ -479,37 +585,82 @@ void AnimatedImageVisual::DoSetProperty(Property::Index index, value.Get(sync); if(sync) { - mImpl->mFlags |= Impl::IS_SYNCHRONOUS_RESOURCE_LOADING; + mImpl->mFlags |= Visual::Base::Impl::IS_SYNCHRONOUS_RESOURCE_LOADING; } else { - mImpl->mFlags &= ~Impl::IS_SYNCHRONOUS_RESOURCE_LOADING; + mImpl->mFlags &= ~Visual::Base::Impl::IS_SYNCHRONOUS_RESOURCE_LOADING; + } + break; + } + + case Toolkit::ImageVisual::Property::ALPHA_MASK_URL: + { + std::string alphaUrl = ""; + if(value.Get(alphaUrl)) + { + AllocateMaskData(); + mMaskingData->mAlphaMaskUrl = alphaUrl; + } + break; + } + + case Toolkit::ImageVisual::Property::MASK_CONTENT_SCALE: + { + float scale = 1.0f; + if(value.Get(scale)) + { + AllocateMaskData(); + mMaskingData->mContentScaleFactor = scale; } break; } + + case Toolkit::ImageVisual::Property::CROP_TO_MASK: + { + bool crop = false; + if(value.Get(crop)) + { + AllocateMaskData(); + mMaskingData->mCropToMask = crop; + } + break; + } + + case Toolkit::DevelImageVisual::Property::MASKING_TYPE: + { + int maskingType = 0; + if(value.Get(maskingType)) + { + AllocateMaskData(); + mMaskingData->mPreappliedMasking = Toolkit::DevelImageVisual::MaskingType::Type(maskingType) == Toolkit::DevelImageVisual::MaskingType::MASKING_ON_LOADING ? true : false; + } + break; + } + + case Toolkit::ImageVisual::Property::RELEASE_POLICY: + { + int releasePolicy = 0; + Scripting::GetEnumerationProperty(value, RELEASE_POLICY_TABLE, RELEASE_POLICY_TABLE_COUNT, releasePolicy); + mReleasePolicy = Toolkit::ImageVisual::ReleasePolicy::Type(releasePolicy); + break; + } + + case Toolkit::ImageVisual::Property::LOAD_POLICY: + { + int loadPolicy = 0; + Scripting::GetEnumerationProperty(value, LOAD_POLICY_TABLE, LOAD_POLICY_TABLE_COUNT, loadPolicy); + mLoadPolicy = Toolkit::ImageVisual::LoadPolicy::Type(loadPolicy); + break; + } } } void AnimatedImageVisual::DoSetOnScene(Actor& actor) { - mPlacementActor = actor; - TextureSet textureSet = PrepareTextureSet(); - - // Loading animated image file is failed. - if(!mImageCache || - (mAnimatedImageLoading && !mAnimatedImageLoading.HasLoadingSucceeded())) - { - textureSet = SetLoadingFailed(); - } - - if(textureSet) // if the image loading is successful - { - StartFirstFrame(textureSet); - } - else - { - mStartFirstFrame = true; - } + mStartFirstFrame = true; + mPlacementActor = actor; + PrepareTextureSet(); } void AnimatedImageVisual::DoSetOffScene(Actor& actor) @@ -523,36 +674,67 @@ void AnimatedImageVisual::DoSetOffScene(Actor& actor) } actor.RemoveRenderer(mImpl->mRenderer); + if(mReleasePolicy == Toolkit::ImageVisual::ReleasePolicy::DETACHED) + { + mImageCache->ClearCache(); // If INVALID_TEXTURE_ID then removal will be attempted on atlas + mImpl->mResourceStatus = Toolkit::Visual::ResourceStatus::PREPARING; + + TextureSet textureSet = TextureSet::New(); + mImpl->mRenderer.SetTextures(textureSet); + } + mPlacementActor.Reset(); - mStartFirstFrame = false; + mStartFirstFrame = false; + mCurrentFrameIndex = FIRST_FRAME_INDEX; + mCurrentLoopIndex = FIRST_LOOP; } void AnimatedImageVisual::OnSetTransform() { if(mImpl->mRenderer) { - mImpl->mTransform.RegisterUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT); + mImpl->mTransform.SetUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT); + } +} + +void AnimatedImageVisual::UpdateShader() +{ + if(mImpl->mRenderer) + { + Shader shader = GenerateShader(); + mImpl->mRenderer.SetShader(shader); } } +Shader AnimatedImageVisual::GenerateShader() const +{ + bool defaultWrapMode = mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE; + bool requiredAlphaMaskingOnRendering = (mMaskingData && !mMaskingData->mMaskImageLoadingFailed) ? !mMaskingData->mPreappliedMasking : false; + Shader shader; + shader = mImageVisualShaderFactory.GetShader( + mFactoryCache, + ImageVisualShaderFeature::FeatureBuilder() + .ApplyDefaultTextureWrapMode(defaultWrapMode) + .EnableRoundedCorner(IsRoundedCornerRequired()) + .EnableBorderline(IsBorderlineRequired()) + .EnableAlphaMaskingOnRendering(requiredAlphaMaskingOnRendering)); + return shader; +} + void AnimatedImageVisual::OnInitialize() { + CreateImageCache(); + bool defaultWrapMode = mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE; - bool atlasing = false; - Shader shader = mImageVisualShaderFactory.GetShader( - mFactoryCache, - atlasing ? TextureAtlas::ENABLED : TextureAtlas::DISABLED, - defaultWrapMode ? DefaultTextureWrapMode::APPLY : DefaultTextureWrapMode::DO_NOT_APPLY, - IsRoundedCornerRequired() ? RoundedCorner::ENABLED : RoundedCorner::DISABLED, - IsBorderlineRequired() ? Borderline::ENABLED : Borderline::DISABLED - ); + Shader shader = GenerateShader(); Geometry geometry = mFactoryCache.GetGeometry(VisualFactoryCache::QUAD_GEOMETRY); - mImpl->mRenderer = Renderer::New(geometry, shader); + mImpl->mRenderer = VisualRenderer::New(geometry, shader); + mImpl->mRenderer.ReserveCustomProperties(CUSTOM_PROPERTY_COUNT); // Register transform properties - mImpl->mTransform.RegisterUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT); + mImpl->mTransform.SetUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT); if(!defaultWrapMode) // custom wrap mode { @@ -565,63 +747,20 @@ void AnimatedImageVisual::OnInitialize() { mImpl->mRenderer.RegisterProperty(PIXEL_AREA_UNIFORM_NAME, mPixelArea); } -} - -void AnimatedImageVisual::LoadFirstBatch() -{ - // Ensure the batch size and cache size are no bigger than the number of URLs, - // and that the cache is at least as big as the batch size. - uint16_t numUrls = 0; - uint16_t batchSize = 1; - uint16_t cacheSize = 1; - - if(mImageUrls) - { - numUrls = mImageUrls->size(); - } - else - { - numUrls = mFrameCount; - } - - batchSize = std::min(mBatchSize, numUrls); - cacheSize = std::min(std::max(batchSize, mCacheSize), numUrls); - - DALI_LOG_INFO(gAnimImgLogFilter, Debug::Concise, "AnimatedImageVisual::LoadFirstBatch() batchSize:%d cacheSize:%d\n", batchSize, cacheSize); - mUrlIndex = 0; - TextureManager& textureManager = mFactoryCache.GetTextureManager(); - - if(mAnimatedImageLoading) - { - mImageCache = new RollingAnimatedImageCache(textureManager, mAnimatedImageLoading, mFrameCount, *this, cacheSize, batchSize, IsSynchronousLoadingRequired()); - } - else if(mImageUrls) + if(mMaskingData) { - if(batchSize > 0 && cacheSize > 0) - { - if(cacheSize < numUrls) - { - mImageCache = new RollingImageCache(textureManager, *mImageUrls, *this, cacheSize, batchSize); - } - else - { - mImageCache = new FixedImageCache(textureManager, *mImageUrls, *this, batchSize); - } - } - else - { - mImageCache = new RollingImageCache(textureManager, *mImageUrls, *this, 1, 1); - } + mImpl->mRenderer.RegisterProperty(CROP_TO_MASK_NAME, static_cast(mMaskingData->mCropToMask)); } - if(!mImageCache) - { - DALI_LOG_ERROR("mImageCache is null\n"); - } + // Enable PreMultipliedAlpha if it need premultiplied + auto preMultiplyOnLoad = IsPreMultipliedAlphaEnabled() && !mImpl->mCustomShader + ? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD + : TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY; + EnablePreMultipliedAlpha(preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD); } -void AnimatedImageVisual::StartFirstFrame(TextureSet& textureSet) +void AnimatedImageVisual::StartFirstFrame(TextureSet& textureSet, uint32_t firstInterval) { DALI_LOG_INFO(gAnimImgLogFilter, Debug::Concise, "AnimatedImageVisual::StartFirstFrame()\n"); @@ -629,6 +768,7 @@ void AnimatedImageVisual::StartFirstFrame(TextureSet& textureSet) if(mImpl->mRenderer) { mImpl->mRenderer.SetTextures(textureSet); + CheckMaskTexture(); Actor actor = mPlacementActor.GetHandle(); if(actor) @@ -638,26 +778,23 @@ void AnimatedImageVisual::StartFirstFrame(TextureSet& textureSet) } } - if(mFrameCount > 1) + if(mImpl->mResourceStatus != Toolkit::Visual::ResourceStatus::FAILED) { - int frameDelay = mImageCache->GetFrameInterval(0); - if(frameDelay == 0u) + if(mFrameCount > SINGLE_IMAGE_COUNT) { - frameDelay = mFrameDelay; // from URL array + mFrameDelayTimer = Timer::New(firstInterval); + mFrameDelayTimer.TickSignal().Connect(this, &AnimatedImageVisual::DisplayNextFrame); + mFrameDelayTimer.Start(); } - mFrameDelayTimer = Timer::New(frameDelay); - mFrameDelayTimer.TickSignal().Connect(this, &AnimatedImageVisual::DisplayNextFrame); - mFrameDelayTimer.Start(); - } - if(mImpl->mResourceStatus != Toolkit::Visual::ResourceStatus::FAILED) - { DALI_LOG_INFO(gAnimImgLogFilter, Debug::Concise, "ResourceReady(ResourceStatus::READY)\n"); ResourceReady(Toolkit::Visual::ResourceStatus::READY); } + + mCurrentFrameIndex = FIRST_FRAME_INDEX; } -TextureSet AnimatedImageVisual::PrepareTextureSet() +void AnimatedImageVisual::PrepareTextureSet() { TextureSet textureSet; if(mImageCache) @@ -665,12 +802,11 @@ TextureSet AnimatedImageVisual::PrepareTextureSet() textureSet = mImageCache->FirstFrame(); } + // Check whether synchronous loading is true or false for the first frame. if(textureSet) { SetImageSize(textureSet); } - - return textureSet; } void AnimatedImageVisual::SetImageSize(TextureSet& textureSet) @@ -683,28 +819,49 @@ void AnimatedImageVisual::SetImageSize(TextureSet& textureSet) mImageSize.SetWidth(texture.GetWidth()); mImageSize.SetHeight(texture.GetHeight()); } + + if(textureSet.GetTextureCount() > 1u && mMaskingData && mMaskingData->mCropToMask) + { + Texture maskTexture = textureSet.GetTexture(1); + if(maskTexture) + { + mImageSize.SetWidth(std::min(static_cast(mImageSize.GetWidth() * mMaskingData->mContentScaleFactor), maskTexture.GetWidth())); + mImageSize.SetHeight(std::min(static_cast(mImageSize.GetHeight() * mMaskingData->mContentScaleFactor), maskTexture.GetHeight())); + + float textureWidth = std::max(static_cast(texture.GetWidth() * mMaskingData->mContentScaleFactor), Dali::Math::MACHINE_EPSILON_1); + float textureHeight = std::max(static_cast(texture.GetHeight() * mMaskingData->mContentScaleFactor), Dali::Math::MACHINE_EPSILON_1); + Vector2 textureRatio(std::min(static_cast(maskTexture.GetWidth()), textureWidth) / textureWidth, + std::min(static_cast(maskTexture.GetHeight()), textureHeight) / textureHeight); + mImpl->mRenderer.RegisterProperty(MASK_TEXTURE_RATIO_NAME, textureRatio); + } + } } } -void AnimatedImageVisual::FrameReady(TextureSet textureSet) +void AnimatedImageVisual::FrameReady(TextureSet textureSet, uint32_t interval) { // When image visual requested to load new frame to mImageCache and it is failed. - if(!textureSet) + if(!mImageCache || !textureSet) { textureSet = SetLoadingFailed(); } - SetImageSize(textureSet); if(mStartFirstFrame) { - StartFirstFrame(textureSet); + mFrameCount = mImageCache->GetTotalFrameCount(); + StartFirstFrame(textureSet, interval); } else { if(mImpl->mRenderer) { + if(mFrameDelayTimer && interval > 0u) + { + mFrameDelayTimer.SetInterval(interval); + } mImpl->mRenderer.SetTextures(textureSet); + CheckMaskTexture(); } } } @@ -716,7 +873,6 @@ bool AnimatedImageVisual::DisplayNextFrame() if(mImageCache) { - bool nextFrame = false; uint32_t frameIndex = mImageCache->GetCurrentFrameIndex(); if(mIsJumpTo) @@ -730,10 +886,10 @@ bool AnimatedImageVisual::DisplayNextFrame() } else if(mActionStatus == DevelAnimatedImageVisual::Action::STOP) { - frameIndex = 0; + mCurrentLoopIndex = FIRST_LOOP; if(mStopBehavior == DevelImageVisual::StopBehavior::FIRST_FRAME) { - frameIndex = 0; + frameIndex = FIRST_FRAME_INDEX; } else if(mStopBehavior == DevelImageVisual::StopBehavior::LAST_FRAME) { @@ -746,13 +902,12 @@ bool AnimatedImageVisual::DisplayNextFrame() } else { - if(mFrameCount > 1) + if(mFrameCount > SINGLE_IMAGE_COUNT) { - nextFrame = true; frameIndex++; if(frameIndex >= mFrameCount) { - frameIndex %= mFrameCount; + frameIndex = FIRST_FRAME_INDEX; ++mCurrentLoopIndex; } @@ -763,38 +918,25 @@ bool AnimatedImageVisual::DisplayNextFrame() return DisplayNextFrame(); } } - - unsigned int delay = mImageCache->GetFrameInterval(frameIndex); - if(delay > 0u) - { - if(mFrameDelayTimer.GetInterval() != delay) - { - mFrameDelayTimer.SetInterval(delay); - } - } } DALI_LOG_INFO(gAnimImgLogFilter, Debug::Concise, "AnimatedImageVisual::DisplayNextFrame(this:%p) CurrentFrameIndex:%d\n", this, frameIndex); - if(nextFrame) - { - textureSet = mImageCache->NextFrame(); - } - else - { - textureSet = mImageCache->Frame(frameIndex); - } - - continueTimer = (mActionStatus == DevelAnimatedImageVisual::Action::PLAY) ? true : false; - } + textureSet = mImageCache->Frame(frameIndex); - if(textureSet) - { - SetImageSize(textureSet); - if(mImpl->mRenderer) + if(textureSet) { - mImpl->mRenderer.SetTextures(textureSet); + SetImageSize(textureSet); + if(mImpl->mRenderer) + { + mImpl->mRenderer.SetTextures(textureSet); + CheckMaskTexture(); + } + mFrameDelayTimer.SetInterval(mImageCache->GetFrameInterval(frameIndex)); } + + mCurrentFrameIndex = frameIndex; + continueTimer = (mActionStatus == DevelAnimatedImageVisual::Action::PLAY && textureSet) ? true : false; } return continueTimer; @@ -805,9 +947,14 @@ TextureSet AnimatedImageVisual::SetLoadingFailed() DALI_LOG_INFO(gAnimImgLogFilter, Debug::Concise, "ResourceReady(ResourceStatus::FAILED)\n"); ResourceReady(Toolkit::Visual::ResourceStatus::FAILED); - TextureSet textureSet = TextureSet::New(); - Texture brokenImage = mFactoryCache.GetBrokenVisualImage(); - textureSet.SetTexture(0u, brokenImage); + Actor actor = mPlacementActor.GetHandle(); + Vector2 imageSize = Vector2::ZERO; + if(actor) + { + imageSize = actor.GetProperty(Actor::Property::SIZE).Get(); + } + mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize); + TextureSet textureSet = mImpl->mRenderer.GetTextures(); if(mFrameDelayTimer) { @@ -820,6 +967,32 @@ TextureSet AnimatedImageVisual::SetLoadingFailed() return textureSet; } +void AnimatedImageVisual::AllocateMaskData() +{ + if(!mMaskingData) + { + mMaskingData.reset(new TextureManager::MaskingData()); + } +} + +void AnimatedImageVisual::CheckMaskTexture() +{ + if(mMaskingData && !mMaskingData->mPreappliedMasking) + { + bool maskLoadFailed = true; + TextureSet textures = mImpl->mRenderer.GetTextures(); + if(textures && textures.GetTextureCount() >= TEXTURE_COUNT_FOR_GPU_ALPHA_MASK) + { + maskLoadFailed = false; + } + if(mMaskingData->mMaskImageLoadingFailed != maskLoadFailed) + { + mMaskingData->mMaskImageLoadingFailed = maskLoadFailed; + UpdateShader(); + } + } +} + } // namespace Internal } // namespace Toolkit