Merge "Change conflict of some visual's Impl namespace" into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / image / image-visual.cpp
index 1c5f5e7..e3aa797 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -31,9 +31,9 @@
 
 // INTERNAL HEADERS
 #include <dali-toolkit/devel-api/visuals/image-visual-actions-devel.h>
+#include <dali-toolkit/internal/texture-manager/texture-manager-impl.h>
 #include <dali-toolkit/internal/visuals/image-atlas-manager.h>
 #include <dali-toolkit/internal/visuals/image-visual-shader-factory.h>
-#include <dali-toolkit/internal/visuals/texture-manager-impl.h>
 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
@@ -51,6 +51,8 @@ namespace Internal
 {
 namespace
 {
+const int CUSTOM_PROPERTY_COUNT(9); // wrap, pixel area, atlas, pixalign, + border/corner
+
 // fitting modes
 DALI_ENUM_TO_STRING_TABLE_BEGIN(FITTING_MODE)
   DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::FittingMode, SHRINK_TO_FIT)
@@ -187,6 +189,23 @@ ImageVisual::~ImageVisual()
       }
     }
 
+    if(mImageUrl.IsValid())
+    {
+      // Decrease reference count of External Resources :
+      // EncodedImageBuffer or ExternalTextures.
+      // Ensure the stage is still valid before accessing texture manager.
+      if(mImageUrl.GetProtocolType() == VisualUrl::TEXTURE)
+      {
+        TextureManager& textureManager = mFactoryCache.GetTextureManager();
+        textureManager.RemoveExternalTexture(mImageUrl.GetUrl());
+      }
+      else if(mImageUrl.IsBufferResource())
+      {
+        TextureManager& textureManager = mFactoryCache.GetTextureManager();
+        textureManager.RemoveEncodedImageBuffer(mImageUrl.GetUrl());
+      }
+    }
+
     // ImageVisual destroyed so remove texture unless ReleasePolicy is set to never release
     if((mTextureId != TextureManager::INVALID_TEXTURE_ID) && (mReleasePolicy != Toolkit::ImageVisual::ReleasePolicy::NEVER))
     {
@@ -288,11 +307,11 @@ void ImageVisual::DoSetProperty(Property::Index index, const Property::Value& va
       {
         if(sync)
         {
-          mImpl->mFlags |= Impl::IS_SYNCHRONOUS_RESOURCE_LOADING;
+          mImpl->mFlags |= Visual::Base::Impl::IS_SYNCHRONOUS_RESOURCE_LOADING;
         }
         else
         {
-          mImpl->mFlags &= ~Impl::IS_SYNCHRONOUS_RESOURCE_LOADING;
+          mImpl->mFlags &= ~Visual::Base::Impl::IS_SYNCHRONOUS_RESOURCE_LOADING;
         }
       }
       else
@@ -452,7 +471,7 @@ void ImageVisual::GetNaturalSize(Vector2& naturalSize)
   }
   else if(mImpl->mRenderer) // Check if we have a loaded image
   {
-    if(mImpl->mFlags & Impl::IS_ATLASING_APPLIED)
+    if(mImpl->mFlags & Visual::Base::Impl::IS_ATLASING_APPLIED)
     {
       naturalSize.x = mAtlasRectSize.GetWidth();
       naturalSize.y = mAtlasRectSize.GetHeight();
@@ -460,7 +479,7 @@ void ImageVisual::GetNaturalSize(Vector2& naturalSize)
     }
 
     auto textureSet = mImpl->mRenderer.GetTextures();
-    if(textureSet)
+    if(textureSet && textureSet.GetTextureCount())
     {
       auto texture = textureSet.GetTexture(0);
       if(texture)
@@ -496,10 +515,16 @@ void ImageVisual::GetNaturalSize(Vector2& naturalSize)
       }
       else
       {
-        Texture brokenImage = mFactoryCache.GetBrokenVisualImage();
-
-        naturalSize.x = brokenImage.GetWidth();
-        naturalSize.y = brokenImage.GetWidth();
+        Actor   actor     = mPlacementActor.GetHandle();
+        Vector2 imageSize = Vector2::ZERO;
+        if(actor)
+        {
+          imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+        }
+        mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
+        Texture brokenImage = mImpl->mRenderer.GetTextures().GetTexture(0);
+        naturalSize.x       = brokenImage.GetWidth();
+        naturalSize.y       = brokenImage.GetWidth();
       }
       return;
     }
@@ -530,13 +555,23 @@ void ImageVisual::OnInitialize()
     }
   }
 
