[dali_2.3.22] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / npatch / npatch-visual.cpp
index 5fc5dd0..1047eaf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
@@ -16,7 +16,7 @@
  */
 
 // CLASS HEADER
-#include "npatch-visual.h"
+#include <dali-toolkit/internal/visuals/npatch/npatch-visual.h>
 
 // EXTERNAL INCLUDES
 #include <dali/devel-api/adaptor-framework/image-loading.h>
@@ -28,7 +28,9 @@
 #include <dali-toolkit/devel-api/utility/npatch-helper.h>
 #include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
 #include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.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/image-visual-shader-feature-builder.h>
 #include <dali-toolkit/internal/visuals/npatch-loader.h>
 #include <dali-toolkit/internal/visuals/rendering-addon.h>
 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
@@ -73,28 +75,40 @@ void NPatchVisual::LoadImages()
   TextureManager& textureManager     = mFactoryCache.GetTextureManager();
   bool            synchronousLoading = mImpl->mFlags & Impl::IS_SYNCHRONOUS_RESOURCE_LOADING;
 
-  if(mId == NPatchData::INVALID_NPATCH_DATA_ID && (mImageUrl.IsLocalResource() || mImageUrl.IsBufferResource()))
+  if(mId == NPatchData::INVALID_NPATCH_DATA_ID)
   {
     bool preMultiplyOnLoad = IsPreMultipliedAlphaEnabled() && !mImpl->mCustomShader ? true : false;
     mId                    = mLoader.Load(textureManager, this, mImageUrl, mBorder, preMultiplyOnLoad, synchronousLoading);
 
-    const NPatchData* data;
+    NPatchDataPtr data;
     if(mLoader.GetNPatchData(mId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
     {
       EnablePreMultipliedAlpha(data->IsPreMultiplied());
     }
   }
 
-  if(!mAuxiliaryPixelBuffer && mAuxiliaryUrl.IsValid() && (mAuxiliaryUrl.IsLocalResource() || mAuxiliaryUrl.IsBufferResource()))
+  if(mAuxiliaryTextureId == TextureManager::INVALID_TEXTURE_ID && mAuxiliaryUrl.IsValid())
   {
+    auto preMultiplyOnLoad = IsPreMultipliedAlphaEnabled() && !mImpl->mCustomShader
+                               ? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD
+                               : TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
+
+    TextureManager::MaskingDataPointer maskingDataPtr       = nullptr;
+    ImageAtlasManagerPtr               imageAtlasManagerPtr = nullptr;
+
+    bool atlasing      = false;
+    auto atlasRect     = Vector4::ZERO;
+    auto atlasRectSize = Dali::ImageDimensions();
+
+    bool loadingStatus = false;
+
     // Load the auxiliary image
-    auto preMultiplyOnLoading = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
-    mAuxiliaryPixelBuffer     = textureManager.LoadPixelBuffer(mAuxiliaryUrl, Dali::ImageDimensions(), FittingMode::DEFAULT, SamplingMode::BOX_THEN_LINEAR, synchronousLoading, this, true, preMultiplyOnLoading);
+    mAuxiliaryTextureSet = textureManager.LoadTexture(mAuxiliaryUrl, Dali::ImageDimensions(), FittingMode::DEFAULT, SamplingMode::BOX_THEN_LINEAR, maskingDataPtr, synchronousLoading, mAuxiliaryTextureId, atlasRect, atlasRectSize, atlasing, loadingStatus, this, nullptr, imageAtlasManagerPtr, true, TextureManager::ReloadPolicy::CACHED, preMultiplyOnLoad);
 
-    // If synchronousLoading is true, we can check the auxiliaryResource's statue now.
+    // If synchronousLoading is true, we can check the auxiliaryResource's status now.
     if(synchronousLoading)
     {
-      mAuxiliaryResourceStatus = mAuxiliaryPixelBuffer ? Toolkit::Visual::ResourceStatus::READY : Toolkit::Visual::ResourceStatus::FAILED;
+      mAuxiliaryResourceStatus = (mAuxiliaryTextureSet && mAuxiliaryTextureSet.GetTextureCount() > 0u) ? Toolkit::Visual::ResourceStatus::READY : Toolkit::Visual::ResourceStatus::FAILED;
     }
   }
 }
@@ -105,7 +119,7 @@ void NPatchVisual::GetNaturalSize(Vector2& naturalSize)
   naturalSize.y = 0u;
 
   // load now if not already loaded
-  const NPatchData* data;
+  NPatchDataPtr data;
   if(mLoader.GetNPatchData(mId, data) && data->GetLoadingState() != NPatchData::LoadingState::LOADING)
   {
     naturalSize.x = data->GetCroppedWidth();
@@ -124,10 +138,10 @@ void NPatchVisual::GetNaturalSize(Vector2& naturalSize)
     }
   }
 
