From df48fc1b49f6e01aa6c9980dcca69b816746e127 Mon Sep 17 00:00:00 2001 From: "Eunki, Hong" Date: Fri, 30 Sep 2022 13:41:51 +0900 Subject: [PATCH] Make MASK_CANCELLED loadstate + minor log info When we remove the image during ApplyMask job, the loadstate become "CANCELLED". And, if we re-load the same image, the loadstate revived as "LOADING". Without MASK_CANCELLED state, that image will send ApplyMask one more times. That mean, alpha mask applied double times. This patch seperate the cancelled situation so we can revive the loadstate well. + Add some more informations for log Change-Id: I055bb9807d2c1afe7192daa29aca08cd47910968 Signed-off-by: Eunki, Hong --- .../src/dali-toolkit/utc-Dali-ImageView.cpp | 68 ++++++++++++++++++++++ .../texture-manager/texture-cache-manager.cpp | 15 +++-- .../texture-manager/texture-manager-impl.cpp | 35 ++++++++--- .../texture-manager/texture-manager-type.h | 1 + 4 files changed, 107 insertions(+), 12 deletions(-) diff --git a/automated-tests/src/dali-toolkit/utc-Dali-ImageView.cpp b/automated-tests/src/dali-toolkit/utc-Dali-ImageView.cpp index 34aa8a3..dbd84e6 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-ImageView.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-ImageView.cpp @@ -1274,6 +1274,74 @@ int UtcDaliImageViewReplaceImage(void) END_TEST; } +int UtcDaliImageViewReloadAlphaMaskImage(void) +{ + ToolkitTestApplication application; + + gResourceReadySignalFired = false; + + ImageView dummy = ImageView::New(); + ImageView imageView = ImageView::New(); + Property::Map propertyMap; + + // To keep alpha mask cached, scene on some dummy image. + // Note : If we don't cache alpha mask image, the reference count of mask image become zero. + // In this case, we might need to wait mask image loading, which is not neccesary & can be changed behavior. + propertyMap[ImageVisual::Property::URL] = gImage_600_RGB; + propertyMap[ImageVisual::Property::ALPHA_MASK_URL] = TEST_BROKEN_IMAGE_DEFAULT; + dummy.SetProperty(ImageView::Property::IMAGE, propertyMap); + + application.GetScene().Add(dummy); + + application.SendNotification(); + application.Render(16); + + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(3), true, TEST_LOCATION); + + application.SendNotification(); + application.Render(16); + + propertyMap.Clear(); + propertyMap[ImageVisual::Property::URL] = gImage_34_RGBA; + propertyMap[ImageVisual::Property::ALPHA_MASK_URL] = TEST_BROKEN_IMAGE_DEFAULT; + imageView.SetProperty(ImageView::Property::IMAGE, propertyMap); + + DALI_TEST_EQUALS(imageView.IsResourceReady(), false, TEST_LOCATION); + + imageView.ResourceReadySignal().Connect(&ResourceReadySignal); + + application.GetScene().Add(imageView); + + application.SendNotification(); + application.Render(16); + + // Load image and use cached mask. Now we try to apply masking. + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION); + + DALI_TEST_EQUALS(gResourceReadySignalFired, false, TEST_LOCATION); + + // Cancel apply masking. + imageView.Unparent(); + + application.SendNotification(); + application.Render(16); + + // Reload same image again. + application.GetScene().Add(imageView); + + application.SendNotification(); + application.Render(16); + + // Finish apply masking. + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION); + + DALI_TEST_EQUALS(imageView.GetRendererCount(), 1u, TEST_LOCATION); + DALI_TEST_EQUALS(imageView.IsResourceReady(), true, TEST_LOCATION); + DALI_TEST_EQUALS(gResourceReadySignalFired, true, TEST_LOCATION); + + END_TEST; +} + void OnRelayoutOverride(Size size) { gNaturalSize = size; // Size Relayout is using diff --git a/dali-toolkit/internal/texture-manager/texture-cache-manager.cpp b/dali-toolkit/internal/texture-manager/texture-cache-manager.cpp index c0e7ac1..fc3ffde 100644 --- a/dali-toolkit/internal/texture-manager/texture-cache-manager.cpp +++ b/dali-toolkit/internal/texture-manager/texture-cache-manager.cpp @@ -43,6 +43,7 @@ extern Debug::Filter* gTextureManagerLogFilter; ///< Define at texture-manager-i 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 @@ -169,7 +170,7 @@ TextureCacheManager::LoadState TextureCacheManager::GetTextureStateInternal(cons Texture TextureCacheManager::GetTexture(const TextureCacheManager::TextureId& textureId, uint32_t textureIndex) { - Texture texture; // empty handle + Texture texture; // empty handle TextureCacheIndex cacheIndex = GetCacheIndexFromId(textureId); switch(static_cast(cacheIndex.detailValue.type)) @@ -645,8 +646,8 @@ TextureCacheManager::TextureCacheIndex TextureCacheManager::AppendCache(const Te void TextureCacheManager::RemoveCache(TextureCacheManager::TextureInfo& textureInfo) { - TextureCacheIndex textureInfoIndex = GetCacheIndexFromId(textureInfo.textureId); - bool removeTextureInfo = false; + TextureCacheIndex textureInfoIndex = GetCacheIndexFromId(textureInfo.textureId); + bool removeTextureInfo = false; DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureCacheManager::Remove(textureId:%d) url:%s\n cacheIdx:%d loadState:%s reference count = %d\n", textureInfo.textureId, textureInfo.url.GetUrl().c_str(), textureInfoIndex.GetIndex(), GET_LOAD_STATE_STRING(textureInfo.loadState), textureInfo.referenceCount); @@ -665,12 +666,18 @@ void TextureCacheManager::RemoveCache(TextureCacheManager::TextureInfo& textureI } removeTextureInfo = true; } - else if(textureInfo.loadState == LoadState::LOADING || textureInfo.loadState == LoadState::MASK_APPLYING) + else if(textureInfo.loadState == LoadState::LOADING) { // We mark the textureInfo for removal. // Once the load has completed, this method will be called again. textureInfo.loadState = LoadState::CANCELLED; } + else if(textureInfo.loadState == LoadState::MASK_APPLYING) + { + // We mark the textureInfo for removal. + // Once the load has completed, this method will be called again. + textureInfo.loadState = LoadState::MASK_CANCELLED; + } else { // In other states, we are not waiting for a load so we are safe to remove the TextureInfo data. diff --git a/dali-toolkit/internal/texture-manager/texture-manager-impl.cpp b/dali-toolkit/internal/texture-manager/texture-manager-impl.cpp index 33405be..643fced 100644 --- a/dali-toolkit/internal/texture-manager/texture-manager-impl.cpp +++ b/dali-toolkit/internal/texture-manager/texture-manager-impl.cpp @@ -92,6 +92,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 @@ -551,7 +552,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 @@ -563,7 +564,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. @@ -582,9 +583,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; } @@ -625,6 +627,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. @@ -711,8 +721,8 @@ void TextureManager::Remove(const TextureManager::TextureId& textureId, TextureU { TextureManager::TextureId 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) + // 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) { if(textureInfo.maskTextureId != INVALID_TEXTURE_ID) { @@ -720,6 +730,8 @@ void TextureManager::Remove(const TextureManager::TextureId& textureId, TextureU } } + 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) { @@ -861,6 +873,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: @@ -974,7 +987,7 @@ void TextureManager::AsyncLoadComplete(const TextureManager::TextureId& textureI 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); @@ -1117,6 +1130,8 @@ void TextureManager::CheckForWaitingTexture(TextureManager::TextureInfo& maskTex UploadTextures(pixelBuffers, maskTextureInfo); } + 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(); @@ -1155,10 +1170,12 @@ void TextureManager::CheckForWaitingTexture(TextureManager::TextureInfo& maskTex 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"); @@ -1172,6 +1189,8 @@ void TextureManager::CheckForWaitingTexture(TextureManager::TextureInfo& maskTex 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); } } diff --git a/dali-toolkit/internal/texture-manager/texture-manager-type.h b/dali-toolkit/internal/texture-manager/texture-manager-type.h index adffcf9..74057fc 100644 --- a/dali-toolkit/internal/texture-manager/texture-manager-type.h +++ b/dali-toolkit/internal/texture-manager/texture-manager-type.h @@ -201,6 +201,7 @@ enum class LoadState MASK_APPLIED, ///< Loading has finished, Mask is applyied by GPU UPLOADED, ///< Uploaded and ready. (For GPU upload only) CANCELLED, ///< Removed before loading completed + MASK_CANCELLED, ///< Removed before mask applying completed LOAD_FAILED ///< Async loading failed, e.g. connection problem }; -- 2.7.4