-  Shader shader = GetShader();
+  // Increase reference count of External Resources :
+  // EncodedImageBuffer or ExternalTextures.
+  // Reference count will be decreased at destructor of the visual.
+  if(mImageUrl.IsValid() && (mImageUrl.IsBufferResource() || mImageUrl.GetProtocolType() == VisualUrl::TEXTURE))
+  {
+    TextureManager& textureManager = mFactoryCache.GetTextureManager();
+    textureManager.UseExternalResource(mImageUrl.GetUrl());
+  }
+
+  Shader shader = GenerateShader();
 
   // Create the renderer
-  mImpl->mRenderer = Renderer::New(geometry, shader);
+  mImpl->mRenderer = VisualRenderer::New(geometry, shader);
+  mImpl->mRenderer.ReserveCustomProperties(CUSTOM_PROPERTY_COUNT);
 
   //Register transform properties
-  mImpl->mTransform.RegisterUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT);
+  mImpl->mTransform.SetUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT);
 
   EnablePreMultipliedAlpha(IsPreMultipliedAlphaEnabled());
 }
@@ -585,17 +620,17 @@ void ImageVisual::LoadTexture(bool& atlasing, Vector4& atlasRect, TextureSet& te
 
   if(atlasing) // Flag needs to be set before creating renderer
   {
-    mImpl->mFlags |= Impl::IS_ATLASING_APPLIED;
+    mImpl->mFlags |= Visual::Base::Impl::IS_ATLASING_APPLIED;
   }
   else
   {
-    mImpl->mFlags &= ~Impl::IS_ATLASING_APPLIED;
+    mImpl->mFlags &= ~Visual::Base::Impl::IS_ATLASING_APPLIED;
   }
 }
 
 bool ImageVisual::AttemptAtlasing()
 {
-  return (!mImpl->mCustomShader && mImageUrl.GetProtocolType() == VisualUrl::LOCAL && mAttemptAtlasing);
+  return (!mImpl->mCustomShader && (mImageUrl.IsLocalResource() || mImageUrl.IsBufferResource()) && mAttemptAtlasing);
 }
 
 void ImageVisual::InitializeRenderer()
@@ -684,12 +719,12 @@ void ImageVisual::DoSetOnScene(Actor& actor)
   }
   else if(mLoadState == TextureManager::LoadState::LOAD_FAILED)
   {
-    Texture brokenImage = mFactoryCache.GetBrokenVisualImage();
-
-    mTextures = TextureSet::New();
-    mTextures.SetTexture(0u, brokenImage);
-    mImpl->mRenderer.SetTextures(mTextures);
-
+    Vector2 imageSize = Vector2::ZERO;
+    if(actor)
+    {
+      imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+    }
+    mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
     actor.AddRenderer(mImpl->mRenderer);
     mPlacementActor.Reset();
 
@@ -723,7 +758,7 @@ void ImageVisual::DoCreatePropertyMap(Property::Map& map) const
   map.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE);
 
   bool sync = IsSynchronousLoadingRequired();
-  map.Insert(SYNCHRONOUS_LOADING, sync);
+  map.Insert(Toolkit::ImageVisual::Property::SYNCHRONOUS_LOADING, sync);
   if(mImageUrl.IsValid())
   {
     map.Insert(Toolkit::ImageVisual::Property::URL, mImageUrl.GetUrl());
@@ -763,11 +798,11 @@ void ImageVisual::DoCreateInstancePropertyMap(Property::Map& map) const
   }
 }
 