-  if(mAuxiliaryPixelBuffer)
+  if(mAuxiliaryTextureSet && mAuxiliaryTextureSet.GetTextureCount() > 0u)
   {
-    naturalSize.x = std::max(naturalSize.x, float(mAuxiliaryPixelBuffer.GetWidth()));
-    naturalSize.y = std::max(naturalSize.y, float(mAuxiliaryPixelBuffer.GetHeight()));
+    naturalSize.x = std::max(naturalSize.x, float(mAuxiliaryTextureSet.GetTexture(0u).GetWidth()));
+    naturalSize.y = std::max(naturalSize.y, float(mAuxiliaryTextureSet.GetTexture(0u).GetHeight()));
   }
 }
 
@@ -202,7 +216,7 @@ void NPatchVisual::DoSetOnScene(Actor& actor)
   // at this case, we try to SetResouce to mPlaceActor twice. so, we should avoid that case.
   mPlacementActor = actor;
 
-  const NPatchData* data;
+  NPatchDataPtr data;
   if(mImpl->mRenderer && mLoader.GetNPatchData(mId, data) && data->GetLoadingState() != NPatchData::LoadingState::LOADING)
   {
     // If mAuxiliaryUrl need to be loaded, we should wait it until LoadComplete called.
@@ -215,11 +229,22 @@ void NPatchVisual::DoSetOnScene(Actor& actor)
 
 void NPatchVisual::DoSetOffScene(Actor& actor)
 {
-  if((mId != NPatchData::INVALID_NPATCH_DATA_ID) && mReleasePolicy == Toolkit::ImageVisual::ReleasePolicy::DETACHED)
+  if(mReleasePolicy == Toolkit::ImageVisual::ReleasePolicy::DETACHED)
   {
-    mLoader.Remove(mId, this);
-    mImpl->mResourceStatus = Toolkit::Visual::ResourceStatus::PREPARING;
-    mId                    = NPatchData::INVALID_NPATCH_DATA_ID;
+    if(mId != NPatchData::INVALID_NPATCH_DATA_ID)
+    {
+      mLoader.RequestRemove(mId, this);
+      mImpl->mResourceStatus = Toolkit::Visual::ResourceStatus::PREPARING;
+      mId                    = NPatchData::INVALID_NPATCH_DATA_ID;
+    }
+    if(mAuxiliaryTextureId != TextureManager::INVALID_TEXTURE_ID)
+    {
+      TextureManager& textureManager = mFactoryCache.GetTextureManager();
+      textureManager.RequestRemove(mAuxiliaryTextureId, this);
+      mAuxiliaryTextureId      = TextureManager::INVALID_TEXTURE_ID;
+      mAuxiliaryResourceStatus = Toolkit::Visual::ResourceStatus::PREPARING;
+      mAuxiliaryTextureSet.Reset();
+    }
   }
 
   actor.RemoveRenderer(mImpl->mRenderer);
@@ -234,12 +259,6 @@ void NPatchVisual::OnSetTransform()
   }
 }
 
