Reload ImageVisual texture on visual size updates 11/312611/8
authorjmm <j0064423.lee@samsung.com>
Wed, 12 Jun 2024 08:14:21 +0000 (17:14 +0900)
committerjmm <j0064423.lee@samsung.com>
Wed, 24 Jul 2024 06:59:28 +0000 (15:59 +0900)
Change-Id: I4135b0fb427b7fff2319079389050d91e38556a7

automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp
dali-toolkit/devel-api/visuals/image-visual-properties-devel.h
dali-toolkit/internal/visuals/image/image-visual.cpp
dali-toolkit/internal/visuals/image/image-visual.h
dali-toolkit/internal/visuals/visual-string-constants.cpp
dali-toolkit/internal/visuals/visual-string-constants.h

index 01d5b21..62df55a 100644 (file)
@@ -4299,4 +4299,109 @@ int UtcDaliImageVisualDebugImageVisualShaderN2(void)
   DALI_TEST_EQUALS(textureTrace.CountMethod("GenTextures"), 1, TEST_LOCATION);
 
   END_TEST;
-}
\ No newline at end of file
+}
+
+int UtcDaliImageVisualSynchronousSizing01(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("UtcDaliImageVisualSynchronousSizing01");
+
+  Vector2  size   = Vector2(64.0f, 64.0f);
+  uint32_t width  = 64;
+  uint32_t height = 64;
+
+  Property::Map imagePropertyMap;
+  imagePropertyMap.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE);
+  imagePropertyMap.Insert(Toolkit::ImageVisual::Property::URL, TEST_IMAGE_FILE_NAME);
+  imagePropertyMap.Insert(Toolkit::DevelImageVisual::Property::SYNCHRONOUS_SIZING, true);
+
+  Toolkit::ImageView imageView = Toolkit::ImageView::New();
+  imageView.SetProperty(Toolkit::ImageView::Property::IMAGE, imagePropertyMap);
+  imageView.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+  imageView.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
+  imageView.SetProperty(Actor::Property::SIZE, size);
+
+  DALI_TEST_EQUALS(imageView.GetRendererCount(), 0u, TEST_LOCATION);
+
+  application.GetScene().Add(imageView);
+
+  // Wait for image loading(1)
+  // (Texture size is its original size, not the actor size.)
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(imageView.GetRendererCount(), 1u, TEST_LOCATION);
+
+  // Set size again
+  imageView.SetProperty(Actor::Property::SIZE, size);
+
+  // Wait for image loading(2)
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+
+  // Check (reloaded image texture size == actor size)
+  Renderer   renderer = imageView.GetRendererAt(0);
+  TextureSet textures = renderer.GetTextures();
+  DALI_TEST_EQUALS(textures.GetTextureCount(), 1u, TEST_LOCATION);
+
+  Texture texture = textures.GetTexture(0);
+  DALI_TEST_EQUALS(texture.GetWidth(), width, TEST_LOCATION);
+  DALI_TEST_EQUALS(texture.GetHeight(), height, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliImageVisualSynchronousSizing02(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("UtcDaliImageVisualSynchronousSizing02");
+
+  Property::Map imagePropertyMap;
+  imagePropertyMap.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE);
+  imagePropertyMap.Insert(Toolkit::ImageVisual::Property::URL, TEST_IMAGE_FILE_NAME);
+  imagePropertyMap.Insert(Toolkit::DevelImageVisual::Property::SYNCHRONOUS_SIZING, true);
+
+  VisualFactory factory = VisualFactory::Get();
+  DALI_TEST_CHECK(factory);
+
+  Visual::Base visual = factory.CreateVisual(imagePropertyMap);
+
+  Vector2 size;
+
+  TestGlAbstraction& gl           = application.GetGlAbstraction();
+  TraceCallStack&    textureTrace = gl.GetTextureTrace();
+  textureTrace.Enable(true);
+
+  DummyControl      actor     = DummyControl::New();
+  DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(actor.GetImplementation());
+  dummyImpl.RegisterVisual(Control::CONTROL_PROPERTY_END_INDEX + 1, visual);
+
+  actor.SetProperty(Actor::Property::SIZE, Vector2(200.f, 200.f)); // set size(1), no renderer yet
+  DALI_TEST_EQUALS(actor.GetRendererCount(), 0u, TEST_LOCATION);
+  DALI_TEST_EQUALS(actor.IsResourceReady(), false, TEST_LOCATION);
+
+  application.GetScene().Add(actor);
+  application.SendNotification();
+  application.Render(); // require to load size(1)
+
+  actor.SetProperty(Actor::Property::SIZE, Vector2(100.f, 100.f)); // set size(2), no renderer yet
+  visual.GetNaturalSize(size);                                     // get size(1)
+  DALI_TEST_EQUALS(size, Vector2(200.0f, 200.0f), 0.001f, TEST_LOCATION);
+
+  // load image
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(2), true, TEST_LOCATION);
+
+  application.SendNotification();
+  application.Render(); // require to load size(2)
+
+  // reload image
+  DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+
+  visual.GetNaturalSize(size); // get size(2)
+  DALI_TEST_EQUALS(size, Vector2(100.0f, 100.0f), 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(actor.GetRendererCount(), 1u, TEST_LOCATION);
+  DALI_TEST_EQUALS(textureTrace.FindMethod("BindTexture"), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(actor.IsResourceReady(), true, TEST_LOCATION);
+
+  END_TEST;
+}
index 90e868e..500f86e 100644 (file)
@@ -210,7 +210,15 @@ enum Type
    * This flag is useful if given resource has low fps, so we don't need to render every frame.
    * @note It is used in the AnimatedVectorImageVisual. The default is false.
    */
-  NOTIFY_AFTER_RASTERIZATION = ORIENTATION_CORRECTION + 17
+  NOTIFY_AFTER_RASTERIZATION = ORIENTATION_CORRECTION + 17,
+
+  /**
+   * @brief Whether to synchronize image texture size to visual size.
+   * @details Name "synchronousSizing", type Property::BOOLEAN.
+   * If this property is true, ImageVisual ignores mDesiredSize.
+   * @note Used by the ImageVisual. The default is false.
+   */
+  SYNCHRONOUS_SIZING = ORIENTATION_CORRECTION + 18
 };
 
 } //namespace Property