-void ImageVisual::OnDoAction(const Dali::Property::Index actionName, const Dali::Property::Value& attributes)
+void ImageVisual::OnDoAction(const Dali::Property::Index actionId, const Dali::Property::Value& attributes)
 {
   // Check if action is valid for this visual type and perform action if possible
 
-  switch(actionName)
+  switch(actionId)
   {
     case DevelImageVisual::Action::RELOAD:
     {
@@ -782,21 +817,15 @@ void ImageVisual::OnSetTransform()
 {
   if(mImpl->mRenderer)
   {
-    mImpl->mTransform.RegisterUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT);
+    mImpl->mTransform.SetUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT);
   }
 }
 
-bool ImageVisual::IsResourceReady() const
-{
-  return (mImpl->mResourceStatus == Toolkit::Visual::ResourceStatus::READY ||
-          mImpl->mResourceStatus == Toolkit::Visual::ResourceStatus::FAILED);
-}
-
 void ImageVisual::UpdateShader()
 {
   if(mImpl->mRenderer)
   {
-    Shader shader = GetShader();
+    Shader shader = GenerateShader();
     mImpl->mRenderer.SetShader(shader);
   }
 }
@@ -821,45 +850,49 @@ void ImageVisual::UploadCompleted()
 }
 
 // From Texture Manager
-void ImageVisual::UploadComplete(bool loadingSuccess, int32_t textureId, TextureSet textureSet, bool usingAtlas, const Vector4& atlasRectangle, bool preMultiplied)
+void ImageVisual::LoadComplete(bool loadingSuccess, TextureInformation textureInformation)
 {
   Toolkit::Visual::ResourceStatus resourceStatus;
   if(mImpl->mRenderer)
   {
-    if(usingAtlas)
+    if(textureInformation.useAtlasing)
     {
       mImpl->mRenderer.RegisterProperty(ATLAS_RECT_UNIFORM_NAME, mAtlasRect);
     }
 
-    EnablePreMultipliedAlpha(preMultiplied);
+    EnablePreMultipliedAlpha(textureInformation.preMultiplied);
 
     Actor actor = mPlacementActor.GetHandle();
+    if(!loadingSuccess)
+    {
+      Vector2 imageSize = Vector2::ZERO;
+      if(actor)
+      {
+        imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+      }
+      mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
+      textureInformation.textureSet = mImpl->mRenderer.GetTextures();
+    }
+    else
+    {
+      Sampler sampler = Sampler::New();
+      sampler.SetWrapMode(mWrapModeU, mWrapModeV);
+      textureInformation.textureSet.SetSampler(0u, sampler);
+      mImpl->mRenderer.SetTextures(textureInformation.textureSet);
+    }
+
     if(actor)
     {
       actor.AddRenderer(mImpl->mRenderer);
       // reset the weak handle so that the renderer only get added to actor once
       mPlacementActor.Reset();
     }
-
-    if(!loadingSuccess)
-    {
-      Texture brokenImage = mFactoryCache.GetBrokenVisualImage();
-
-      textureSet = TextureSet::New();
-      textureSet.SetTexture(0u, brokenImage);
-      mImpl->mRenderer.SetTextures(textureSet);
-    }
-
-    Sampler sampler = Sampler::New();
-    sampler.SetWrapMode(mWrapModeU, mWrapModeV);
-    textureSet.SetSampler(0u, sampler);
-    mImpl->mRenderer.SetTextures(textureSet);
   }
 
   // Storing TextureSet needed when renderer staged.
   if(!mImpl->mRenderer)
   {
-    mTextures = textureSet;
+    mTextures = textureInformation.textureSet;
   }
 
   // Image loaded, set status regardless of staged status.
@@ -934,61 +967,71 @@ void ImageVisual::RemoveTexture()
   }
 }
 
