Remove external resources lazy. 38/295838/2
authorjmm <j0064423.lee@samsung.com>
Fri, 14 Jul 2023 09:02:44 +0000 (18:02 +0900)
committerjmm <j0064423.lee@samsung.com>
Mon, 17 Jul 2023 04:37:43 +0000 (13:37 +0900)
Since we don't increase & decrease the reference count of ExternalResources during
LoadTexture() API, It can be happened that some TextureId validation failed.

For example of dali://2,

ImageUrl::New() // refcount : 1
ImageVisual::Initialize() // refcount : 2
~ImageVisual
 - RemoveExternalTexture("dali://2"); // refcount : 1
 - RequestRemove(2) // still refcount : 1
~ImageUrl // now, refcount : 0
ImageVisual()
LoadTexture() //< New generated texture will use TextureId as 2, with refcount 1

== Process() ==

Remove(2) // Now, TextureId 2's refcount is 0! load cancel.

This patch make we only remove normal texture cache, instead of ExternalResource

Change-Id: Ia735770a02c231fa79af40a1e5926aab11358b71
Signed-off-by: jmm <j0064423.lee@samsung.com>
automated-tests/src/dali-toolkit-internal/utc-Dali-TextureManager.cpp
dali-toolkit/internal/texture-manager/texture-manager-impl.cpp

index bd3d5ed..b9970b3 100644 (file)
@@ -583,6 +583,113 @@ int UtcTextureManagerExternalTexture(void)
   END_TEST;
 }
 
+int UtcTextureManagerRemoveExternalTextureAndLoadAgain(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("UtcTextureManagerRemoveExternalTextureAndLoadAgain check TextureManager RequestRemove and RemoveExternalTexture lifecycle works well");
+
+  auto  visualFactory  = Toolkit::VisualFactory::Get();
+  auto& textureManager = GetImplementation(visualFactory).GetTextureManager(); // Use VisualFactory's texture manager
+
+  TestObserver observer1;
+  TestObserver observer2;
+
+  auto                               textureId1(TextureManager::INVALID_TEXTURE_ID);
+  auto                               textureId2(TextureManager::INVALID_TEXTURE_ID);
+  TextureManager::MaskingDataPointer maskInfo = nullptr;
+
+  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;
+
+  uint32_t width(64);
+  uint32_t height(64);
+  uint32_t bufferSize = width * height * Pixel::GetBytesPerPixel(Pixel::RGBA8888);
+
+  uint8_t*  buffer    = reinterpret_cast<uint8_t*>(malloc(bufferSize));
+  PixelData pixelData = PixelData::New(buffer, bufferSize, width, height, Pixel::RGBA8888, PixelData::FREE);
+
+  DALI_TEST_CHECK(pixelData);
+
+  Dali::Toolkit::ImageUrl imageUrl = Dali::Toolkit::Image::GenerateUrl(pixelData, true);
+  std::string             url1     = imageUrl.GetUrl();
+  std::string             url2     = TEST_IMAGE_FILE_NAME;
+
+  // Step 1 : Load request for external url
+  TextureSet texture1 = textureManager.LoadTexture(
+    url1,
+    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_CHECK(textureId1 != TextureManager::INVALID_TEXTURE_ID);
+
+  // Step 2 : Request remove for external url
+  textureManager.RequestRemove(textureId1, &observer1);
+
+  // Step 3 : Reduce imageUrl reference count.
+  imageUrl.Reset();
+
+  // Step 4 : Request new load by normal image.
+  TextureSet texture2 = textureManager.LoadTexture(
+    url2,
+    ImageDimensions(),
+    FittingMode::SCALE_TO_FILL,
+    SamplingMode::BOX_THEN_LINEAR,
+    maskInfo,
+    synchronousLoading,
+    textureId2,
+    atlasRect,
+    atlasRectSize,
+    atlasingStatus,
+    loadingStatus,
+    &observer2,
+    atlasUploadObserver,
+    atlasManager,
+    true,
+    TextureManager::ReloadPolicy::CACHED,
+    preMultiply);
+
+  DALI_TEST_CHECK(textureId2 != TextureManager::INVALID_TEXTURE_ID);
+
+  DALI_TEST_EQUALS(observer1.mLoaded, false, TEST_LOCATION);
+  DALI_TEST_EQUALS(observer1.mObserverCalled, false, TEST_LOCATION);
+  DALI_TEST_EQUALS(observer2.mLoaded, false, TEST_LOCATION);
+  DALI_TEST_EQUALS(observer2.mObserverCalled, false, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(observer1.mLoaded, false, TEST_LOCATION);
+  DALI_TEST_EQUALS(observer1.mObserverCalled, false, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(observer2.mLoaded, true, TEST_LOCATION);
+  DALI_TEST_EQUALS(observer2.mObserverCalled, true, TEST_LOCATION);
+  DALI_TEST_EQUALS(observer2.mCompleteType, TestObserver::CompleteType::UPLOAD_COMPLETE, TEST_LOCATION);
+
+  END_TEST;
+}
+
 int UtcTextureManagerEncodedImageBufferReferenceCount(void)
 {
   ToolkitTestApplication application;
@@ -2166,4 +2273,4 @@ int UtcTextureManagerDestroyObserverDuringObserve(void)
   }
 
   END_TEST;
-}
\ No newline at end of file
+}
index 086ec56..b548e6c 100644 (file)
@@ -755,22 +755,23 @@ void TextureManager::RequestRemove(const TextureManager::TextureId& textureId, T
   // Queue to remove.
   if(textureId != INVALID_TEXTURE_ID)
   {
-    if(observer)
+    TextureCacheIndex textureCacheIndex = mTextureCacheManager.GetCacheIndexFromId(textureId);
+    if(textureCacheIndex != INVALID_CACHE_INDEX)
     {
-      // Remove observer from cached texture info
-      TextureCacheIndex textureCacheIndex = mTextureCacheManager.GetCacheIndexFromId(textureId);
-      if(textureCacheIndex != INVALID_CACHE_INDEX)
+      if(observer)
       {
+        // Remove observer from cached texture info
         TextureInfo& textureInfo(mTextureCacheManager[textureCacheIndex]);
         RemoveTextureObserver(textureInfo, observer);
       }
-    }
-    mRemoveQueue.PushBack(textureId);
 
-    if(!mRemoveProcessorRegistered && Adaptor::IsAvailable())
-    {
-      mRemoveProcessorRegistered = true;
-      Adaptor::Get().RegisterProcessor(*this, true);
+      mRemoveQueue.PushBack(textureId);
+
+      if(!mRemoveProcessorRegistered && Adaptor::IsAvailable())
+      {
+        mRemoveProcessorRegistered = true;
+        Adaptor::Get().RegisterProcessor(*this, true);
+      }
     }
   }
 }