index 147e617..c8c7375 100644 (file)
@@ -188,6 +188,7 @@ ImageVisual::ImageVisual(VisualFactoryCache&       factoryCache,
   mImageUrl(imageUrl),
   mMaskingData(),
   mDesiredSize(size),
+  mLastRequiredSize(size),
   mTextureId(TextureManager::INVALID_TEXTURE_ID),
   mTextures(),
   mImageVisualShaderFactory(shaderFactory),
@@ -263,8 +264,9 @@ void ImageVisual::DoSetProperties(const Property::Map& propertyMap)
   // Load image immediately if LOAD_POLICY requires it
   if(mLoadPolicy == Toolkit::ImageVisual::LoadPolicy::IMMEDIATE)
   {
-    auto attemptAtlasing = AttemptAtlasing();
-    LoadTexture(attemptAtlasing, mAtlasRect, mTextures, mOrientationCorrection, TextureManager::ReloadPolicy::CACHED);
+    Dali::ImageDimensions size            = mUseSynchronousSizing ? mLastRequiredSize : mDesiredSize;
+    auto                  attemptAtlasing = AttemptAtlasing();
+    LoadTexture(attemptAtlasing, mAtlasRect, mTextures, size, TextureManager::ReloadPolicy::CACHED);
   }
 }
 
@@ -457,6 +459,12 @@ void ImageVisual::DoSetProperty(Property::Index index, const Property::Value& va
       value.Get(mUseFastTrackUploading);
       break;
     }
+
+    case Toolkit::DevelImageVisual::Property::SYNCHRONOUS_SIZING:
+    {
+      value.Get(mUseSynchronousSizing);
+      break;
+    }
   }
 }
 