-Shader ImageVisual::GetShader()
+Shader ImageVisual::GenerateShader() const
 {
   Shader shader;
 
-  std::string_view vertexShaderView;
-  bool             usesWholeTexture = true;
-  if(mImpl->mCustomShader && !mImpl->mCustomShader->mVertexShader.empty())
-  {
-    vertexShaderView = mImpl->mCustomShader->mVertexShader;
-    usesWholeTexture = false; // Impossible to tell.
-  }
-  else
-  {
-    vertexShaderView = mImageVisualShaderFactory.GetVertexShaderSource();
-  }
-
-  std::string_view fragmentShaderView;
-  if(mImpl->mCustomShader && !mImpl->mCustomShader->mFragmentShader.empty())
-  {
-    fragmentShaderView = mImpl->mCustomShader->mFragmentShader;
-  }
-  else
-  {
-    fragmentShaderView = mImageVisualShaderFactory.GetFragmentShaderSource();
-  }
-
-  // If the texture is native, we may need to change prefix and sampler in
-  // the fragment shader
-  bool        modifiedFragmentShader = false;
-  std::string fragmentShaderString;
-  if(mTextures && DevelTexture::IsNative(mTextures.GetTexture(0)))
-  {
-    Texture nativeTexture  = mTextures.GetTexture(0);
-    fragmentShaderString   = std::string(fragmentShaderView);
-    modifiedFragmentShader = DevelTexture::ApplyNativeFragmentShader(nativeTexture, fragmentShaderString);
-    fragmentShaderView     = fragmentShaderString;
-  }
+  bool       usesWholeTexture  = true;
+  const bool useStandardShader = !mImpl->mCustomShader;
+  const bool useNativeImage    = (mTextures && DevelTexture::IsNative(mTextures.GetTexture(0)));
 
-  const bool useStandardShader = !mImpl->mCustomShader && !modifiedFragmentShader;
   if(useStandardShader)
   {
     // Create and cache the standard shader
     shader = mImageVisualShaderFactory.GetShader(
       mFactoryCache,
-      mImpl->mFlags & Impl::IS_ATLASING_APPLIED,
-      mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE,
-      IsRoundedCornerRequired());
-  }
-  else if(mImpl->mCustomShader)
-  {
-    shader = Shader::New(vertexShaderView, fragmentShaderView, mImpl->mCustomShader->mHints);
+      ImageVisualShaderFeature::FeatureBuilder()
+        .EnableTextureAtlas(mImpl->mFlags & Visual::Base::Impl::IS_ATLASING_APPLIED && !useNativeImage)
+        .ApplyDefaultTextureWrapMode(mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE)
+        .EnableRoundedCorner(IsRoundedCornerRequired())
+        .EnableBorderline(IsBorderlineRequired())
+        .SetTextureForFragmentShaderCheck(useNativeImage ? mTextures.GetTexture(0) : Dali::Texture()));
   }
   else
   {
-    shader = Shader::New(vertexShaderView, fragmentShaderView);
+    std::string_view vertexShaderView;
+    std::string_view fragmentShaderView;
+
+    if(mImpl->mCustomShader && !mImpl->mCustomShader->mVertexShader.empty())
+    {
+      vertexShaderView = mImpl->mCustomShader->mVertexShader;
+      usesWholeTexture = false; // Impossible to tell.
+    }
+    else
+    {
+      vertexShaderView = mImageVisualShaderFactory.GetVertexShaderSource();
+    }
+
+    if(mImpl->mCustomShader && !mImpl->mCustomShader->mFragmentShader.empty())
+    {
+      fragmentShaderView = mImpl->mCustomShader->mFragmentShader;
+    }
+    else
+    {
+      fragmentShaderView = mImageVisualShaderFactory.GetFragmentShaderSource();
+    }
+
+    // If the texture is native, we may need to change prefix and sampler in
+    // the fragment shader
+    if(useNativeImage)
+    {
+      bool        modifiedFragmentShader = false;
+      Texture     nativeTexture          = mTextures.GetTexture(0);
+      std::string fragmentShaderString   = std::string(fragmentShaderView);
+
+      modifiedFragmentShader = DevelTexture::ApplyNativeFragmentShader(nativeTexture, fragmentShaderString);
+      if(modifiedFragmentShader)
+      {
+        fragmentShaderView = fragmentShaderString;
+      }
+
+      // Create shader here cause fragmentShaderString scope issue
+      shader = Shader::New(vertexShaderView, fragmentShaderView, mImpl->mCustomShader->mHints);
+    }
+    else
+    {
+      shader = Shader::New(vertexShaderView, fragmentShaderView, mImpl->mCustomShader->mHints);
+    }
   }
 
   if(usesWholeTexture)