-bool NPatchVisual::IsResourceReady() const
-{
-  return (mImpl->mResourceStatus == Toolkit::Visual::ResourceStatus::READY ||
-          mImpl->mResourceStatus == Toolkit::Visual::ResourceStatus::FAILED);
-}
-
 void NPatchVisual::DoCreatePropertyMap(Property::Map& map) const
 {
   map.Clear();
@@ -275,6 +294,8 @@ NPatchVisual::NPatchVisual(VisualFactoryCache& factoryCache, ImageVisualShaderFa
   mImageUrl(),
   mAuxiliaryUrl(),
   mId(NPatchData::INVALID_NPATCH_DATA_ID),
+  mAuxiliaryTextureSet(),
+  mAuxiliaryTextureId(TextureManager::INVALID_TEXTURE_ID),
   mAuxiliaryResourceStatus(Toolkit::Visual::ResourceStatus::PREPARING),
   mBorderOnly(false),
   mBorder(),
@@ -286,20 +307,35 @@ NPatchVisual::NPatchVisual(VisualFactoryCache& factoryCache, ImageVisualShaderFa
 
 NPatchVisual::~NPatchVisual()
 {
-  if(Stage::IsInstalled() && (mId != NPatchData::INVALID_NPATCH_DATA_ID) && (mReleasePolicy != Toolkit::ImageVisual::ReleasePolicy::NEVER))
+  if(Stage::IsInstalled())
   {
-    mLoader.Remove(mId, this);
-    mId = NPatchData::INVALID_NPATCH_DATA_ID;
+    if(mReleasePolicy != Toolkit::ImageVisual::ReleasePolicy::NEVER)
+    {
+      if(mId != NPatchData::INVALID_NPATCH_DATA_ID)
+      {
+        mLoader.RequestRemove(mId, this);
+        mId = NPatchData::INVALID_NPATCH_DATA_ID;
+      }
+      if(mAuxiliaryTextureId != TextureManager::INVALID_TEXTURE_ID)
+      {
+        TextureManager& textureManager = mFactoryCache.GetTextureManager();
+
+        textureManager.RequestRemove(mAuxiliaryTextureId, this);
+        mAuxiliaryTextureId = TextureManager::INVALID_TEXTURE_ID;
+        mAuxiliaryTextureSet.Reset();
+      }
+    }
   }
 }
 
 void NPatchVisual::OnInitialize()
 {
   // Get basic geometry and shader
-  Geometry geometry = mFactoryCache.GetGeometry(VisualFactoryCache::QUAD_GEOMETRY);
-  Shader   shader   = mImageVisualShaderFactory.GetShader(
+  Geometry geometry                        = mFactoryCache.GetGeometry(VisualFactoryCache::QUAD_GEOMETRY);
+  auto     imageVisualShaderFeatureBuilder = ImageVisualShaderFeatureBuilder();
+  Shader   shader                          = mImageVisualShaderFactory.GetShader(
     mFactoryCache,
-    ImageVisualShaderFeature::FeatureBuilder());
+    imageVisualShaderFeatureBuilder);
 
   mImpl->mRenderer = VisualRenderer::New(geometry, shader);
   mImpl->mRenderer.ReserveCustomProperties(CUSTOM_PROPERTY_COUNT);
@@ -310,8 +346,8 @@ void NPatchVisual::OnInitialize()
 
 Geometry NPatchVisual::CreateGeometry()
 {
-  Geometry          geometry;
-  const NPatchData* data;
+  Geometry      geometry;
+  NPatchDataPtr data;
   if(mLoader.GetNPatchData(mId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
   {
     if(data->GetStretchPixelsX().Size() == 1 && data->GetStretchPixelsY().Size() == 1)
@@ -365,17 +401,17 @@ Geometry NPatchVisual::CreateGeometry()
 
 Shader NPatchVisual::CreateShader()
 {
-  Shader            shader;
-  const NPatchData* data;
+  Shader        shader;
+  NPatchDataPtr data;
   // 0 is either no data (load failed?) or no stretch regions on image
   // for both cases we use the default shader
   NPatchUtility::StretchRanges::SizeType xStretchCount = 0;
   NPatchUtility::StretchRanges::SizeType yStretchCount = 0;
 
-  auto fragmentShader = mAuxiliaryPixelBuffer ? SHADER_NPATCH_VISUAL_MASK_SHADER_FRAG
-                                              : SHADER_NPATCH_VISUAL_SHADER_FRAG;
-  auto shaderType = mAuxiliaryPixelBuffer ? VisualFactoryCache::NINE_PATCH_MASK_SHADER
-                                          : VisualFactoryCache::NINE_PATCH_SHADER;
+  auto fragmentShader = mAuxiliaryResourceStatus == Toolkit::Visual::ResourceStatus::READY ? SHADER_NPATCH_VISUAL_MASK_SHADER_FRAG
+                                                                                           : SHADER_NPATCH_VISUAL_SHADER_FRAG;
+  auto shaderType     = mAuxiliaryResourceStatus == Toolkit::Visual::ResourceStatus::READY ? VisualFactoryCache::NINE_PATCH_MASK_SHADER
+                                                                                           : VisualFactoryCache::NINE_PATCH_SHADER;
 
   // ask loader for the regions
   if(mLoader.GetNPatchData(mId, data))
@@ -392,19 +428,20 @@ Shader NPatchVisual::CreateShader()
       shader = mFactoryCache.GetShader(shaderType);
       if(DALI_UNLIKELY(!shader))
       {
-        shader = Shader::New(SHADER_NPATCH_VISUAL_3X3_SHADER_VERT, fragmentShader);
-        // Only cache vanilla 9 patch shaders
-        mFactoryCache.SaveShader(shaderType, shader);
+        shader = mFactoryCache.GenerateAndSaveShader(shaderType, SHADER_NPATCH_VISUAL_3X3_SHADER_VERT, fragmentShader);
       }
     }
     else if(xStretchCount > 0 || yStretchCount > 0)
     {
+      std::stringstream shaderName;
+      shaderName << "N_PATCH_" << xStretchCount << "x" << yStretchCount;
+
       std::stringstream vertexShader;
       vertexShader << "#define FACTOR_SIZE_X " << xStretchCount + 2 << "\n"
                    << "#define FACTOR_SIZE_Y " << yStretchCount + 2 << "\n"
                    << SHADER_NPATCH_VISUAL_SHADER_VERT;
 
-      shader = Shader::New(vertexShader.str(), fragmentShader);
+      shader = Shader::New(vertexShader.str(), fragmentShader, Dali::Shader::Hint::NONE, shaderName.str());
     }
   }
   else
@@ -431,12 +468,15 @@ Shader NPatchVisual::CreateShader()
     }
     else if(xStretchCount > 0 || yStretchCount > 0)
     {
+      std::stringstream shaderName;
+      shaderName << "N_PATCH_" << xStretchCount << "x" << yStretchCount;
+
       std::stringstream vertexShader;
       vertexShader << "#define FACTOR_SIZE_X " << xStretchCount + 2 << "\n"
                    << "#define FACTOR_SIZE_Y " << yStretchCount + 2 << "\n"
                    << SHADER_NPATCH_VISUAL_SHADER_VERT;
 
-      shader = Shader::New(vertexShader.str(), fragmentShader, hints);
+      shader = Shader::New(vertexShader.str(), fragmentShader, hints, shaderName.str());
     }
   }
 
@@ -445,40 +485,25 @@ Shader NPatchVisual::CreateShader()
 
 void NPatchVisual::ApplyTextureAndUniforms()
 {
-  const NPatchData* data;
-  TextureSet        textureSet;
+  NPatchDataPtr data;
+  TextureSet    textureSet;
 
   if(mLoader.GetNPatchData(mId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
   {
     textureSet = data->GetTextures();
-    NPatchHelper::ApplyTextureAndUniforms(mImpl->mRenderer, data);
+    NPatchHelper::ApplyTextureAndUniforms(mImpl->mRenderer, data.Get());
 
-    if(mAuxiliaryPixelBuffer)
+    if(mAuxiliaryResourceStatus == Toolkit::Visual::ResourceStatus::READY)
     {
-      // If the auxiliary image is smaller than the un-stretched NPatch, use CPU resizing to enlarge it to the
-      // same size as the unstretched NPatch. This will give slightly higher quality results than just relying
-      // on GL interpolation alone.
-      if(mAuxiliaryPixelBuffer.GetWidth() < data->GetCroppedWidth() &&
-         mAuxiliaryPixelBuffer.GetHeight() < data->GetCroppedHeight())
-      {
-        mAuxiliaryPixelBuffer.Resize(data->GetCroppedWidth(), data->GetCroppedHeight());
-      }
-
-      // Note, this resets mAuxiliaryPixelBuffer handle
-      auto auxiliaryPixelData = Devel::PixelBuffer::Convert(mAuxiliaryPixelBuffer);
-
-      auto texture = Texture::New(TextureType::TEXTURE_2D,
-                                  auxiliaryPixelData.GetPixelFormat(),
-                                  auxiliaryPixelData.GetWidth(),
-                                  auxiliaryPixelData.GetHeight());
-      texture.Upload(auxiliaryPixelData);
+      DALI_ASSERT_ALWAYS(mAuxiliaryTextureId != TextureManager::INVALID_TEXTURE_ID);
+      DALI_ASSERT_ALWAYS(mAuxiliaryTextureSet && mAuxiliaryTextureSet.GetTextureCount() > 0u);
 
       // TODO : This code exist due to the texture cache manager hold TextureSet, not Texture.
       // If we call textureSet.SetTexture(1, texture) directly, the cached TextureSet also be changed.
       // We should make pass utc-Dali-VisualFactory.cpp UtcDaliNPatchVisualAuxiliaryImage02().
       TextureSet tempTextureSet = TextureSet::New();
+      tempTextureSet.SetTexture(1, mAuxiliaryTextureSet.GetTexture(0));
       tempTextureSet.SetTexture(0, textureSet.GetTexture(0));
-      tempTextureSet.SetTexture(1, texture);
       textureSet = tempTextureSet;
 
       mImpl->mRenderer.RegisterProperty(DevelImageVisual::Property::AUXILIARY_IMAGE_ALPHA,
@@ -523,7 +548,7 @@ Geometry NPatchVisual::GetNinePatchGeometry(VisualFactoryCache::GeometryType sub
 
 void NPatchVisual::SetResource()
 {
-  const NPatchData* data;
+  NPatchDataPtr data;
   if(mImpl->mRenderer && mLoader.GetNPatchData(mId, data))
   {
     Geometry geometry = CreateGeometry();
@@ -558,27 +583,30 @@ void NPatchVisual::SetResource()
 
 void NPatchVisual::LoadComplete(bool loadSuccess, TextureInformation textureInformation)
 {
-  if(textureInformation.returnType == TextureUploadObserver::ReturnType::TEXTURE) // For the Url.
+  if(textureInformation.url.length() > 0) // For the Url.
   {
-    if(textureInformation.textureId != TextureManager::INVALID_TEXTURE_ID)
+    if(DALI_UNLIKELY(mId == NPatchData::INVALID_NPATCH_DATA_ID))
     {
-      if(mId == NPatchData::INVALID_NPATCH_DATA_ID)
-      {
-        // Special case when mLoader.Load call LoadComplete function before mId setup.
-        // We can overwrite mId.
-        mId = static_cast<NPatchData::NPatchDataId>(textureInformation.textureId);
-      }
+      // Special case when mLoader.Load call LoadComplete function before mId setup.
+      // We can overwrite mId.
+      mId = static_cast<NPatchData::NPatchDataId>(textureInformation.textureId);
     }
     if(loadSuccess)
     {
       EnablePreMultipliedAlpha(textureInformation.preMultiplied);
     }
   }
-  else // For the AuxiliaryUrl : ReturnType::PIXEL_BUFFER
+  else // For the AuxiliaryUrl
   {
-    if(loadSuccess && textureInformation.url == mAuxiliaryUrl.GetUrl())
+    if(DALI_UNLIKELY(mAuxiliaryTextureId == TextureManager::INVALID_TEXTURE_ID))
     {
-      mAuxiliaryPixelBuffer    = textureInformation.pixelBuffer;
+      // Special case when TextureManager.LoadTexture call LoadComplete function before mAuxiliaryTextureId setup.
+      // We can overwrite mAuxiliaryTextureId.
+      mAuxiliaryTextureId = textureInformation.textureId;
+    }
+    if(loadSuccess)
+    {
+      mAuxiliaryTextureSet     = textureInformation.textureSet;
       mAuxiliaryResourceStatus = Toolkit::Visual::ResourceStatus::READY;
     }
     else
@@ -586,10 +614,11 @@ void NPatchVisual::LoadComplete(bool loadSuccess, TextureInformation textureInfo
       mAuxiliaryResourceStatus = Toolkit::Visual::ResourceStatus::FAILED;
     }
   }
+
   // If auxiliaryUrl didn't required OR auxiliaryUrl load done.
   if(!mAuxiliaryUrl.IsValid() || mAuxiliaryResourceStatus != Toolkit::Visual::ResourceStatus::PREPARING)
   {
-    const NPatchData* data;
+    NPatchDataPtr data;
     // and.. If Url loading done.
     if(mImpl->mRenderer && mLoader.GetNPatchData(mId, data) && data->GetLoadingState() != NPatchData::LoadingState::LOADING)
     {