Remove observer from mLoadQueue when we request to remove observer 06/300706/4
authorEunki, Hong <eunkiki.hong@samsung.com>
Wed, 1 Nov 2023 04:18:13 +0000 (13:18 +0900)
committerEunki Hong <eunkiki.hong@samsung.com>
Mon, 6 Nov 2023 02:35:01 +0000 (02:35 +0000)
That might be happen during ResourceReady signal observing

- Add
- Remove

If than, the added request added in mLoadQueue 2 times.
and Remove request try to remove observe there (but will be failed actually.)

So, the visual get LoadCompleted signal twice.

It might have some logical problem in AnimatedImageVisual.
So let we keep ensure that 1-observer can only emit only 1-time.

Change-Id: I3eee087118cf62761709b8416fe09cf52094d156
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
automated-tests/src/dali-toolkit/utc-Dali-ImageView.cpp
dali-toolkit/internal/texture-manager/texture-manager-impl.cpp

index 2f2901f..7448eba 100644 (file)
@@ -3773,6 +3773,34 @@ void OnResourceReadySignal10(Control control)
   }
 }
 
+void OnResourceReadySignal11(Control control)
+{
+  gResourceReadySignalCounter++;
+
+  if(!gImageView2)
+  {
+    auto scene = gImageView1.GetParent();
+
+    // Try to load animated image visual here which is already cached, and then ignore forcely.
+
+    Property::Map map1;
+    map1[Toolkit::ImageVisual::Property::URL] = TEST_GIF_FILE_NAME;
+
+    gImageView2 = ImageView::New();
+    gImageView2.SetProperty(Toolkit::ImageView::Property::IMAGE, map1);
+
+    gImageView3 = ImageView::New();
+    gImageView3.SetProperty(Toolkit::ImageView::Property::IMAGE, map1);
+
+    scene.Add(gImageView2);
+    gImageView2.Unparent();
+
+    scene.Add(gImageView3);
+    gImageView3.Unparent();
+    gImageView3.Reset(); // Destroy visual
+  }
+}
+
 } // namespace
 
 int UtcDaliImageViewSetImageOnResourceReadySignal01(void)
@@ -4617,6 +4645,82 @@ int UtcDaliImageViewSetImageOnResourceReadySignal10(void)
   END_TEST;
 }
 
+int UtcDaliImageViewSetImageOnResourceReadySignal11(void)
+{
+  tet_infoline("Test ResourceReady Add AnimatedImageVisual and then Remove immediately.");
+
+  ToolkitTestApplication application;
+
+  gResourceReadySignalCounter = 0;
+
+  // Clear image view for clear test
+
+  if(gImageView1)
+  {
+    gImageView1.Reset();
+  }
+  if(gImageView2)
+  {
+    gImageView2.Reset();
+  }
+  if(gImageView3)
+  {
+    gImageView3.Reset();
+  }
+
+  try
+  {
+    gImageView1 = ImageView::New();
+    gImageView1.SetProperty(Toolkit::ImageView::Property::IMAGE, TEST_GIF_FILE_NAME);
+    gImageView1.ResourceReadySignal().Connect(&OnResourceReadySignal11);
+    application.GetScene().Add(gImageView1); // It will call resourceReady signal 1 time.
+
+    tet_printf("ResourceReady called %d times\n", gResourceReadySignalCounter);
+
+    DALI_TEST_EQUALS(gResourceReadySignalCounter, 0, TEST_LOCATION);
+
+    application.SendNotification();
+    application.Render();
+
+    // Load gImageView1
+    DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+
+    tet_printf("ResourceReady called %d times\n", gResourceReadySignalCounter);
+
+    DALI_TEST_EQUALS(gResourceReadySignalCounter, 1, TEST_LOCATION);
+
+    DALI_TEST_CHECK(true);
+  }
+  catch(...)
+  {
+    // Exception should not happened
+    DALI_TEST_CHECK(false);
+  }
+
+  // Clear cache.
+  application.SendNotification();
+  application.Render();
+
+  gResourceReadySignalCounter = 0;
+
+  // Clear image view for clear test
+
+  if(gImageView1)
+  {
+    gImageView1.Reset();
+  }
+  if(gImageView2)
+  {
+    gImageView2.Reset();
+  }
+  if(gImageView3)
+  {
+    gImageView3.Reset();
+  }
+
+  END_TEST;
+}
+
 int UtcDaliImageViewUseSameUrlWithAnimatedImageVisual(void)
 {
   tet_infoline("Test multiple views with same image in animated image visual");
index 0dceae2..0c3e3dd 100644 (file)
@@ -585,7 +585,7 @@ TextureManager::TextureId TextureManager::RequestLoadInternal(
     if(textureInfo.loadState != LoadState::UPLOADED)
     {
       textureInfo.preMultiplied = (preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD);
-      textureInfo.loadState = TextureManager::LoadState::WAITING_FOR_MASK;
+      textureInfo.loadState     = TextureManager::LoadState::WAITING_FOR_MASK;
     }
   }
 
@@ -939,6 +939,8 @@ void TextureManager::LoadOrQueueTexture(TextureManager::TextureInfo& textureInfo
 
 void TextureManager::QueueLoadTexture(const TextureManager::TextureInfo& textureInfo, TextureUploadObserver* observer)
 {
+  DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Verbose, "Add observer to observer queue (textureId:%d, observer:%p)\n", textureInfo.textureId, observer);
+
   const auto& textureId = textureInfo.textureId;
   mLoadQueue.PushBack(QueueElement(textureId, observer));
 
@@ -1413,6 +1415,7 @@ void TextureManager::ObserverDestroyed(TextureUploadObserver* observer)
   {
     if(element.mObserver == observer)
     {
+      DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Verbose, "Remove observer from observer queue (textureId:%d, observer:%p)\n", element.mTextureId, element.mObserver);
       element.mTextureId = INVALID_TEXTURE_ID;
       element.mObserver  = nullptr;
     }
@@ -1515,6 +1518,22 @@ void TextureManager::RemoveTextureObserver(TextureManager::TextureInfo& textureI
       observer->DestructionSignal().Disconnect(this, &TextureManager::ObserverDestroyed);
       textureInfo.observerList.Erase(iter);
     }
+    else
+    {
+      // Given textureId might exist at load queue.
+      // Remove observer from the LoadQueue
+      for(auto&& element : mLoadQueue)
+      {
+        if(element.mTextureId == textureInfo.textureId && element.mObserver == observer)
+        {
+          DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Verbose, "Remove observer from observer queue (textureId:%d, observer:%p)\n", element.mTextureId, element.mObserver);
+          DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Verbose, "  Disconnect DestructionSignal to observer:%p\n", observer);
+          observer->DestructionSignal().Disconnect(this, &TextureManager::ObserverDestroyed);
+          element.mObserver = nullptr;
+          break;
+        }
+      }
+    }
   }
 }