[Tizen] Remove observer from mLoadQueue when we request to remove observer 65/300765/1 accepted/tizen/7.0/unified/20231103.165436 accepted/tizen/7.0/unified/20231116.025850
authorEunki, Hong <eunkiki.hong@samsung.com>
Wed, 1 Nov 2023 04:18:13 +0000 (13:18 +0900)
committerEunki, Hong <eunkiki.hong@samsung.com>
Thu, 2 Nov 2023 02:22:52 +0000 (11:22 +0900)
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.

TODO : Make UTC

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 5797b880ec493e420e38f0d9d14408a8cbf0137d..6d169330f2b883a4d7976fa7a783df1ca6521396 100644 (file)
@@ -3679,6 +3679,34 @@ void OnResourceReadySignal07(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)
@@ -4216,6 +4244,82 @@ int UtcDaliImageViewSetImageOnResourceReadySignal07(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");
@@ -4347,7 +4451,6 @@ int UtcDaliImageViewNpatchImageCacheTest02(void)
     map[Toolkit::Visual::Property::TYPE]        = Toolkit::Visual::N_PATCH;
     map[Toolkit::ImageVisual::Property::URL]    = normalImageUrl;
     map[Toolkit::ImageVisual::Property::BORDER] = border;
-
     imageView[index] = ImageView::New();
     imageView[index].SetProperty(Toolkit::ImageView::Property::IMAGE, map);
     imageView[index].SetProperty(Actor::Property::SIZE, Vector2(100.0f, 200.0f));
index 73d342f5c9924375d3e44b046922ebb4c638f629..1de41058db471ddc7bde41991a53d49358f7ea9f 100644 (file)
@@ -605,7 +605,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;
     }
   }
 
@@ -928,6 +928,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));
 
@@ -1415,6 +1417,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;
     }
@@ -1516,6 +1519,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;
+        }
+      }
+    }
   }
 }