X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali-toolkit%2Finternal%2Ftexture-manager%2Ftexture-manager-impl.cpp;h=0984e2f5a6b21f9b7b44a644d993b6ce98eb488d;hb=refs%2Fchanges%2F95%2F284695%2F6;hp=3156f9ef308ef461b6e7c986c8fb98e7e7c7faca;hpb=e683c9fe2c2a7c0eed6b073a47c200ee23cecb36;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git diff --git a/dali-toolkit/internal/texture-manager/texture-manager-impl.cpp b/dali-toolkit/internal/texture-manager/texture-manager-impl.cpp index 3156f9e..0984e2f 100644 --- a/dali-toolkit/internal/texture-manager/texture-manager-impl.cpp +++ b/dali-toolkit/internal/texture-manager/texture-manager-impl.cpp @@ -33,34 +33,15 @@ namespace { -constexpr auto INITIAL_HASH_NUMBER = size_t{0u}; -constexpr auto DEFAULT_NUMBER_OF_LOCAL_LOADER_THREADS = size_t{4u}; -constexpr auto DEFAULT_NUMBER_OF_REMOTE_LOADER_THREADS = size_t{8u}; +constexpr auto INITIAL_HASH_NUMBER = size_t{0u}; + +constexpr auto TEXTURE_INDEX = 0u; ///< The Index for texture +constexpr auto MASK_TEXTURE_INDEX = 1u; ///< The Index for mask texture constexpr auto NUMBER_OF_LOCAL_LOADER_THREADS_ENV = "DALI_TEXTURE_LOCAL_THREADS"; constexpr auto NUMBER_OF_REMOTE_LOADER_THREADS_ENV = "DALI_TEXTURE_REMOTE_THREADS"; constexpr auto LOAD_IMAGE_YUV_PLANES_ENV = "DALI_LOAD_IMAGE_YUV_PLANES"; -size_t GetNumberOfThreads(const char* environmentVariable, size_t defaultValue) -{ - using Dali::EnvironmentVariable::GetEnvironmentVariable; - auto numberString = GetEnvironmentVariable(environmentVariable); - auto numberOfThreads = numberString ? std::strtoul(numberString, nullptr, 10) : 0; - constexpr auto MAX_NUMBER_OF_THREADS = 100u; - DALI_ASSERT_DEBUG(numberOfThreads < MAX_NUMBER_OF_THREADS); - return (numberOfThreads > 0 && numberOfThreads < MAX_NUMBER_OF_THREADS) ? numberOfThreads : defaultValue; -} - -size_t GetNumberOfLocalLoaderThreads() -{ - return GetNumberOfThreads(NUMBER_OF_LOCAL_LOADER_THREADS_ENV, DEFAULT_NUMBER_OF_LOCAL_LOADER_THREADS); -} - -size_t GetNumberOfRemoteLoaderThreads() -{ - return GetNumberOfThreads(NUMBER_OF_REMOTE_LOADER_THREADS_ENV, DEFAULT_NUMBER_OF_REMOTE_LOADER_THREADS); -} - bool NeedToLoadYuvPlanes() { auto loadYuvPlanesString = Dali::EnvironmentVariable::GetEnvironmentVariable(LOAD_IMAGE_YUV_PLANES_ENV); @@ -89,6 +70,7 @@ Debug::Filter* gTextureManagerLogFilter = Debug::Filter::New(Debug::NoLogging, f loadState == TextureManagerType::LoadState::MASK_APPLIED ? "MASK_APPLIED" : \ loadState == TextureManagerType::LoadState::UPLOADED ? "UPLOADED" : \ loadState == TextureManagerType::LoadState::CANCELLED ? "CANCELLED" : \ + loadState == TextureManagerType::LoadState::MASK_CANCELLED ? "MASK_CANCELLED" : \ loadState == TextureManagerType::LoadState::LOAD_FAILED ? "LOAD_FAILED" : \ "Unknown" // clang-format on @@ -128,8 +110,7 @@ TextureManager::MaskingData::MaskingData() TextureManager::TextureManager() : mTextureCacheManager(), - mAsyncLocalLoaders(GetNumberOfLocalLoaderThreads(), [&]() { return TextureAsyncLoadingHelper(*this); }), - mAsyncRemoteLoaders(GetNumberOfRemoteLoaderThreads(), [&]() { return TextureAsyncLoadingHelper(*this); }), + mAsyncLoader(std::unique_ptr(new TextureAsyncLoadingHelper(*this))), mLifecycleObservers(), mLoadQueue(), mRemoveQueue(), @@ -154,9 +135,9 @@ TextureSet TextureManager::LoadAnimatedImageTexture( const uint32_t& frameIndex, TextureManager::TextureId& textureId, MaskingDataPointer& maskInfo, + const Dali::ImageDimensions& desiredSize, + const Dali::FittingMode::Type& fittingMode, const Dali::SamplingMode::Type& samplingMode, - const Dali::WrapMode::Type& wrapModeU, - const Dali::WrapMode::Type& wrapModeV, const bool& synchronousLoading, TextureUploadObserver* textureObserver, TextureManager::MultiplyOnLoad& preMultiplyOnLoad) @@ -168,7 +149,7 @@ TextureSet TextureManager::LoadAnimatedImageTexture( Devel::PixelBuffer pixelBuffer; if(animatedImageLoading) { - pixelBuffer = animatedImageLoading.LoadFrame(frameIndex); + pixelBuffer = animatedImageLoading.LoadFrame(frameIndex, desiredSize, fittingMode, samplingMode); } if(!pixelBuffer) { @@ -179,7 +160,7 @@ TextureSet TextureManager::LoadAnimatedImageTexture( Texture maskTexture; if(maskInfo && maskInfo->mAlphaMaskUrl.IsValid()) { - Devel::PixelBuffer maskPixelBuffer = LoadImageFromFile(maskInfo->mAlphaMaskUrl.GetUrl(), ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::NO_FILTER, true); + Devel::PixelBuffer maskPixelBuffer = LoadImageFromFile(maskInfo->mAlphaMaskUrl.GetUrl(), desiredSize, fittingMode, samplingMode, true); if(maskPixelBuffer) { if(!maskInfo->mPreappliedMasking) @@ -210,10 +191,10 @@ TextureSet TextureManager::LoadAnimatedImageTexture( Texture texture = Texture::New(Dali::TextureType::TEXTURE_2D, pixelData.GetPixelFormat(), pixelData.GetWidth(), pixelData.GetHeight()); texture.Upload(pixelData); textureSet = TextureSet::New(); - textureSet.SetTexture(0u, texture); + textureSet.SetTexture(TEXTURE_INDEX, texture); if(maskTexture) { - textureSet.SetTexture(1u, maskTexture); + textureSet.SetTexture(MASK_TEXTURE_INDEX, maskTexture); } } } @@ -234,7 +215,7 @@ TextureSet TextureManager::LoadAnimatedImageTexture( } } - textureId = RequestLoadInternal(url, alphaMaskId, contentScaleFactor, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::BOX_THEN_LINEAR, UseAtlas::NO_ATLAS, cropToMask, StorageType::UPLOAD_TO_TEXTURE, textureObserver, true, TextureManager::ReloadPolicy::CACHED, preMultiplyOnLoad, animatedImageLoading, frameIndex, false); + textureId = RequestLoadInternal(url, alphaMaskId, contentScaleFactor, desiredSize, fittingMode, samplingMode, UseAtlas::NO_ATLAS, cropToMask, StorageType::UPLOAD_TO_TEXTURE, textureObserver, true, TextureManager::ReloadPolicy::CACHED, preMultiplyOnLoad, animatedImageLoading, frameIndex, false); TextureManager::LoadState loadState = mTextureCacheManager.GetTextureStateInternal(textureId); if(loadState == TextureManager::LoadState::UPLOADED) @@ -244,13 +225,6 @@ TextureSet TextureManager::LoadAnimatedImageTexture( } } - if(textureSet) - { - Sampler sampler = Sampler::New(); - sampler.SetWrapMode(wrapModeU, wrapModeV); - textureSet.SetSampler(0u, sampler); - } - return textureSet; } @@ -307,8 +281,6 @@ TextureSet TextureManager::LoadTexture( Dali::ImageDimensions& textureRectSize, bool& atlasingStatus, bool& loadingStatus, - const Dali::WrapMode::Type& wrapModeU, - const Dali::WrapMode::Type& wrapModeV, TextureUploadObserver* textureObserver, AtlasUploadObserver* atlasObserver, ImageAtlasManagerPtr imageAtlasManager, @@ -444,7 +416,7 @@ TextureSet TextureManager::LoadTexture( if(loadState == TextureManager::LoadState::UPLOADED) { // LoadComplete has already been called - keep the same texture set - textureSet = mTextureCacheManager.GetTextureSet(textureId); + textureSet = GetTextureSet(textureId); } // If we are loading the texture, or waiting for the ready signal handler to complete, inform @@ -463,13 +435,6 @@ TextureSet TextureManager::LoadTexture( } } - if(!atlasingStatus && textureSet) - { - Sampler sampler = Sampler::New(); - sampler.SetWrapMode(wrapModeU, wrapModeV); - textureSet.SetSampler(0u, sampler); - } - if(synchronousLoading) { loadingStatus = false; @@ -565,8 +530,7 @@ TextureManager::TextureId TextureManager::RequestLoadInternal( // Update preMultiplyOnLoad value. It should be changed according to preMultiplied value of the cached info. preMultiplyOnLoad = mTextureCacheManager[cacheIndex].preMultiplied ? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD : TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY; - - DALI_LOG_INFO(gTextureManagerLogFilter, Debug::General, "TextureManager::RequestLoad( url=%s observer=%p ) Using cached texture id@%d, textureId=%d, frameindex=%d, premultiplied=%d\n", url.GetUrl().c_str(), observer, cacheIndex.GetIndex(), textureId, frameIndex, mTextureCacheManager[cacheIndex].preMultiplied ? 1 : 0); + DALI_LOG_INFO(gTextureManagerLogFilter, Debug::General, "TextureManager::RequestLoad( url=%s observer=%p ) Using cached texture id@%d, textureId=%d, maskTextureId=%d, frameindex=%d, premultiplied=%d\n", url.GetUrl().c_str(), observer, cacheIndex.GetIndex(), textureId, maskTextureId, frameIndex, mTextureCacheManager[cacheIndex].preMultiplied ? 1 : 0); } if(textureId == INVALID_TEXTURE_ID) // There was no caching, or caching not required @@ -577,8 +541,7 @@ TextureManager::TextureId TextureManager::RequestLoadInternal( // Cache new texutre, and get cacheIndex. cacheIndex = mTextureCacheManager.AppendCache(TextureInfo(textureId, maskTextureId, url, desiredSize, contentScale, fittingMode, samplingMode, false, cropToMask, useAtlas, textureHash, orientationCorrection, preMultiply, animatedImageLoading, frameIndex, loadYuvPlanes)); - - DALI_LOG_INFO(gTextureManagerLogFilter, Debug::General, "TextureManager::RequestLoad( url=%s observer=%p ) New texture, cacheIndex:%d, textureId=%d, frameindex=%d premultiply=%d\n", url.GetUrl().c_str(), observer, cacheIndex.GetIndex(), textureId, frameIndex, preMultiply); + DALI_LOG_INFO(gTextureManagerLogFilter, Debug::General, "TextureManager::RequestLoad( url=%s observer=%p ) New texture, cacheIndex:%d, textureId=%d, maskTextureId=%d, frameindex=%d premultiply=%d\n", url.GetUrl().c_str(), observer, cacheIndex.GetIndex(), textureId, maskTextureId, frameIndex, preMultiply); } // The below code path is common whether we are using the cache or not. @@ -597,10 +560,10 @@ TextureManager::TextureId TextureManager::RequestLoadInternal( TextureManager::LoadState::WAITING_FOR_MASK != textureInfo.loadState && TextureManager::LoadState::MASK_APPLYING != textureInfo.loadState && TextureManager::LoadState::MASK_APPLIED != textureInfo.loadState && - TextureManager::LoadState::CANCELLED != textureInfo.loadState) + TextureManager::LoadState::CANCELLED != textureInfo.loadState && + TextureManager::LoadState::MASK_CANCELLED != textureInfo.loadState) { - DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Verbose, "TextureManager::RequestLoad( url=%s observer=%p ) ForcedReload cacheIndex:%d, textureId=%d\n", url.GetUrl().c_str(), observer, cacheIndex.GetIndex(), textureId); - + DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Verbose, "TextureManager::RequestLoad( url=%s observer=%p ) ForcedReload cacheIndex:%d, textureId=%d, maskTextureId=%d\n", url.GetUrl().c_str(), observer, cacheIndex.GetIndex(), textureId, maskTextureId); textureInfo.loadState = TextureManager::LoadState::NOT_STARTED; } @@ -640,6 +603,14 @@ TextureManager::TextureId TextureManager::RequestLoadInternal( ObserveTexture(textureInfo, observer); break; } + case TextureManager::LoadState::MASK_CANCELLED: + { + // A cancelled texture hasn't finished mask applying yet. Treat as a mask applying texture + // (it's ref count has already been incremented, above) + textureInfo.loadState = TextureManager::LoadState::MASK_APPLYING; + ObserveTexture(textureInfo, observer); + break; + } case TextureManager::LoadState::LOAD_FINISHED: { // Loading has already completed. @@ -683,10 +654,9 @@ TextureManager::TextureId TextureManager::RequestLoadInternal( { if(mTextureCacheManager[maskCacheIndex].storageType == StorageType::KEEP_TEXTURE) { - TextureSet maskTextures = mTextureCacheManager[maskCacheIndex].textureSet; - if(maskTextures && maskTextures.GetTextureCount()) + if(!mTextureCacheManager[maskCacheIndex].textures.empty()) { - maskTexture = maskTextures.GetTexture(0u); + maskTexture = mTextureCacheManager[maskCacheIndex].textures[0]; } } else if(mTextureCacheManager[maskCacheIndex].storageType == StorageType::KEEP_PIXEL_BUFFER) @@ -711,13 +681,10 @@ TextureManager::TextureId TextureManager::RequestLoadInternal( // Upload texture UploadTextures(pixelBuffers, textureInfo); - if(maskTexture && textureInfo.textureSet) - { - textureInfo.textureSet.SetTexture(1u, maskTexture); - } } } } + return textureId; } @@ -729,30 +696,42 @@ void TextureManager::Remove(const TextureManager::TextureId& textureId, TextureU if(textureCacheIndex != INVALID_CACHE_INDEX) { TextureManager::TextureId maskTextureId = INVALID_TEXTURE_ID; - TextureInfo& textureInfo(mTextureCacheManager[textureCacheIndex]); - if(textureInfo.maskTextureId != INVALID_TEXTURE_ID) + TextureInfo& textureInfo(mTextureCacheManager[textureCacheIndex]); + // We only need to consider maskTextureId when texture's loadState is not cancelled. Because it is already deleted. + if(textureInfo.loadState != LoadState::CANCELLED && textureInfo.loadState != LoadState::MASK_CANCELLED) { - maskTextureId = textureInfo.maskTextureId; + if(textureInfo.maskTextureId != INVALID_TEXTURE_ID) + { + maskTextureId = textureInfo.maskTextureId; + } } + DALI_LOG_INFO(gTextureManagerLogFilter, Debug::General, "TextureManager::Remove( textureId=%d observer=%p ) cacheIndex:%d removal maskTextureId=%d, loadingQueueTextureId=%d, loadState=%s\n", textureId, observer, textureCacheIndex.GetIndex(), maskTextureId, mLoadingQueueTextureId, GET_LOAD_STATE_STRING(textureInfo.loadState)); + // the case that LoadingQueue is working. if(mLoadingQueueTextureId != INVALID_TEXTURE_ID) { // If textureId is not same, this observer need to delete when ProcessRemoveQueue() is called. - TextureUploadObserver* queueObserver = nullptr; - if(mLoadingQueueTextureId != textureId) + // If textureId is same, we should not call RemoveTextureObserver. + // Because ObserverDestroyed signal already disconnected in NotifyObservers + TextureUploadObserver* queueObserver = observer; + if(mLoadingQueueTextureId == textureId) { - queueObserver = observer; + queueObserver = nullptr; } - // Remove textureId after NotifyObserver finished - if(maskTextureId != INVALID_TEXTURE_ID) + // Remove element from the mLoadQueue + for(auto&& element : mLoadQueue) { - if(textureInfo.loadState != LoadState::CANCELLED) + if(element.mTextureId == textureId && element.mObserver == observer) { - mRemoveQueue.PushBack(QueueElement(maskTextureId, nullptr)); + // Do not erase the item. We will clear it later in ProcessLoadQueue(). + element.mTextureId = INVALID_TEXTURE_ID; + element.mObserver = nullptr; + break; } } + mRemoveQueue.PushBack(QueueElement(textureId, queueObserver)); } else @@ -760,6 +739,9 @@ void TextureManager::Remove(const TextureManager::TextureId& textureId, TextureU // Remove its observer RemoveTextureObserver(textureInfo, observer); + // Remove textureId in CacheManager. Now, textureInfo is invalidate. + mTextureCacheManager.RemoveCache(textureInfo); + // Remove maskTextureId in CacheManager if(maskTextureId != INVALID_TEXTURE_ID) { @@ -767,31 +749,9 @@ void TextureManager::Remove(const TextureManager::TextureId& textureId, TextureU if(maskCacheIndex != INVALID_CACHE_INDEX) { TextureInfo& maskTextureInfo(mTextureCacheManager[maskCacheIndex]); - - // Only Remove maskTexture when texture's loadState is not CANCELLED. because it is already deleted. - if(textureInfo.loadState != LoadState::CANCELLED) - { - mTextureCacheManager.RemoveCache(maskTextureInfo); - } + mTextureCacheManager.RemoveCache(maskTextureInfo); } } - - // Remove textureId in CacheManager - mTextureCacheManager.RemoveCache(textureInfo); - } - } - - if(observer) - { - // Remove element from the LoadQueue - for(auto&& element : mLoadQueue) - { - if(element.mObserver == observer) - { - // Do not erase the item. We will clear it later in ProcessLoadQueue(). - element.mObserver = nullptr; - break; - } } } } @@ -889,6 +849,7 @@ void TextureManager::LoadOrQueueTexture(TextureManager::TextureInfo& textureInfo } case LoadState::LOADING: case LoadState::CANCELLED: + case LoadState::MASK_CANCELLED: case LoadState::LOAD_FINISHED: case LoadState::WAITING_FOR_MASK: case LoadState::MASK_APPLYING: @@ -904,27 +865,26 @@ void TextureManager::QueueLoadTexture(const TextureManager::TextureInfo& texture const auto& textureId = textureInfo.textureId; mLoadQueue.PushBack(QueueElement(textureId, observer)); - observer->DestructionSignal().Connect(this, &TextureManager::ObserverDestroyed); + if(observer) + { + observer->DestructionSignal().Connect(this, &TextureManager::ObserverDestroyed); + } } void TextureManager::LoadTexture(TextureManager::TextureInfo& textureInfo, TextureUploadObserver* observer) { DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureManager::LoadTexture(): url:%s sync:%s\n", textureInfo.url.GetUrl().c_str(), textureInfo.loadSynchronously ? "T" : "F"); - textureInfo.loadState = LoadState::LOADING; if(!textureInfo.loadSynchronously) { - auto& loadersContainer = (textureInfo.url.IsLocalResource() || textureInfo.url.IsBufferResource()) ? mAsyncLocalLoaders : mAsyncRemoteLoaders; - auto loadingHelperIt = loadersContainer.GetNext(); - auto premultiplyOnLoad = (textureInfo.preMultiplyOnLoad && textureInfo.maskTextureId == INVALID_TEXTURE_ID) ? DevelAsyncImageLoader::PreMultiplyOnLoad::ON : DevelAsyncImageLoader::PreMultiplyOnLoad::OFF; - DALI_ASSERT_ALWAYS(loadingHelperIt != loadersContainer.End()); + auto premultiplyOnLoad = (textureInfo.preMultiplyOnLoad && textureInfo.maskTextureId == INVALID_TEXTURE_ID) ? DevelAsyncImageLoader::PreMultiplyOnLoad::ON : DevelAsyncImageLoader::PreMultiplyOnLoad::OFF; if(textureInfo.animatedImageLoading) { - loadingHelperIt->LoadAnimatedImage(textureInfo.textureId, textureInfo.animatedImageLoading, textureInfo.frameIndex, premultiplyOnLoad); + mAsyncLoader->LoadAnimatedImage(textureInfo.textureId, textureInfo.animatedImageLoading, textureInfo.frameIndex, textureInfo.desiredSize, textureInfo.fittingMode, textureInfo.samplingMode, premultiplyOnLoad); } else { - loadingHelperIt->Load(textureInfo.textureId, textureInfo.url, textureInfo.desiredSize, textureInfo.fittingMode, textureInfo.samplingMode, textureInfo.orientationCorrection, premultiplyOnLoad, textureInfo.loadYuvPlanes); + mAsyncLoader->Load(textureInfo.textureId, textureInfo.url, textureInfo.desiredSize, textureInfo.fittingMode, textureInfo.samplingMode, textureInfo.orientationCorrection, premultiplyOnLoad, textureInfo.loadYuvPlanes); } } ObserveTexture(textureInfo, observer); @@ -934,7 +894,7 @@ void TextureManager::ProcessLoadQueue() { for(auto&& element : mLoadQueue) { - if(!element.mObserver) + if(element.mTextureId == INVALID_TEXTURE_ID) { continue; } @@ -945,7 +905,10 @@ void TextureManager::ProcessLoadQueue() TextureInfo& textureInfo(mTextureCacheManager[cacheIndex]); if((textureInfo.loadState == LoadState::UPLOADED) || (textureInfo.loadState == LoadState::LOAD_FINISHED && textureInfo.storageType == StorageType::RETURN_PIXEL_BUFFER)) { - EmitLoadComplete(element.mObserver, textureInfo, true); + if(element.mObserver) + { + EmitLoadComplete(element.mObserver, textureInfo, true); + } } else if(textureInfo.loadState == LoadState::LOADING) { @@ -964,15 +927,11 @@ void TextureManager::ProcessLoadQueue() void TextureManager::ProcessRemoveQueue() { - TextureCacheIndex textureCacheIndex = INVALID_CACHE_INDEX; for(auto&& element : mRemoveQueue) { - textureCacheIndex = mTextureCacheManager.GetCacheIndexFromId(element.mTextureId); - if(textureCacheIndex != INVALID_CACHE_INDEX) + if(element.mTextureId != INVALID_TEXTURE_ID) { - TextureInfo& textureInfo(mTextureCacheManager[textureCacheIndex]); - RemoveTextureObserver(textureInfo, element.mObserver); - mTextureCacheManager.RemoveCache(textureInfo); + Remove(element.mTextureId, element.mObserver); } } mRemoveQueue.Clear(); @@ -999,8 +958,7 @@ void TextureManager::AsyncLoadComplete(const TextureManager::TextureId& textureI TextureInfo& textureInfo(mTextureCacheManager[cacheIndex]); DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, " textureId:%d Url:%s CacheIndex:%d LoadState: %s\n", textureInfo.textureId, textureInfo.url.GetUrl().c_str(), cacheIndex.GetIndex(), GET_LOAD_STATE_STRING(textureInfo.loadState)); - - if(textureInfo.loadState != LoadState::CANCELLED) + if(textureInfo.loadState != LoadState::CANCELLED && textureInfo.loadState != LoadState::MASK_CANCELLED) { // textureInfo can be invalidated after this call (as the mTextureInfoContainer may be modified) PostLoad(textureInfo, pixelBuffers); @@ -1066,11 +1024,7 @@ void TextureManager::PostLoad(TextureManager::TextureInfo& textureInfo, std::vec { // Upload image texture. textureInfo.loadState will be UPLOADED. UploadTextures(pixelBuffers, textureInfo); - if(maskTextureInfo.textureSet.GetTextureCount() > 0u) - { - Texture maskTexture = maskTextureInfo.textureSet.GetTexture(0u); - textureInfo.textureSet.SetTexture(1u, maskTexture); - } + // notify mask texture set. NotifyObservers(textureInfo, true); } @@ -1147,10 +1101,15 @@ void TextureManager::CheckForWaitingTexture(TextureManager::TextureInfo& maskTex UploadTextures(pixelBuffers, maskTextureInfo); } - // Search the cache, checking if any texture has this texture id as a - // maskTextureId: + DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureManager::CheckForWaitingTexture(): maskTextureId=%d, maskTextureUrl=%s\n", maskTextureInfo.textureId, maskTextureInfo.url.GetUrl().c_str()); + + // Search the cache, checking if any texture has this texture id as a maskTextureId const std::size_t size = mTextureCacheManager.size(); + // Keep notify observer required textureIds. + // Note : NotifyObservers can change mTextureCacheManager cache struct. We should check id's validation before notify. + std::vector notifyRequiredTextureIds; + // TODO : Refactorize here to not iterate whole cached image. for(TextureCacheIndex cacheIndex = TextureCacheIndex(TextureManagerType::TEXTURE_CACHE_INDEX_TYPE_LOCAL, 0u); cacheIndex.GetIndex() < size; ++cacheIndex.detailValue.index) { @@ -1175,26 +1134,55 @@ void TextureManager::CheckForWaitingTexture(TextureManager::TextureInfo& maskTex std::vector pixelBuffers; pixelBuffers.push_back(textureInfo.pixelBuffer); UploadTextures(pixelBuffers, textureInfo); - if(maskTextureInfo.textureSet.GetTextureCount() > 0u) - { - Texture maskTexture = maskTextureInfo.textureSet.GetTexture(0u); - textureInfo.textureSet.SetTexture(1u, maskTexture); - } - // notify mask texture set. - NotifyObservers(textureInfo, true); + + // Increase reference counts for notify required textureId. + // Now we can assume that we don't remove & re-assign this textureId + // during NotifyObserver signal emit. + maskTextureInfo.referenceCount++; + textureInfo.referenceCount++; + + DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureManager::CheckForWaitingTexture(): Ready to notify textureId=%d\n", textureInfo.textureId); + + notifyRequiredTextureIds.push_back(textureInfo.textureId); } } - else + else // maskTextureInfo.loadState == LoadState::LOAD_FAILED { // Url texture load success, But alpha mask texture load failed. Run as normal image upload. DALI_LOG_ERROR("Alpha mask image loading failed! Image will not be masked\n"); std::vector pixelBuffers; pixelBuffers.push_back(textureInfo.pixelBuffer); UploadTextures(pixelBuffers, textureInfo); - NotifyObservers(textureInfo, true); + + // Increase reference counts for notify required textureId. + // Now we can assume that we don't remove & re-assign this textureId + // during NotifyObserver signal emit. + maskTextureInfo.referenceCount++; + textureInfo.referenceCount++; + + DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureManager::CheckForWaitingTexture(): Ready to notify textureId=%d\n", textureInfo.textureId); + + notifyRequiredTextureIds.push_back(textureInfo.textureId); } } } + + // Notify textures are masked + for(const auto textureId : notifyRequiredTextureIds) + { + TextureCacheIndex textureCacheIndex = mTextureCacheManager.GetCacheIndexFromId(textureId); + if(textureCacheIndex != INVALID_CACHE_INDEX) + { + TextureInfo& textureInfo(mTextureCacheManager[textureCacheIndex]); + NotifyObservers(textureInfo, true); + } + } + + // Decrease reference count + for(const auto textureId : notifyRequiredTextureIds) + { + Remove(textureId, nullptr); + } } void TextureManager::ApplyMask(TextureManager::TextureInfo& textureInfo, const TextureManager::TextureId& maskTextureId) @@ -1208,12 +1196,9 @@ void TextureManager::ApplyMask(TextureManager::TextureInfo& textureInfo, const T DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureManager::ApplyMask(): url:%s sync:%s\n", textureInfo.url.GetUrl().c_str(), textureInfo.loadSynchronously ? "T" : "F"); - textureInfo.loadState = LoadState::MASK_APPLYING; - auto& loadersContainer = (textureInfo.url.IsLocalResource() || textureInfo.url.IsBufferResource()) ? mAsyncLocalLoaders : mAsyncRemoteLoaders; - auto loadingHelperIt = loadersContainer.GetNext(); - auto premultiplyOnLoad = textureInfo.preMultiplyOnLoad ? DevelAsyncImageLoader::PreMultiplyOnLoad::ON : DevelAsyncImageLoader::PreMultiplyOnLoad::OFF; - DALI_ASSERT_ALWAYS(loadingHelperIt != loadersContainer.End()); - loadingHelperIt->ApplyMask(textureInfo.textureId, pixelBuffer, maskPixelBuffer, textureInfo.scaleFactor, textureInfo.cropToMask, premultiplyOnLoad); + textureInfo.loadState = LoadState::MASK_APPLYING; + auto premultiplyOnLoad = textureInfo.preMultiplyOnLoad ? DevelAsyncImageLoader::PreMultiplyOnLoad::ON : DevelAsyncImageLoader::PreMultiplyOnLoad::OFF; + mAsyncLoader->ApplyMask(textureInfo.textureId, pixelBuffer, maskPixelBuffer, textureInfo.scaleFactor, textureInfo.cropToMask, premultiplyOnLoad); } } @@ -1232,19 +1217,15 @@ void TextureManager::UploadTextures(std::vector& pixelBuffer renderingAddOn.CreateGeometry(textureInfo.textureId, pixelBuffers[0]); } - if(!textureInfo.textureSet) - { - textureInfo.textureSet = TextureSet::New(); - } + // Remove previous textures and insert new textures + textureInfo.textures.clear(); - uint32_t index = 0; for(auto&& pixelBuffer : pixelBuffers) { - Texture texture = Texture::New(Dali::TextureType::TEXTURE_2D, pixelBuffer.GetPixelFormat(), pixelBuffer.GetWidth(), pixelBuffer.GetHeight()); - + Texture texture = Texture::New(Dali::TextureType::TEXTURE_2D, pixelBuffer.GetPixelFormat(), pixelBuffer.GetWidth(), pixelBuffer.GetHeight()); PixelData pixelData = Devel::PixelBuffer::Convert(pixelBuffer); texture.Upload(pixelData); - textureInfo.textureSet.SetTexture(index++, texture); + textureInfo.textures.push_back(texture); } } @@ -1292,7 +1273,6 @@ void TextureManager::NotifyObservers(TextureManager::TextureInfo& textureInfo, c // Texture load requests for the same URL are deferred until the end of this // method. DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureManager::NotifyObservers() textureId:%d url:%s loadState:%s\n", textureId, info->url.GetUrl().c_str(), GET_LOAD_STATE_STRING(info->loadState)); - // It is possible for the observer to be deleted. // Disconnect and remove the observer first. observer->DestructionSignal().Disconnect(this, &TextureManager::ObserverDestroyed); @@ -1345,7 +1325,8 @@ void TextureManager::ObserverDestroyed(TextureUploadObserver* observer) { if(element.mObserver == observer) { - element.mObserver = nullptr; + element.mTextureId = INVALID_TEXTURE_ID; + element.mObserver = nullptr; } } } @@ -1361,14 +1342,75 @@ void TextureManager::EmitLoadComplete(TextureUploadObserver* observer, TextureMa { observer->LoadComplete(success, TextureUploadObserver::TextureInformation(TextureUploadObserver::ReturnType::PIXEL_BUFFER, textureInfo.pixelBuffer, textureInfo.url.GetUrl(), textureInfo.preMultiplied)); } - else if(textureInfo.isAnimatedImageFormat) + else + { + TextureSet textureSet = GetTextureSet(textureInfo); + if(textureInfo.isAnimatedImageFormat) + { + observer->LoadComplete(success, TextureUploadObserver::TextureInformation(TextureUploadObserver::ReturnType::ANIMATED_IMAGE_TEXTURE, textureInfo.textureId, textureSet, textureInfo.frameCount, textureInfo.frameInterval)); + } + else + { + observer->LoadComplete(success, TextureUploadObserver::TextureInformation(TextureUploadObserver::ReturnType::TEXTURE, textureInfo.textureId, textureSet, (textureInfo.useAtlas == UseAtlas::USE_ATLAS) ? true : false, textureInfo.atlasRect, textureInfo.preMultiplied)); + } + } +} + +TextureSet TextureManager::GetTextureSet(const TextureManager::TextureId& textureId) +{ + TextureSet textureSet; + TextureManager::LoadState loadState = mTextureCacheManager.GetTextureStateInternal(textureId); + if(loadState == TextureManager::LoadState::UPLOADED) { - observer->LoadComplete(success, TextureUploadObserver::TextureInformation(TextureUploadObserver::ReturnType::ANIMATED_IMAGE_TEXTURE, textureInfo.textureId, textureInfo.frameCount, textureInfo.frameInterval)); + // LoadComplete has already been called - keep the same texture set + TextureCacheIndex textureCacheIndex = mTextureCacheManager.GetCacheIndexFromId(textureId); + if(textureCacheIndex != INVALID_CACHE_INDEX) + { + TextureInfo& textureInfo(mTextureCacheManager[textureCacheIndex]); + textureSet = GetTextureSet(textureInfo); + } } else { - observer->LoadComplete(success, TextureUploadObserver::TextureInformation(TextureUploadObserver::ReturnType::TEXTURE, textureInfo.textureId, textureInfo.textureSet, (textureInfo.useAtlas == UseAtlas::USE_ATLAS) ? true : false, textureInfo.atlasRect, textureInfo.preMultiplied)); + DALI_LOG_ERROR("GetTextureSet is failed. texture is not uploaded \n"); } + return textureSet; +} + +TextureSet TextureManager::GetTextureSet(const TextureManager::TextureInfo& textureInfo) +{ + TextureSet textureSet; + + // LoadComplete has already been called - keep the same texture set + textureSet = TextureSet::New(); + if(!textureInfo.textures.empty()) + { + if(textureInfo.textures.size() > 1) // For YUV case + { + uint32_t index = 0u; + for(auto&& texture : textureInfo.textures) + { + textureSet.SetTexture(index++, texture); + } + } + else + { + textureSet.SetTexture(TEXTURE_INDEX, textureInfo.textures[0]); + TextureCacheIndex maskCacheIndex = mTextureCacheManager.GetCacheIndexFromId(textureInfo.maskTextureId); + if(maskCacheIndex != INVALID_CACHE_INDEX) + { + TextureInfo& maskTextureInfo(mTextureCacheManager[maskCacheIndex]); + if(maskTextureInfo.storageType == StorageType::UPLOAD_TO_TEXTURE || maskTextureInfo.storageType == StorageType::KEEP_TEXTURE) + { + if(!maskTextureInfo.textures.empty()) + { + textureSet.SetTexture(MASK_TEXTURE_INDEX, maskTextureInfo.textures[0]); + } + } + } + } + } + return textureSet; } void TextureManager::RemoveTextureObserver(TextureManager::TextureInfo& textureInfo, TextureUploadObserver* observer) @@ -1376,8 +1418,8 @@ void TextureManager::RemoveTextureObserver(TextureManager::TextureInfo& textureI // Remove its observer if(observer) { - const auto iterEnd = textureInfo.observerList.End(); - const auto iter = std::find(textureInfo.observerList.Begin(), iterEnd, observer); + const auto iterEnd = textureInfo.observerList.End(); + const auto iter = std::find(textureInfo.observerList.Begin(), iterEnd, observer); if(iter != iterEnd) { // Disconnect and remove the observer.