@@ -474,7 +482,30 @@ void ImageVisual::AllocateMaskData()
 
 void ImageVisual::GetNaturalSize(Vector2& naturalSize)
 {
-  if(mDesiredSize.GetWidth() > 0 && mDesiredSize.GetHeight() > 0)
+  if(mUseSynchronousSizing && (mLastRequiredSize.GetWidth() > 0 && mLastRequiredSize.GetHeight() > 0))
+  {
+    if(mImpl->mRenderer)
+    {
+      auto textureSet = mImpl->mRenderer.GetTextures();
+      if(textureSet && textureSet.GetTextureCount())
+      {
+        auto texture = textureSet.GetTexture(0);
+        if(texture)
+        {
+          if(mTextureSize != Vector2::ZERO)
+          {
+            naturalSize = mTextureSize;
+            return;
+          }
+        }
+      }
+    }
+
+    naturalSize.x = mLastRequiredSize.GetWidth();
+    naturalSize.y = mLastRequiredSize.GetHeight();
+    return;
+  }
+  else if(mDesiredSize.GetWidth() > 0 && mDesiredSize.GetHeight() > 0)
   {
     if(mImpl->mRenderer)
     {
@@ -596,10 +627,12 @@ void ImageVisual::OnInitialize()
   }
 }
 
-void ImageVisual::LoadTexture(bool& atlasing, Vector4& atlasRect, TextureSet& textures, bool orientationCorrection, TextureManager::ReloadPolicy forceReload)
+void ImageVisual::LoadTexture(bool& atlasing, Vector4& atlasRect, TextureSet& textures, const Dali::ImageDimensions& size, TextureManager::ReloadPolicy forceReload)
 {
   TextureManager& textureManager = mFactoryCache.GetTextureManager();
 
+  mLastRequiredSize = size;
+
   ImageAtlasManagerPtr atlasManager        = nullptr;
   AtlasUploadObserver* atlasUploadObserver = nullptr;
   auto                 textureObserver     = this;
@@ -643,6 +676,7 @@ void ImageVisual::LoadTexture(bool& atlasing, Vector4& atlasRect, TextureSet& te
        forceReload == TextureManager::ReloadPolicy::CACHED &&
        (mImageUrl.GetProtocolType() == VisualUrl::LOCAL || mImageUrl.GetProtocolType() == VisualUrl::REMOTE) &&
        !synchronousLoading &&
+       !mUseSynchronousSizing &&
        !atlasing &&
        !mImpl->mCustomShader &&
        !(mMaskingData && mMaskingData->mAlphaMaskUrl.IsValid()))
@@ -651,13 +685,14 @@ void ImageVisual::LoadTexture(bool& atlasing, Vector4& atlasRect, TextureSet& te
     }
     else if(mUseFastTrackUploading)
     {
-      DALI_LOG_DEBUG_INFO("FastTrack : Fail to load fast track. mUrl : [%s]%s%s%s%s%s%s%s%s\n",
+      DALI_LOG_DEBUG_INFO("FastTrack : Fail to load fast track. mUrl : [%s]%s%s%s%s%s%s%s%s%s\n",
                           mImageUrl.GetEllipsedUrl().c_str(),
                           (mLoadPolicy != Toolkit::ImageVisual::LoadPolicy::ATTACHED) ? "/ mLoadPolicy != ATTACHED" : "",
                           (mReleasePolicy != Toolkit::ImageVisual::ReleasePolicy::DETACHED) ? "/ mReleasePolicy != DETACHED" : "",
                           (forceReload != TextureManager::ReloadPolicy::CACHED) ? "/ forceReload != CACHED" : "",
                           (!(mImageUrl.GetProtocolType() == VisualUrl::LOCAL || mImageUrl.GetProtocolType() == VisualUrl::REMOTE)) ? "/ url is not image" : "",
                           (synchronousLoading) ? "/ synchronousLoading" : "",
+                          (mUseSynchronousSizing) ? "/ useSynchronousSizing " : "",
                           (atlasing) ? "/ atlasing" : "",
                           (mImpl->mCustomShader) ? "/ use customs shader" : "",
                           (mMaskingData && mMaskingData->mAlphaMaskUrl.IsValid()) ? "/ use masking url" : "");
@@ -671,7 +706,7 @@ void ImageVisual::LoadTexture(bool& atlasing, Vector4& atlasRect, TextureSet& te
     EnablePreMultipliedAlpha(preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD);
 
     // Set new TextureSet with fast track loading task
-    mFastTrackLoadingTask = new FastTrackLoadingTask(mImageUrl, mDesiredSize, mFittingMode, mSamplingMode, mOrientationCorrection, preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD ? DevelAsyncImageLoader::PreMultiplyOnLoad::ON : DevelAsyncImageLoader::PreMultiplyOnLoad::OFF, mFactoryCache.GetLoadYuvPlanes(), MakeCallback(this, &ImageVisual::FastLoadComplete));
+    mFastTrackLoadingTask = new FastTrackLoadingTask(mImageUrl, size, mFittingMode, mSamplingMode, mOrientationCorrection, preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD ? DevelAsyncImageLoader::PreMultiplyOnLoad::ON : DevelAsyncImageLoader::PreMultiplyOnLoad::OFF, mFactoryCache.GetLoadYuvPlanes(), MakeCallback(this, &ImageVisual::FastLoadComplete));
 
     TextureSet textureSet = TextureSet::New();
     if(!mFastTrackLoadingTask->mLoadPlanesAvaliable)
@@ -699,7 +734,7 @@ void ImageVisual::LoadTexture(bool& atlasing, Vector4& atlasRect, TextureSet& te
   }
   else
   {
-    textures = textureManager.LoadTexture(mImageUrl, mDesiredSize, mFittingMode, mSamplingMode, mMaskingData, synchronousLoading, mTextureId, atlasRect, mAtlasRectSize, atlasing, loadingStatus, textureObserver, atlasUploadObserver, atlasManager, mOrientationCorrection, forceReload, preMultiplyOnLoad);
+    textures = textureManager.LoadTexture(mImageUrl, size, mFittingMode, mSamplingMode, mMaskingData, synchronousLoading, mTextureId, atlasRect, mAtlasRectSize, atlasing, loadingStatus, textureObserver, atlasUploadObserver, atlasManager, mOrientationCorrection, forceReload, preMultiplyOnLoad);
   }
 
   if(textures)
@@ -759,7 +794,7 @@ void ImageVisual::InitializeRenderer()
   {
     if(mTextureId == TextureManager::INVALID_TEXTURE_ID)
     {
-      LoadTexture(attemptAtlasing, mAtlasRect, mTextures, mOrientationCorrection, TextureManager::ReloadPolicy::CACHED);
+      LoadTexture(attemptAtlasing, mAtlasRect, mTextures, mDesiredSize, TextureManager::ReloadPolicy::CACHED);
     }
     else
     {
@@ -897,9 +932,11 @@ void ImageVisual::DoCreatePropertyMap(Property::Map& map) const
   map.Insert(Toolkit::ImageVisual::Property::SYNCHRONOUS_LOADING, sync);
   if(mImageUrl.IsValid())
   {
+    Dali::ImageDimensions size = mUseSynchronousSizing ? mLastRequiredSize : mDesiredSize;
+
     map.Insert(Toolkit::ImageVisual::Property::URL, mImageUrl.GetUrl());
-    map.Insert(Toolkit::ImageVisual::Property::DESIRED_WIDTH, mDesiredSize.GetWidth());
-    map.Insert(Toolkit::ImageVisual::Property::DESIRED_HEIGHT, mDesiredSize.GetHeight());
+    map.Insert(Toolkit::ImageVisual::Property::DESIRED_WIDTH, size.GetWidth());
+    map.Insert(Toolkit::ImageVisual::Property::DESIRED_HEIGHT, size.GetHeight());
   }
 
   map.Insert(Toolkit::ImageVisual::Property::FITTING_MODE, mFittingMode);
@@ -934,6 +971,7 @@ void ImageVisual::DoCreatePropertyMap(Property::Map& map) const
   map.Insert(Toolkit::ImageVisual::Property::ORIENTATION_CORRECTION, mOrientationCorrection);
 
   map.Insert(Toolkit::DevelImageVisual::Property::FAST_TRACK_UPLOADING, mUseFastTrackUploading);
+  map.Insert(Toolkit::DevelImageVisual::Property::SYNCHRONOUS_SIZING, mUseSynchronousSizing);
 }
 
 void ImageVisual::DoCreateInstancePropertyMap(Property::Map& map) const
@@ -942,8 +980,9 @@ void ImageVisual::DoCreateInstancePropertyMap(Property::Map& map) const
   map.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE);
   if(mImageUrl.IsValid())
   {
-    map.Insert(Toolkit::ImageVisual::Property::DESIRED_WIDTH, mDesiredSize.GetWidth());
-    map.Insert(Toolkit::ImageVisual::Property::DESIRED_HEIGHT, mDesiredSize.GetHeight());
+    Dali::ImageDimensions size = mUseSynchronousSizing ? mLastRequiredSize : mDesiredSize;
+    map.Insert(Toolkit::ImageVisual::Property::DESIRED_WIDTH, size.GetWidth());
+    map.Insert(Toolkit::ImageVisual::Property::DESIRED_HEIGHT, size.GetHeight());
   }
 }
 
@@ -961,7 +1000,8 @@ void ImageVisual::OnDoAction(const Dali::Property::Index actionId, const Dali::P
       ResourceReady(Toolkit::Visual::ResourceStatus::PREPARING);
       mLoadState = TextureManager::LoadState::NOT_STARTED;
 
-      LoadTexture(attemptAtlasing, mAtlasRect, mTextures, mOrientationCorrection, TextureManager::ReloadPolicy::FORCED);
+      Dali::ImageDimensions size = mUseSynchronousSizing ? mLastRequiredSize : mDesiredSize;
+      LoadTexture(attemptAtlasing, mAtlasRect, mTextures, size, TextureManager::ReloadPolicy::FORCED);
       break;
     }
   }
@@ -973,6 +1013,28 @@ void ImageVisual::OnSetTransform()
   {
     mImpl->mTransform.SetUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT);
   }
+
+  if(mUseSynchronousSizing)
+  {
+    // Get current visual size
+    Vector2  size                    = mImpl->mTransform.GetVisualSize(mImpl->mControlSize);
+    uint32_t maximumNumber           = std::numeric_limits<uint16_t>::max();
+    uint32_t sizeWidth               = static_cast<uint32_t>(roundf(size.width));
+    sizeWidth                        = std::min(sizeWidth, maximumNumber);
+    uint32_t sizeHeight              = static_cast<uint32_t>(roundf(size.height));
+    sizeHeight                       = std::min(sizeHeight, maximumNumber);
+    Dali::ImageDimensions visualSize = Dali::ImageDimensions(sizeWidth, sizeHeight);
+
+    // Reload if visual size is updated
+    if(mLastRequiredSize != visualSize)
+    {
+      RemoveTexture();
+
+      mLoadState           = TextureManager::LoadState::NOT_STARTED;
+      bool attemptAtlasing = AttemptAtlasing();
+      LoadTexture(attemptAtlasing, mAtlasRect, mTextures, visualSize, TextureManager::ReloadPolicy::FORCED);
+    }
+  }
 }
 
 void ImageVisual::UpdateShader()
index 445218b..dd1c6b1 100644 (file)
@@ -275,10 +275,10 @@ private:
    * @param[in, out] atlasing flag if the image has been put in a atlas (true), passing false will not atlas even if possible.
    * @param[out] atlasRect if atlasing is used this the texture area of the image in the atlas.
    * @param[out] textures resulting texture set from the image loading.
-   * @param[in] orientationCorrection flag determines if orientation correction should be performed
+   * @param[in] size if mUseSynchronousSizing is true this is the size of visual, else it is mDesiredSize
    * @param[in] forceReload flag determines if the texture should be reloaded from its source or use the cached texture.
    */
-  void LoadTexture(bool& atlasing, Vector4& atlasRect, TextureSet& textures, bool orientationCorrection, TextureManager::ReloadPolicy forceReload);
+  void LoadTexture(bool& atlasing, Vector4& atlasRect, TextureSet& textures, const Dali::ImageDimensions& size, TextureManager::ReloadPolicy forceReload);
 
   /**
    * @brief Checks if atlasing should be attempted
@@ -369,6 +369,7 @@ private:
   TextureManager::MaskingDataPointer mMaskingData;
 
   Dali::ImageDimensions     mDesiredSize;
+  Dali::ImageDimensions     mLastRequiredSize;
   TextureManager::TextureId mTextureId;
   TextureSet                mTextures;
   Vector2                   mTextureSize;
@@ -395,6 +396,7 @@ private:
   bool                                            mUseFastTrackUploading{false};  ///< True if we use fast tack feature.
   bool                                            mRendererAdded{false};          ///< True if renderer added into actor.
   bool                                            mUseBrokenImageRenderer{false}; ///< True if renderer changed as broken image.
+  bool                                            mUseSynchronousSizing{false};   ///< True if we need to synchronize image texture size to visual size, otherwise use mDesiredSize.
 };
 
 } // namespace Internal
index ae39540..d4df78c 100644 (file)
@@ -213,6 +213,7 @@ const char* const FAST_TRACK_UPLOADING_NAME("fastTrackUploading");
 const char* const ENABLE_BROKEN_IMAGE("enableBrokenImage");
 const char* const ENABLE_FRAME_CACHE("enableFrameCache");
 const char* const NOTIFY_AFTER_RASTERIZATION("notifyAfterRasterization");
+const char* const SYNCHRONOUS_SIZING("synchronousSizing");
 
 // Text visual
 const char* const TEXT_PROPERTY("text");
index 9835299..1e7eea9 100644 (file)
@@ -115,6 +115,7 @@ extern const char* const FAST_TRACK_UPLOADING_NAME;
 extern const char* const ENABLE_BROKEN_IMAGE;
 extern const char* const ENABLE_FRAME_CACHE;
 extern const char* const NOTIFY_AFTER_RASTERIZATION;
+extern const char* const SYNCHRONOUS_SIZING;
 
 // Text visual
 extern const char* const TEXT_PROPERTY;