From: Eunki, Hong Date: Fri, 23 Sep 2022 04:48:41 +0000 (+0900) Subject: Fix maskTextureId remove issue X-Git-Tag: dali_2.1.42~4 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=23637864bea71fcf6ce78c2a194b3cc203ccd9f9 Fix maskTextureId remove issue After remove maskTextureInfo at TextureCacheManager, original textureInfo reference can be broken. This patch make validate the textureInfo's reference well. Change-Id: I69e83bff5da237fe0a0ff66ce892de0f5e6ddb58 Signed-off-by: Eunki, Hong --- diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextureManager.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextureManager.cpp index 5f82a5c..c80d1b5 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextureManager.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextureManager.cpp @@ -54,8 +54,9 @@ void utc_dali_toolkit_texture_manager_cleanup(void) namespace { -const char* TEST_IMAGE_FILE_NAME = TEST_RESOURCE_DIR "/gallery-small-1.jpg"; -const char* TEST_MASK_FILE_NAME = TEST_RESOURCE_DIR "/mask.png"; +const char* TEST_IMAGE_FILE_NAME = TEST_RESOURCE_DIR "/gallery-small-1.jpg"; +const char* TEST_IMAGE_2_FILE_NAME = TEST_RESOURCE_DIR "/icon-delete.png"; +const char* TEST_MASK_FILE_NAME = TEST_RESOURCE_DIR "/mask.png"; class TestObserver : public Dali::Toolkit::TextureUploadObserver { @@ -1034,7 +1035,7 @@ int UtcTextureManagerAsyncSyncAsync(void) Texture asyncTexture2 = asyncTextureSet2.GetTexture(0u); DALI_TEST_CHECK(syncTexture); DALI_TEST_CHECK(asyncTexture2); - DALI_TEST_CHECK(asyncTexture2 == syncTexture); // check loaded two texture is same. + DALI_TEST_CHECK(asyncTexture2 == syncTexture); // check loaded two texture is same. // observer is called synchronously because the texture is cached. DALI_TEST_EQUALS(asyncObserver2.mLoaded, true, TEST_LOCATION); @@ -1216,3 +1217,162 @@ int UtcTextureManagerRemoveDuringApplyMasking(void) END_TEST; } + +int UtcTextureManagerMaskCacheTest(void) +{ + ToolkitTestApplication application; + tet_infoline("UtcTextureManagerMaskCacheTest"); + + TextureManager textureManager; // Create new texture manager + + TestObserver observer1; + TestObserver observer2; + + std::string filename(TEST_IMAGE_FILE_NAME); + std::string filename2(TEST_IMAGE_2_FILE_NAME); + std::string maskname(TEST_MASK_FILE_NAME); + TextureManager::MaskingDataPointer maskInfo = nullptr; + maskInfo.reset(new TextureManager::MaskingData()); + maskInfo->mAlphaMaskUrl = maskname; + maskInfo->mAlphaMaskId = TextureManager::INVALID_TEXTURE_ID; + maskInfo->mCropToMask = true; + maskInfo->mContentScaleFactor = 1.0f; + + TextureManager::MaskingDataPointer maskInfo2 = nullptr; + maskInfo2.reset(new TextureManager::MaskingData()); + maskInfo2->mAlphaMaskUrl = maskname; + maskInfo2->mAlphaMaskId = TextureManager::INVALID_TEXTURE_ID; + maskInfo2->mCropToMask = true; + maskInfo2->mContentScaleFactor = 1.0f; + + auto textureId1(TextureManager::INVALID_TEXTURE_ID); + auto textureId2(TextureManager::INVALID_TEXTURE_ID); + Vector4 atlasRect(0.f, 0.f, 1.f, 1.f); + Dali::ImageDimensions atlasRectSize(0, 0); + bool synchronousLoading(false); + bool atlasingStatus(false); + bool loadingStatus(false); + auto preMultiply = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY; + ImageAtlasManagerPtr atlasManager = nullptr; + Toolkit::AtlasUploadObserver* atlasUploadObserver = nullptr; + + textureManager.LoadTexture( + filename, + ImageDimensions(), + FittingMode::SCALE_TO_FILL, + SamplingMode::BOX_THEN_LINEAR, + maskInfo, + synchronousLoading, + textureId1, + atlasRect, + atlasRectSize, + atlasingStatus, + loadingStatus, + &observer1, + atlasUploadObserver, + atlasManager, + true, + TextureManager::ReloadPolicy::CACHED, + preMultiply); + + DALI_TEST_EQUALS(observer1.mLoaded, false, TEST_LOCATION); + DALI_TEST_EQUALS(observer1.mObserverCalled, false, TEST_LOCATION); + + application.SendNotification(); + application.Render(); + + // Load image and mask image. + // Now, LoadState become MASK_APPLYING + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION); + + tet_printf("Current textureId1:%d's state become MASK_APPLYING\n", static_cast(textureId1)); + + textureManager.LoadTexture( + filename2, + ImageDimensions(), + FittingMode::SCALE_TO_FILL, + SamplingMode::BOX_THEN_LINEAR, + maskInfo2, + synchronousLoading, + textureId2, + atlasRect, + atlasRectSize, + atlasingStatus, + loadingStatus, + &observer2, + atlasUploadObserver, + atlasManager, + true, + TextureManager::ReloadPolicy::CACHED, + preMultiply); + + application.SendNotification(); + application.Render(); + + // Load image2 + image1 apply mask + image2 apply mask = total 3 event trigger required. + // Note that we use cached mask image. + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(3), true, TEST_LOCATION); + + DALI_TEST_EQUALS(observer1.mLoaded, true, TEST_LOCATION); + DALI_TEST_EQUALS(observer1.mObserverCalled, true, TEST_LOCATION); + DALI_TEST_EQUALS(observer2.mLoaded, true, TEST_LOCATION); + DALI_TEST_EQUALS(observer2.mObserverCalled, true, TEST_LOCATION); + + try + { + // Remove textureId1 first, and then remove textureId2. Check whether segfault occured. + textureManager.Remove(textureId1, &observer1); + textureManager.Remove(textureId2, &observer2); + + TestObserver observer3; + maskInfo.reset(new TextureManager::MaskingData()); + maskInfo->mAlphaMaskUrl = maskname; + maskInfo->mAlphaMaskId = TextureManager::INVALID_TEXTURE_ID; + maskInfo->mCropToMask = true; + maskInfo->mContentScaleFactor = 1.0f; + + textureManager.LoadTexture( + filename, + ImageDimensions(), + FittingMode::SCALE_TO_FILL, + SamplingMode::BOX_THEN_LINEAR, + maskInfo, + synchronousLoading, + textureId1, + atlasRect, + atlasRectSize, + atlasingStatus, + loadingStatus, + &observer3, + atlasUploadObserver, + atlasManager, + true, + TextureManager::ReloadPolicy::CACHED, + preMultiply); + + DALI_TEST_EQUALS(observer3.mLoaded, false, TEST_LOCATION); + DALI_TEST_EQUALS(observer3.mObserverCalled, false, TEST_LOCATION); + + application.SendNotification(); + application.Render(); + + // Load image and mask image. + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION); + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION); + + DALI_TEST_EQUALS(observer3.mLoaded, false, TEST_LOCATION); + DALI_TEST_EQUALS(observer3.mObserverCalled, false, TEST_LOCATION); + + // Apply mask. + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION); + + DALI_TEST_EQUALS(observer3.mLoaded, true, TEST_LOCATION); + DALI_TEST_EQUALS(observer3.mObserverCalled, true, TEST_LOCATION); + } + catch(...) + { + DALI_TEST_CHECK(false); + } + + END_TEST; +} diff --git a/dali-toolkit/internal/texture-manager/texture-manager-impl.cpp b/dali-toolkit/internal/texture-manager/texture-manager-impl.cpp index 0c89aad..f761781 100644 --- a/dali-toolkit/internal/texture-manager/texture-manager-impl.cpp +++ b/dali-toolkit/internal/texture-manager/texture-manager-impl.cpp @@ -37,8 +37,8 @@ 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 TEXTURE_INDEX = 0u; ///< The Index for texture -constexpr auto MASK_TEXTURE_INDEX = 1u; ///< The Index for mask texture +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"; @@ -710,7 +710,7 @@ void TextureManager::Remove(const TextureManager::TextureId& textureId, TextureU if(textureCacheIndex != INVALID_CACHE_INDEX) { TextureManager::TextureId maskTextureId = INVALID_TEXTURE_ID; - TextureInfo& textureInfo(mTextureCacheManager[textureCacheIndex]); + TextureInfo& textureInfo(mTextureCacheManager[textureCacheIndex]); if(textureInfo.maskTextureId != INVALID_TEXTURE_ID) { maskTextureId = textureInfo.maskTextureId; @@ -741,6 +741,12 @@ void TextureManager::Remove(const TextureManager::TextureId& textureId, TextureU // Remove its observer RemoveTextureObserver(textureInfo, observer); + // Keep loadState due to the textureInfo validate problem. + auto textureLoadState = textureInfo.loadState; + + // Remove textureId in CacheManager + mTextureCacheManager.RemoveCache(textureInfo); + // Remove maskTextureId in CacheManager if(maskTextureId != INVALID_TEXTURE_ID) { @@ -750,15 +756,12 @@ void TextureManager::Remove(const TextureManager::TextureId& textureId, TextureU TextureInfo& maskTextureInfo(mTextureCacheManager[maskCacheIndex]); // Only Remove maskTexture when texture's loadState is not CANCELLED. because it is already deleted. - if(textureInfo.loadState != LoadState::CANCELLED) + if(textureLoadState != LoadState::CANCELLED) { mTextureCacheManager.RemoveCache(maskTextureInfo); } } } - - // Remove textureId in CacheManager - mTextureCacheManager.RemoveCache(textureInfo); } } @@ -1210,7 +1213,7 @@ void TextureManager::UploadTextures(std::vector& pixelBuffer 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.textures.push_back(texture); @@ -1346,7 +1349,7 @@ void TextureManager::EmitLoadComplete(TextureUploadObserver* observer, TextureMa TextureSet TextureManager::GetTextureSet(const TextureManager::TextureId& textureId) { - TextureSet textureSet; + TextureSet textureSet; TextureManager::LoadState loadState = mTextureCacheManager.GetTextureStateInternal(textureId); if(loadState == TextureManager::LoadState::UPLOADED) { @@ -1406,8 +1409,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.