[Tizen] Destroy removal visuals after idler 23/300223/1
authorEunki, Hong <eunkiki.hong@samsung.com>
Thu, 19 Oct 2023 02:34:34 +0000 (11:34 +0900)
committerEunki, Hong <eunkiki.hong@samsung.com>
Thu, 19 Oct 2023 02:45:36 +0000 (11:45 +0900)
This is a combination of 3 commits.

Revert "[Tizen] Keep reference when member callback excute"

Keep reference when member callback excute + Make NPatchData as RefObject

Some CallbackBase didn't hold the reference of itself.
So it was possible to call destructor of itself during it's
API was running.

It might makes some unknown issues. So let we keep reference
for some issue-comes known APIs : SvgVisual, NPatchData, and lottie

It future, we should discard visuals rather than delate it directly.

Destroy removal visuals after idler

There was some bug when visual destructor called during
it's emit ResourceReady.

To avoid this case, Let we keep visuals more long term,
and Discard + Destroy after some idler called.

To avoid multiple Idler callback register,
let we make that idler callback in VisualFactory.

Change-Id: I4156f1af3cf40ffb30235dc9e6c55f9c7633f21d

19 files changed:
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-adaptor.cpp
automated-tests/src/dali-toolkit/utc-Dali-Slider.cpp
dali-scene3d/internal/controls/scene-view/scene-view-impl.cpp
dali-toolkit/devel-api/utility/npatch-helper.cpp
dali-toolkit/devel-api/utility/npatch-helper.h
dali-toolkit/devel-api/visual-factory/visual-factory.cpp
dali-toolkit/devel-api/visual-factory/visual-factory.h
dali-toolkit/internal/controls/control/control-data-impl.cpp
dali-toolkit/internal/visuals/animated-image/rolling-animated-image-cache.cpp
dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp
dali-toolkit/internal/visuals/npatch-data.cpp
dali-toolkit/internal/visuals/npatch-data.h
dali-toolkit/internal/visuals/npatch-loader.cpp
dali-toolkit/internal/visuals/npatch-loader.h
dali-toolkit/internal/visuals/npatch/npatch-visual.cpp
dali-toolkit/internal/visuals/svg/svg-visual.cpp
dali-toolkit/internal/visuals/visual-factory-cache.cpp
dali-toolkit/internal/visuals/visual-factory-impl.cpp
dali-toolkit/internal/visuals/visual-factory-impl.h

index 7c887f884ecf0e1def980fb35cbf3be673d87d07..c675fef5f3c25e33698c3da9563070ec5a768ef9 100644 (file)
@@ -92,8 +92,8 @@ bool Adaptor::AddIdle(CallbackBase* callback, bool hasReturnValue)
 
 void Adaptor::RemoveIdle(CallbackBase* callback)
 {
-  mCallbacks.Erase(std::find_if(mCallbacks.Begin(), mCallbacks.End(), [&callback](CallbackBase* current) { return callback == current; }));
-  mReturnCallbacks.Erase(std::find_if(mReturnCallbacks.Begin(), mReturnCallbacks.End(), [&callback](CallbackBase* current) { return callback == current; }));
+  mCallbacks.Erase(std::remove_if(mCallbacks.Begin(), mCallbacks.End(), [&callback](CallbackBase* current) { return callback == current; }), mCallbacks.End());
+  mReturnCallbacks.Erase(std::remove_if(mReturnCallbacks.Begin(), mReturnCallbacks.End(), [&callback](CallbackBase* current) { return callback == current; }), mReturnCallbacks.End());
 }
 
 void Adaptor::RunIdles()
index 22b4d2f8aef49665ab5963c839683317bd296f7b..1e86e0df5462d2a04fea3dafc2ae58539d484b59 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
@@ -346,10 +346,10 @@ int UtcDaliSliderSignals2(void)
   END_TEST;
 }
 
-int UtcDaliSetPropertyP(void)
+int UtcDaliSliderSetPropertyP(void)
 {
   ToolkitTestApplication application;
-  tet_infoline("UtcDaliSetPropertyP");
+  tet_infoline("UtcDaliSliderSetPropertyP");
 
   Slider slider = Slider::New();
   slider.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
index d630b24d3bcbb352878256e9ca54c4e3a3a1bfaf..75c9b514d5cfe8c625bfaba16e290ba27370e557 100644 (file)
@@ -160,123 +160,122 @@ void SetShadowLightConstraint(Dali::CameraActor selectedCamera, Dali::CameraActo
   shadowLightCamera.RemoveConstraints();
 
   // Compute ViewProjectionMatrix and store it to "tempViewProjectionMatrix" property
-  auto       tempViewProjectionMatrixIndex  = shadowLightCamera.RegisterProperty("tempViewProjectionMatrix", Matrix::IDENTITY);
-  Constraint projectionMatrixConstraint = Constraint::New<Matrix>(shadowLightCamera, tempViewProjectionMatrixIndex, [](Matrix& output, const PropertyInputContainer& inputs)
-                                                                  {
-                                                                    Matrix worldMatrix = inputs[0]->GetMatrix();
-                                                                    float tangentFov_2 = tanf(inputs[4]->GetFloat());
-                                                                    float  nearDistance = inputs[5]->GetFloat();
-                                                                    float  farDistance  = inputs[6]->GetFloat();
-                                                                    float  aspectRatio  = inputs[7]->GetFloat();
-                                                                    float  nearY        = 0.0f;
-                                                                    float  nearX        = 0.0f;
-                                                                    float  farY         = 0.0f;
-                                                                    float  farX         = 0.0f;
-                                                                    if(inputs[1]->GetInteger() == Dali::Camera::ProjectionMode::PERSPECTIVE_PROJECTION)
-                                                                    {
-                                                                      if(inputs[2]->GetInteger() == Dali::DevelCameraActor::ProjectionDirection::VERTICAL)
-                                                                      {
-                                                                        nearY = tangentFov_2 * nearDistance;
-                                                                        nearX = nearY * aspectRatio;
-                                                                        farY  = tangentFov_2 * farDistance;
-                                                                        farX  = farY * aspectRatio;
-                                                                      }
-                                                                      else
-                                                                      {
-                                                                        nearX = tangentFov_2 * nearDistance;
-                                                                        nearY = nearX / aspectRatio;
-                                                                        farX  = tangentFov_2 * farDistance;
-                                                                        farY  = farX / aspectRatio;
-                                                                      }
-                                                                    }
-                                                                    else
-                                                                    {
-                                                                      if(inputs[2]->GetInteger() == Dali::DevelCameraActor::ProjectionDirection::VERTICAL)
-                                                                      {
-                                                                        nearY = inputs[3]->GetFloat();
-                                                                        nearX = nearY * aspectRatio;
-                                                                      }
-                                                                      else
-                                                                      {
-                                                                        nearX = inputs[3]->GetFloat();
-                                                                        nearY = nearX / aspectRatio;
-                                                                      }
-                                                                      farX = nearX;
-                                                                      farY = nearY;
-                                                                    }
-
-                                                                    std::vector<Vector4> points;
-                                                                    points.push_back(Vector4(nearX, nearY, nearDistance, 1.0f));
-                                                                    points.push_back(Vector4(-nearX, nearY, nearDistance, 1.0f));
-                                                                    points.push_back(Vector4(-nearX, -nearY, nearDistance, 1.0f));
-                                                                    points.push_back(Vector4(nearX, -nearY, nearDistance, 1.0f));
-                                                                    points.push_back(Vector4(farX, farY, farDistance, 1.0f));
-                                                                    points.push_back(Vector4(-farX, farY, farDistance, 1.0f));
-                                                                    points.push_back(Vector4(-farX, -farY, farDistance, 1.0f));
-                                                                    points.push_back(Vector4(farX, -farY, farDistance, 1.0f));
-
-                                                                    Matrix shadowCameraWorldMatrix = inputs[8]->GetMatrix();
-                                                                    Vector4 worldCenter;
-                                                                    for(auto&& point : points)
-                                                                    {
-                                                                      point = worldMatrix * point;
-                                                                      worldCenter += point;
-                                                                    }
-                                                                    worldCenter /= 8.0f;
-                                                                    shadowCameraWorldMatrix.SetTranslation(Vector3(worldCenter));
-                                                                    Matrix shadowCameraViewMatrix = shadowCameraWorldMatrix;
-                                                                    shadowCameraViewMatrix.Invert();
-
-                                                                    Vector3 areaMin = Vector3::ONE * MAXFLOAT, areaMax = Vector3::ONE * -MAXFLOAT;
-                                                                    for(auto&& point : points)
-                                                                    {
-                                                                      Vector4 pointV = shadowCameraViewMatrix * point;
-                                                                      areaMin.x      = std::min(areaMin.x, pointV.x);
-                                                                      areaMin.y      = std::min(areaMin.y, pointV.y);
-                                                                      areaMin.z      = std::min(areaMin.z, pointV.z);
-                                                                      areaMax.x      = std::max(areaMax.x, pointV.x);
-                                                                      areaMax.y      = std::max(areaMax.y, pointV.y);
-                                                                      areaMax.z      = std::max(areaMax.z, pointV.z);
-                                                                    }
-
-                                                                    Vector2 center        = Vector2(areaMax + areaMin) * 0.5;
-                                                                    float   delta         = std::max(std::abs(areaMax.x - areaMin.x), std::abs(areaMax.y - areaMin.y));
-                                                                    float   delta_2       = delta * 0.5f;
-                                                                    Vector2 squareAreaMin = center - Vector2::ONE * delta_2;
-                                                                    Vector2 squareAreaMax = center + Vector2::ONE * delta_2;
-                                                                    float   deltaZ        = areaMax.z - areaMin.z;
-
-                                                                    float right  = -squareAreaMin.x;
-                                                                    float left   = -squareAreaMax.x;
-                                                                    float top    = squareAreaMin.y;
-                                                                    float bottom = squareAreaMax.y;
-                                                                    float near   = areaMin.z;
-                                                                    float far    = areaMax.z;
-
-                                                                    float* projMatrix = output.AsFloat();
-
-                                                                    projMatrix[0] = -2.0f / delta;
-                                                                    projMatrix[1] = 0.0f;
-                                                                    projMatrix[2] = 0.0f;
-                                                                    projMatrix[3] = 0.0f;
-
-                                                                    projMatrix[4] = 0.0f;
-                                                                    projMatrix[5] = -2.0f / delta;
-                                                                    projMatrix[6] = 0.0f;
-                                                                    projMatrix[7] = 0.0f;
-
-                                                                    projMatrix[8]  = 0.0f;
-                                                                    projMatrix[9]  = 0.0f;
-                                                                    projMatrix[10] = 2.0f / deltaZ;
-                                                                    projMatrix[11] = 0.0f;
-
-                                                                    projMatrix[12] = -(right + left) / delta;
-                                                                    projMatrix[13] = -(top + bottom) / delta;
-                                                                    projMatrix[14] = -(near + far) / deltaZ;
-                                                                    projMatrix[15] = 1.0f;
-
-                                                                    output = output * shadowCameraViewMatrix;
-                                                                  });
+  auto       tempViewProjectionMatrixIndex = shadowLightCamera.RegisterProperty("tempViewProjectionMatrix", Matrix::IDENTITY);
+  Constraint projectionMatrixConstraint    = Constraint::New<Matrix>(shadowLightCamera, tempViewProjectionMatrixIndex, [](Matrix& output, const PropertyInputContainer& inputs) {
+    Matrix worldMatrix  = inputs[0]->GetMatrix();
+    float  tangentFov_2 = tanf(inputs[4]->GetFloat());
+    float  nearDistance = inputs[5]->GetFloat();
+    float  farDistance  = inputs[6]->GetFloat();
+    float  aspectRatio  = inputs[7]->GetFloat();
+    float  nearY        = 0.0f;
+    float  nearX        = 0.0f;
+    float  farY         = 0.0f;
+    float  farX         = 0.0f;
+    if(inputs[1]->GetInteger() == Dali::Camera::ProjectionMode::PERSPECTIVE_PROJECTION)
+    {
+      if(inputs[2]->GetInteger() == Dali::DevelCameraActor::ProjectionDirection::VERTICAL)
+      {
+        nearY = tangentFov_2 * nearDistance;
+        nearX = nearY * aspectRatio;
+        farY  = tangentFov_2 * farDistance;
+        farX  = farY * aspectRatio;
+      }
+      else
+      {
+        nearX = tangentFov_2 * nearDistance;
+        nearY = nearX / aspectRatio;
+        farX  = tangentFov_2 * farDistance;
+        farY  = farX / aspectRatio;
+      }
+    }
+    else
+    {
+      if(inputs[2]->GetInteger() == Dali::DevelCameraActor::ProjectionDirection::VERTICAL)
+      {
+        nearY = inputs[3]->GetFloat();
+        nearX = nearY * aspectRatio;
+      }
+      else
+      {
+        nearX = inputs[3]->GetFloat();
+        nearY = nearX / aspectRatio;
+      }
+      farX = nearX;
+      farY = nearY;
+    }
+
+    std::vector<Vector4> points;
+    points.push_back(Vector4(nearX, nearY, nearDistance, 1.0f));
+    points.push_back(Vector4(-nearX, nearY, nearDistance, 1.0f));
+    points.push_back(Vector4(-nearX, -nearY, nearDistance, 1.0f));
+    points.push_back(Vector4(nearX, -nearY, nearDistance, 1.0f));
+    points.push_back(Vector4(farX, farY, farDistance, 1.0f));
+    points.push_back(Vector4(-farX, farY, farDistance, 1.0f));
+    points.push_back(Vector4(-farX, -farY, farDistance, 1.0f));
+    points.push_back(Vector4(farX, -farY, farDistance, 1.0f));
+
+    Matrix  shadowCameraWorldMatrix = inputs[8]->GetMatrix();
+    Vector4 worldCenter;
+    for(auto&& point : points)
+    {
+      point = worldMatrix * point;
+      worldCenter += point;
+    }
+    worldCenter /= 8.0f;
+    shadowCameraWorldMatrix.SetTranslation(Vector3(worldCenter));
+    Matrix shadowCameraViewMatrix = shadowCameraWorldMatrix;
+    shadowCameraViewMatrix.Invert();
+
+    Vector3 areaMin = Vector3::ONE * MAXFLOAT, areaMax = Vector3::ONE * -MAXFLOAT;
+    for(auto&& point : points)
+    {
+      Vector4 pointV = shadowCameraViewMatrix * point;
+      areaMin.x      = std::min(areaMin.x, pointV.x);
+      areaMin.y      = std::min(areaMin.y, pointV.y);
+      areaMin.z      = std::min(areaMin.z, pointV.z);
+      areaMax.x      = std::max(areaMax.x, pointV.x);
+      areaMax.y      = std::max(areaMax.y, pointV.y);
+      areaMax.z      = std::max(areaMax.z, pointV.z);
+    }
+
+    Vector2 center        = Vector2(areaMax + areaMin) * 0.5;
+    float   delta         = std::max(std::abs(areaMax.x - areaMin.x), std::abs(areaMax.y - areaMin.y));
+    float   delta_2       = delta * 0.5f;
+    Vector2 squareAreaMin = center - Vector2::ONE * delta_2;
+    Vector2 squareAreaMax = center + Vector2::ONE * delta_2;
+    float   deltaZ        = areaMax.z - areaMin.z;
+
+    float right  = -squareAreaMin.x;
+    float left   = -squareAreaMax.x;
+    float top    = squareAreaMin.y;
+    float bottom = squareAreaMax.y;
+    float near   = areaMin.z;
+    float far    = areaMax.z;
+
+    float* projMatrix = output.AsFloat();
+
+    projMatrix[0] = -2.0f / delta;
+    projMatrix[1] = 0.0f;
+    projMatrix[2] = 0.0f;
+    projMatrix[3] = 0.0f;
+
+    projMatrix[4] = 0.0f;
+    projMatrix[5] = -2.0f / delta;
+    projMatrix[6] = 0.0f;
+    projMatrix[7] = 0.0f;
+
+    projMatrix[8]  = 0.0f;
+    projMatrix[9]  = 0.0f;
+    projMatrix[10] = 2.0f / deltaZ;
+    projMatrix[11] = 0.0f;
+
+    projMatrix[12] = -(right + left) / delta;
+    projMatrix[13] = -(top + bottom) / delta;
+    projMatrix[14] = -(near + far) / deltaZ;
+    projMatrix[15] = 1.0f;
+
+    output = output * shadowCameraViewMatrix;
+  });
   projectionMatrixConstraint.AddSource(Source{selectedCamera, Dali::Actor::Property::WORLD_MATRIX});
   projectionMatrixConstraint.AddSource(Source{selectedCamera, Dali::CameraActor::Property::PROJECTION_MODE});
   projectionMatrixConstraint.AddSource(Source{selectedCamera, Dali::DevelCameraActor::Property::PROJECTION_DIRECTION});
@@ -622,8 +621,7 @@ void SceneView::SetShadow(Scene3D::Light light)
     return;
   }
 
-  auto foundLight = std::find_if(mLights.begin(), mLights.end(), [light](std::pair<Scene3D::Light, bool> lightEntity) -> bool
-                                 { return (lightEntity.second && lightEntity.first == light); });
+  auto foundLight = std::find_if(mLights.begin(), mLights.end(), [light](std::pair<Scene3D::Light, bool> lightEntity) -> bool { return (lightEntity.second && lightEntity.first == light); });
 
   if(foundLight == mLights.end())
   {
@@ -638,7 +636,7 @@ void SceneView::SetShadow(Scene3D::Light light)
   SetShadowLightConstraint(selectedCamera, lightCamera);
 
   // make framebuffer for depth map and set it to render task.
-  Vector3  size               = Self().GetProperty<Vector3>(Dali::Actor::Property::SIZE);
+  Vector3  size                = Self().GetProperty<Vector3>(Dali::Actor::Property::SIZE);
   uint32_t shadowMapBufferSize = std::min(static_cast<uint32_t>(std::max(size.width, size.height)), MAXIMUM_SIZE_SHADOW_MAP);
   UpdateShadowMapBuffer(shadowMapBufferSize);
 
@@ -1112,12 +1110,7 @@ void SceneView::OnSkyboxLoadComplete()
   }
 
   mSkyboxResourceReady = true;
-  if(IsResourceReady())
-  {
-    Control::SetResourceReady();
-  }
-
-  mSkyboxTexture = mSkyboxLoadTask->GetLoadedTexture();
+  mSkyboxTexture       = mSkyboxLoadTask->GetLoadedTexture();
   Shader skyboxShader;
   if(mSkyboxLoadTask->GetEnvironmentMapType() == Scene3D::EnvironmentMapType::CUBEMAP)
   {
@@ -1138,17 +1131,22 @@ void SceneView::OnSkyboxLoadComplete()
   }
 
   mSkyboxLoadTask.Reset();
+
+  if(IsResourceReady())
+  {
+    Control::SetResourceReady();
+  }
 }
 
 void SceneView::OnIblDiffuseLoadComplete()
 {
   mDiffuseTexture          = mIblDiffuseLoadTask->GetLoadedTexture();
   mIblDiffuseResourceReady = true;
+  mIblDiffuseLoadTask.Reset();
   if(mIblDiffuseResourceReady && mIblSpecularResourceReady)
   {
     OnIblLoadComplete();
   }
-  mIblDiffuseLoadTask.Reset();
 }
 
 void SceneView::OnIblSpecularLoadComplete()
@@ -1156,11 +1154,11 @@ void SceneView::OnIblSpecularLoadComplete()
   mSpecularTexture          = mIblSpecularLoadTask->GetLoadedTexture();
   mSpecularMipmapLevels     = mIblSpecularLoadTask->GetMipmapLevels();
   mIblSpecularResourceReady = true;
+  mIblSpecularLoadTask.Reset();
   if(mIblDiffuseResourceReady && mIblSpecularResourceReady)
   {
     OnIblLoadComplete();
   }
-  mIblSpecularLoadTask.Reset();
 }
 
 void SceneView::OnIblLoadComplete()
index 382ef2321e6aa26123fb673949c70f4d1d8fd556..fed5316c9af8f4b8aebf6d9553d3e48620d71295 100644 (file)
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2022 Samsung Electronics Co., Ltd.
+* Copyright (c) 2023 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.
@@ -21,6 +21,9 @@
 // EXTERNAL INCLUDES
 #include <dali/integration-api/debug.h>
 
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/visuals/npatch-data.h>
+
 namespace Dali
 {
 namespace Toolkit
@@ -250,7 +253,7 @@ void RegisterStretchProperties(Renderer& renderer, const char* uniformName, cons
   }
 }
 
-void ApplyTextureAndUniforms(Renderer& renderer, const std::shared_ptr<const Internal::NPatchData> data)
+void ApplyTextureAndUniforms(Renderer& renderer, const Internal::NPatchData* data)
 {
   TextureSet textureSet;
   textureSet = data->GetTextures();
index 242706336eb4463b5858987816a701bb1d7cae0b..da1f55a3fbf6c99a737aeff7a4164fc944628190 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_NPATCH_HELPER_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
  */
 
 // EXTERNAL INCLUDES
+#include <dali/devel-api/rendering/renderer-devel.h>
 #include <dali/public-api/math/uint-16-pair.h>
 #include <dali/public-api/rendering/geometry.h>
-#include <dali/devel-api/rendering/renderer-devel.h>
-#include <memory> ///< for std::shared_ptr
 
 // INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/utility/npatch-utilities.h>
 #include <dali-toolkit/public-api/dali-toolkit-common.h>
-#include <dali-toolkit/internal/visuals/npatch-data.h>
 
 namespace Dali
 {
 namespace Toolkit
 {
-namespace NPatchHelper
+namespace Internal
 {
-/**
- * The list that includes stretch pixel ranges
- */
-using StretchRanges = Dali::Vector<Uint16Pair>;
+class NPatchData;
+}
 
+namespace NPatchHelper
+{
 /**
  * @brief Creates a Npatch Geometry object
  *
@@ -70,7 +69,6 @@ DALI_TOOLKIT_API Geometry CreateGridGeometry(Uint16Pair gridSize);
  */
 DALI_TOOLKIT_API Geometry CreateBorderGeometry(Uint16Pair gridSize);
 
-
 /**
  * @brief Registers a properties for Stretch Ranges
  *
@@ -87,9 +85,9 @@ void RegisterStretchProperties(Renderer& renderer, const char* uniformName, cons
  * @param[in,out] renderer The renderer for broken image
  * @param[in] data The pointer of npatch-data
  */
-void ApplyTextureAndUniforms(Renderer& renderer, const std::shared_ptr<const Internal::NPatchData> data);
+void ApplyTextureAndUniforms(Renderer& renderer, const Internal::NPatchData* data);
 
-} // namespace NPatchUtility
+} // namespace NPatchHelper
 
 } // namespace Toolkit
 
index dce31096010f8e497931f178f7601fe0f14949d1..7fca5cf60c3ef2b6d7291920cf1f15c784a1c9f9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
@@ -116,6 +116,11 @@ void VisualFactory::UsePreCompiledShader()
   GetImplementation(*this).UsePreCompiledShader();
 }
 
+void VisualFactory::DiscardVisual(Visual::Base visual)
+{
+  GetImplementation(*this).DiscardVisual(visual);
+}
+
 } // namespace Toolkit
 
 } // namespace Dali
index bf861f7460d4a6bb4c1ff6447296a70445b7a88e..a7919f4afe9fc8fba0fc50188c31b9d82a127744 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_VISUAL_FACTORY_H
 
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
@@ -137,6 +137,13 @@ public:
    */
   void UsePreCompiledShader();
 
+  /**
+   * @brief Discard visual base. It will keep reference of visual until idle callback called.
+   *
+   * @param[in] visual Discarded visual base.
+   */
+  void DiscardVisual(Visual::Base visual);
+
 private:
   explicit DALI_INTERNAL VisualFactory(Internal::VisualFactory* impl);
 };
index a151d115baf1318447c9c3500420d26e058a771f..c33ae6e681243cc5ab428e26127bea2c2260e07d 100644 (file)
@@ -232,6 +232,23 @@ void MoveVisual(RegisteredVisualContainer::Iterator sourceIter, RegisteredVisual
   }
 }
 
+/**
+ * Discard visual from source to visual factory.
+ */
+void DiscardVisual(RegisteredVisualContainer::Iterator sourceIter, RegisteredVisualContainer& source)
+{
+  Toolkit::Visual::Base visual = (*sourceIter)->visual;
+  if(visual)
+  {
+    if(Stage::IsInstalled())
+    {
+      Toolkit::VisualFactory::Get().DiscardVisual(visual);
+    }
+  }
+
+  source.Erase(sourceIter);
+}
+
 /**
  * Performs actions as requested using the action name.
  * @param[in] object The object on which to perform the action.
@@ -873,8 +890,9 @@ void Control::Impl::UnregisterVisual(Property::Index index)
     Actor self(mControlImpl.Self());
     Toolkit::GetImplementation((*iter)->visual).SetOffScene(self);
     (*iter)->pending = false;
-    (*iter)->visual.Reset();
-    mRemoveVisuals.Erase(iter);
+
+    // Discard removed visual. It will be destroyed at next Idle time.
+    DiscardVisual(iter, mRemoveVisuals);
   }
 }
 
@@ -1005,7 +1023,9 @@ void Control::Impl::ResourceReady(Visual::Base& object)
     {
       Toolkit::GetImplementation((*visualToRemoveIter)->visual).SetOffScene(self);
     }
-    mRemoveVisuals.Erase(visualToRemoveIter);
+
+    // Discard removed visual. It will be destroyed at next Idle time.
+    DiscardVisual(visualToRemoveIter, mRemoveVisuals);
   }
 
   // A visual is ready so control may need relayouting if staged
@@ -2001,17 +2021,25 @@ void Control::Impl::OnSceneDisconnection()
 
   // Visuals pending replacement can now be taken out of the removal list and set off scene
   // Iterate through all replacement visuals and add to a move queue then set off scene
-  for(auto removalIter = mRemoveVisuals.Begin(), end = mRemoveVisuals.End(); removalIter != end; removalIter++)
+
+  if(!mRemoveVisuals.Empty())
   {
-    Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self);
+    std::reverse(mRemoveVisuals.Begin(), mRemoveVisuals.End());
+
+    while(!mRemoveVisuals.Empty())
+    {
+      auto removalIter = mRemoveVisuals.End() - 1u;
+      Toolkit::GetImplementation((*removalIter)->visual).SetOffScene(self);
+
+      // Discard removed visual. It will be destroyed at next Idle time.
+      DiscardVisual(removalIter, mRemoveVisuals);
+    }
   }
 
   for(auto replacedIter = mVisuals.Begin(), end = mVisuals.End(); replacedIter != end; replacedIter++)
   {
     (*replacedIter)->pending = false;
   }
-
-  mRemoveVisuals.Clear();
 }
 
 void Control::Impl::SetMargin(Extents margin)
index abe558129febf2f89959a7f4a1b296d47a85e086..370a6787360b67cc652f978692df14ce080d7059 100644 (file)
@@ -362,6 +362,8 @@ void RollingAnimatedImageCache::LoadComplete(bool loadSuccess, TextureInformatio
 
   MakeFrameReady(loadSuccess, textureInformation.textureSet, textureInformation.interval, textureInformation.preMultiplied);
 
+  // TODO : We need to remove some below logics, since user can remove Visual during ResourceReady callback.
+
   if(loadSuccess)
   {
     // The frames of a single animated image can not be loaded parallelly.
index 4f093ad5e794be70ca1588c253389b2c08b178f9..e56bba2e535bb6510fa0652dd2c97002e6ff856e 100644 (file)
@@ -628,14 +628,14 @@ void AnimatedVectorImageVisual::OnResourceReady(VectorAnimationTask::ResourceSta
 
 void AnimatedVectorImageVisual::OnAnimationFinished()
 {
-  AnimatedVectorImageVisualPtr self = this; // Keep reference until this API finished
-
   if(DALI_UNLIKELY(mImpl == nullptr))
   {
     DALI_LOG_ERROR("Fatal error!! already destroyed object callback called! AnimatedVectorImageVisual : %p, url : %s\n", this, mUrl.GetUrl().c_str());
     return;
   }
 
+  AnimatedVectorImageVisualPtr self = this; // Keep reference until this API finished
+
   DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "AnimatedVectorImageVisual::OnAnimationFinished: action state = %d [%p]\n", mPlayState, this);
 
   if(mPlayState != DevelImageVisual::PlayState::STOPPED)
index 72f058bc047855ce55b245f177ff3337b9c5edac..28c3ebd954f52a69ea809a70d5677dd231897e87 100644 (file)
@@ -19,7 +19,6 @@
 #include <dali-toolkit/internal/visuals/npatch-data.h>
 
 // INTERNAL HEADERS
-#include <dali-toolkit/internal/visuals/npatch-loader.h> ///< for NPatchLoader
 #include <dali-toolkit/internal/visuals/rendering-addon.h>
 
 // EXTERNAL HEADERS
@@ -31,9 +30,8 @@ namespace Toolkit
 {
 namespace Internal
 {
-NPatchData::NPatchData(NPatchLoader& loader)
+NPatchData::NPatchData()
 : mId(INVALID_NPATCH_DATA_ID),
-  mNPatchLoader(loader),
   mUrl(),
   mTextureSet(),
   mHash(0),
@@ -259,8 +257,7 @@ void NPatchData::NotifyObserver(TextureUploadObserver* observer, const bool& loa
 
 void NPatchData::LoadComplete(bool loadSuccess, TextureInformation textureInformation)
 {
-  // Increase reference count of itself
-  mNPatchLoader.IncreaseReference(mId);
+  NPatchDataPtr self = this; // Keep reference until this API finished
 
   if(loadSuccess)
   {
@@ -305,9 +302,6 @@ void NPatchData::LoadComplete(bool loadSuccess, TextureInformation textureInform
   // (If mLoadingState was LOAD_COMPLETE, NotifyObserver will be called directly. @todo : Should we fix this logic, matched with texture manager?)
   // So LoadComplete will be called.
   mObserverList.Swap(mQueuedObservers);
-
-  // Decrease reference count of itself
-  mNPatchLoader.RequestRemove(mId, nullptr);
 }
 
 void NPatchData::ObserverDestroyed(TextureUploadObserver* observer)
index f50392bfbf29d455df8c841777c1daf843e76008..99c4d08147312f8f5c6c8a4cdb785263e272151b 100644 (file)
@@ -19,6 +19,7 @@
 
 // EXTERNAL INCLUDES
 #include <dali/devel-api/adaptor-framework/pixel-buffer.h>
+#include <dali/public-api/object/ref-object.h>
 #include <dali/public-api/rendering/texture-set.h>
 #include <string>
 
@@ -33,9 +34,10 @@ namespace Toolkit
 {
 namespace Internal
 {
-class NPatchLoader;
+class NPatchData;
+typedef IntrusivePtr<NPatchData> NPatchDataPtr;
 
-class NPatchData : public ConnectionTracker, public Dali::Toolkit::TextureUploadObserver
+class NPatchData : public ConnectionTracker, public Dali::Toolkit::TextureUploadObserver, public Dali::RefObject
 {
 public:
   typedef int32_t           NPatchDataId;                ///< The NPatchDataId type. This is used as a handle to refer to a particular Npatch Data.
@@ -55,10 +57,8 @@ public:
 public:
   /**
    * Constructor
-   *
-   * @param[in] loader NPatchLoader who create this data.
    */
-  NPatchData(NPatchLoader& loader);
+  NPatchData();
 
   /**
    * Destructor, non-virtual as not a base class
@@ -286,7 +286,6 @@ private:
   NPatchDataId     mId;
   ObserverListType mObserverList;    ///< Container used to store all observer clients of this Texture
   ObserverListType mQueuedObservers; ///< Container observers when user try to add during notify observers
-  NPatchLoader&    mNPatchLoader;    ///< NPatchLoader who keep this data
 
   VisualUrl                    mUrl;            ///< Url of the N-Patch
   TextureSet                   mTextureSet;     ///< Texture containing the cropped image
index 340188b5ceb4b33e099dae4230b146eed4a7f07e..16b49beec7867709629c9c4160b1eec85ac9eb73 100644 (file)
@@ -66,9 +66,9 @@ NPatchData::NPatchDataId NPatchLoader::GenerateUniqueNPatchDataId()
 
 NPatchData::NPatchDataId NPatchLoader::Load(TextureManager& textureManager, TextureUploadObserver* textureObserver, const VisualUrl& url, const Rect<int>& border, bool& preMultiplyOnLoad, bool synchronousLoading)
 {
-  std::shared_ptr<NPatchData> data = GetNPatchData(url, border, preMultiplyOnLoad);
+  NPatchDataPtr data = GetNPatchData(url, border, preMultiplyOnLoad);
 
-  DALI_ASSERT_ALWAYS(data.get() && "NPatchData creation failed!");
+  DALI_ASSERT_ALWAYS(data.Get() && "NPatchData creation failed!");
 
   if(data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
   {
@@ -97,7 +97,7 @@ NPatchData::NPatchDataId NPatchLoader::Load(TextureManager& textureManager, Text
     auto preMultiplyOnLoading = preMultiplyOnLoad ? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD
                                                   : TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
 
-    Devel::PixelBuffer pixelBuffer = textureManager.LoadPixelBuffer(url, Dali::ImageDimensions(), FittingMode::DEFAULT, SamplingMode::BOX_THEN_LINEAR, synchronousLoading, data.get(), true, preMultiplyOnLoading);
+    Devel::PixelBuffer pixelBuffer = textureManager.LoadPixelBuffer(url, Dali::ImageDimensions(), FittingMode::DEFAULT, SamplingMode::BOX_THEN_LINEAR, synchronousLoading, data.Get(), true, preMultiplyOnLoading);
 
     if(pixelBuffer)
     {
@@ -127,7 +127,7 @@ int32_t NPatchLoader::GetCacheIndexFromId(const NPatchData::NPatchDataId id)
   return INVALID_CACHE_INDEX;
 }
 
-bool NPatchLoader::GetNPatchData(const NPatchData::NPatchDataId id, std::shared_ptr<const NPatchData>& data)
+bool NPatchLoader::GetNPatchData(const NPatchData::NPatchDataId id, NPatchDataPtr& data)
 {
   int32_t cacheIndex = GetCacheIndexFromId(id);
   if(cacheIndex != INVALID_CACHE_INDEX)
@@ -162,19 +162,6 @@ void NPatchLoader::RequestRemove(NPatchData::NPatchDataId id, TextureUploadObser
   }
 }
 
-void NPatchLoader::IncreaseReference(NPatchData::NPatchDataId id)
-{
-  int32_t cacheIndex = GetCacheIndexFromId(id);
-  if(cacheIndex == INVALID_CACHE_INDEX)
-  {
-    return;
-  }
-
-  NPatchInfo& info(mCache[cacheIndex]);
-
-  ++info.mReferenceCount;
-}
-
 void NPatchLoader::Remove(NPatchData::NPatchDataId id, TextureUploadObserver* textureObserver)
 {
   int32_t cacheIndex = GetCacheIndexFromId(id);
@@ -208,7 +195,7 @@ void NPatchLoader::Process(bool postProcessor)
   }
 }
 
-std::shared_ptr<NPatchData> NPatchLoader::GetNPatchData(const VisualUrl& url, const Rect<int>& border, bool& preMultiplyOnLoad)
+NPatchDataPtr NPatchLoader::GetNPatchData(const VisualUrl& url, const Rect<int>& border, bool& preMultiplyOnLoad)
 {
   std::size_t                              hash  = CalculateHash(url.GetUrl());
   std::vector<NPatchInfo>::size_type       index = UNINITIALIZED_ID;
@@ -260,7 +247,7 @@ std::shared_ptr<NPatchData> NPatchLoader::GetNPatchData(const VisualUrl& url, co
   // If this is new image loading, make new cache data
   if(infoPtr == nullptr)
   {
-    NPatchInfo info(std::make_shared<NPatchData>(*this));
+    NPatchInfo info(new NPatchData());
     info.mData->SetId(GenerateUniqueNPatchDataId());
     info.mData->SetHash(hash);
     info.mData->SetUrl(url);
@@ -273,7 +260,7 @@ std::shared_ptr<NPatchData> NPatchLoader::GetNPatchData(const VisualUrl& url, co
   // Else if LOAD_COMPLETE, Same url but border is different - use the existing texture
   else if(infoPtr->mData->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
   {
-    NPatchInfo info(std::make_shared<NPatchData>(*this));
+    NPatchInfo info(new NPatchData());
 
     info.mData->SetId(GenerateUniqueNPatchDataId());
     info.mData->SetHash(hash);
index 59e52dc97eba65958b754b25446470fdda581ded..5890326e505eba9466553a8f0f9186332dfc3ee5 100644 (file)
@@ -21,7 +21,6 @@
 #include <dali/devel-api/adaptor-framework/pixel-buffer.h>
 #include <dali/integration-api/processor-interface.h>
 #include <dali/public-api/rendering/texture-set.h>
-#include <memory> // for std::shared_ptr
 #include <string>
 #include <utility> // for std::pair
 
@@ -79,7 +78,7 @@ public:
    * @param [out] data const pointer to the NPatchData
    * @return true if data matching to id was really found
    */
-  bool GetNPatchData(const NPatchData::NPatchDataId id, std::shared_ptr<const NPatchData>& data);
+  bool GetNPatchData(const NPatchData::NPatchDataId id, NPatchDataPtr& data);
 
   /**
    * @brief Request remove a texture matching id.
@@ -90,13 +89,6 @@ public:
    */
   void RequestRemove(NPatchData::NPatchDataId id, TextureUploadObserver* textureObserver);
 
-  /**
-   * @brief Increase reference count of a texture matching id.
-   *
-   * @param [in] id cache data id
-   */
-  void IncreaseReference(NPatchData::NPatchDataId id);
-
 protected: // Implementation of Processor
   /**
    * @copydoc Dali::Integration::Processor::Process()
@@ -126,7 +118,7 @@ private:
    */
   struct NPatchInfo
   {
-    NPatchInfo(std::shared_ptr<NPatchData> data)
+    NPatchInfo(NPatchDataPtr data)
     : mData(data),
       mReferenceCount(1u)
     {
@@ -152,8 +144,8 @@ private:
     NPatchInfo(const NPatchInfo& info) = delete;            // Do not use copy constructor
     NPatchInfo& operator=(const NPatchInfo& info) = delete; // Do not use copy assign
 
-    std::shared_ptr<NPatchData> mData;
-    std::int16_t                mReferenceCount; ///< The number of N-patch visuals that use this data.
+    NPatchDataPtr mData;
+    std::int16_t  mReferenceCount; ///< The number of N-patch visuals that use this data.
   };
 
   /**
@@ -166,7 +158,7 @@ private:
    *                                   image has no alpha channel
    * @return NPatchData pointer that Load function will used.
    */
-  std::shared_ptr<NPatchData> GetNPatchData(const VisualUrl& url, const Rect<int>& border, bool& preMultiplyOnLoad);
+  NPatchDataPtr GetNPatchData(const VisualUrl& url, const Rect<int>& border, bool& preMultiplyOnLoad);
 
 protected:
   /**
index 606e040fa539547708cdb574269667c393082415..e469297a904c6d07f4a1f4e95db840bd2e284784 100644 (file)
@@ -80,7 +80,7 @@ void NPatchVisual::LoadImages()
     bool preMultiplyOnLoad = IsPreMultipliedAlphaEnabled() && !mImpl->mCustomShader ? true : false;
     mId                    = mLoader.Load(textureManager, this, mImageUrl, mBorder, preMultiplyOnLoad, synchronousLoading);
 
-    std::shared_ptr<const NPatchData> data;
+    NPatchDataPtr data;
     if(mLoader.GetNPatchData(mId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
     {
       EnablePreMultipliedAlpha(data->IsPreMultiplied());
@@ -126,7 +126,7 @@ void NPatchVisual::GetNaturalSize(Vector2& naturalSize)
   naturalSize.y = 0u;
 
   // load now if not already loaded
-  std::shared_ptr<const NPatchData> data;
+  NPatchDataPtr data;
   if(mLoader.GetNPatchData(mId, data) && data->GetLoadingState() != NPatchData::LoadingState::LOADING)
   {
     naturalSize.x = data->GetCroppedWidth();
@@ -223,7 +223,7 @@ void NPatchVisual::DoSetOnScene(Actor& actor)
   // at this case, we try to SetResouce to mPlaceActor twice. so, we should avoid that case.
   mPlacementActor = actor;
 
-  std::shared_ptr<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.
@@ -338,9 +338,9 @@ NPatchVisual::~NPatchVisual()
 void NPatchVisual::OnInitialize()
 {
   // Get basic geometry and shader
-  Geometry geometry = mFactoryCache.GetGeometry(VisualFactoryCache::QUAD_GEOMETRY);
-  auto imageVisualShaderFeatureBuilder = ImageVisualShaderFeatureBuilder();
-  Shader   shader   = mImageVisualShaderFactory.GetShader(
+  Geometry geometry                        = mFactoryCache.GetGeometry(VisualFactoryCache::QUAD_GEOMETRY);
+  auto     imageVisualShaderFeatureBuilder = ImageVisualShaderFeatureBuilder();
+  Shader   shader                          = mImageVisualShaderFactory.GetShader(
     mFactoryCache,
     imageVisualShaderFeatureBuilder);
 
@@ -353,8 +353,8 @@ void NPatchVisual::OnInitialize()
 
 Geometry NPatchVisual::CreateGeometry()
 {
-  Geometry                          geometry;
-  std::shared_ptr<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)
@@ -408,8 +408,8 @@ Geometry NPatchVisual::CreateGeometry()
 
 Shader NPatchVisual::CreateShader()
 {
-  Shader                            shader;
-  std::shared_ptr<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;
@@ -488,13 +488,13 @@ Shader NPatchVisual::CreateShader()
 
 void NPatchVisual::ApplyTextureAndUniforms()
 {
-  std::shared_ptr<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(mAuxiliaryResourceStatus == Toolkit::Visual::ResourceStatus::READY)
     {
@@ -551,7 +551,7 @@ Geometry NPatchVisual::GetNinePatchGeometry(VisualFactoryCache::GeometryType sub
 
 void NPatchVisual::SetResource()
 {
-  std::shared_ptr<const NPatchData> data;
+  NPatchDataPtr data;
   if(mImpl->mRenderer && mLoader.GetNPatchData(mId, data))
   {
     Geometry geometry = CreateGeometry();
@@ -628,7 +628,7 @@ void NPatchVisual::LoadComplete(bool loadSuccess, TextureInformation textureInfo
   // If auxiliaryUrl didn't required OR auxiliaryUrl load done.
   if(!mAuxiliaryUrl.IsValid() || mAuxiliaryResourceStatus != Toolkit::Visual::ResourceStatus::PREPARING)
   {
-    std::shared_ptr<const NPatchData> data;
+    NPatchDataPtr data;
     // and.. If Url loading done.
     if(mImpl->mRenderer && mLoader.GetNPatchData(mId, data) && data->GetLoadingState() != NPatchData::LoadingState::LOADING)
     {
index 60c21415f0dfaea7b9598be025ea9bab3549c3e4..8bf94abcf2a27d57eb4611615843b8ca118d8b04 100644 (file)
@@ -337,13 +337,12 @@ void SvgVisual::AddRasterizationTask(const Vector2& size)
 
 void SvgVisual::ApplyRasterizedImage(SvgTaskPtr task)
 {
-  SvgVisualPtr self = this; // Keep reference until this API finished
-
   if(DALI_UNLIKELY(mImpl == nullptr))
   {
     DALI_LOG_ERROR("Fatal error!! already destroyed object callback called! SvgVisual : %p, url : %s, task : %p\n", this, mImageUrl.GetUrl().c_str(), task.Get());
     return;
   }
+  SvgVisualPtr self = this; // Keep reference until this API finished
 
   // We don't need to keep tasks anymore. reset now.
   if(task == mLoadingTask)
index 9437bdc2e101e3a1c923b7b4e954fb8fc5329f06..69fbbad6e2a50ff9fedbb7b1f36b2124bbdd7371 100644 (file)
@@ -272,8 +272,8 @@ VisualUrl::Type VisualFactoryCache::GetBrokenImageVisualType(int index)
 
 Geometry VisualFactoryCache::GetNPatchGeometry(int index)
 {
-  Geometry                          geometry;
-  std::shared_ptr<const NPatchData> data;
+  Geometry      geometry;
+  NPatchDataPtr data;
   if(mNPatchLoader.GetNPatchData(mBrokenImageInfoContainer[index].npatchId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
   {
     if(data->GetStretchPixelsX().Size() == 1 && data->GetStretchPixelsY().Size() == 1)
@@ -306,8 +306,8 @@ Geometry VisualFactoryCache::GetNPatchGeometry(int index)
 
 Shader VisualFactoryCache::GetNPatchShader(int index)
 {
-  Shader                            shader;
-  std::shared_ptr<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;
@@ -344,13 +344,13 @@ Shader VisualFactoryCache::GetNPatchShader(int index)
 
 void VisualFactoryCache::ApplyTextureAndUniforms(Renderer& renderer, int index)
 {
-  std::shared_ptr<const NPatchData> data;
-  TextureSet                        textureSet;
+  NPatchDataPtr data;
+  TextureSet    textureSet;
   if(mNPatchLoader.GetNPatchData(mBrokenImageInfoContainer[index].npatchId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
   {
     textureSet                               = data->GetTextures();
     mBrokenImageInfoContainer[index].texture = textureSet.GetTexture(0);
-    NPatchHelper::ApplyTextureAndUniforms(renderer, data);
+    NPatchHelper::ApplyTextureAndUniforms(renderer, data.Get());
     renderer.SetTextures(textureSet);
   }
 }
@@ -374,8 +374,8 @@ void VisualFactoryCache::UpdateBrokenImageRenderer(Renderer& renderer, const Vec
         mBrokenImageInfoContainer[index].visualType = visualUrl.GetType();
         if(mBrokenImageInfoContainer[index].visualType == VisualUrl::Type::N_PATCH)
         {
-          std::shared_ptr<const NPatchData> data;
-          Rect<int>                         border;
+          NPatchDataPtr data;
+          Rect<int>     border;
           mBrokenImageInfoContainer[index].npatchId = mNPatchLoader.Load(mTextureManager, NULL, mBrokenImageInfoContainer[index].url, border, mPreMultiplyOnLoad, true);
           if(mNPatchLoader.GetNPatchData(mBrokenImageInfoContainer[index].npatchId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
           {
index 4656e596822e7f182779d5aba58be5f0dd59a124..9f9eb2a9d5b57077b1ff07f9141551b7957949e1 100644 (file)
@@ -19,6 +19,7 @@
 
 // EXTERNAL INCLUDES
 #include <dali/devel-api/scripting/scripting.h>
+#include <dali/integration-api/adaptor-framework/adaptor.h>
 #include <dali/integration-api/debug.h>
 #include <dali/public-api/object/property-array.h>
 #include <dali/public-api/object/type-registry-helper.h>
@@ -28,6 +29,7 @@
 #include <dali-toolkit/devel-api/asset-manager/asset-manager.h>
 #include <dali-toolkit/devel-api/styling/style-manager-devel.h>
 #include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
+#include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
 #include <dali-toolkit/internal/visuals/animated-gradient/animated-gradient-visual.h>
 #include <dali-toolkit/internal/visuals/animated-image/animated-image-visual.h>
 #include <dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.h>
@@ -41,7 +43,6 @@
 #include <dali-toolkit/internal/visuals/npatch/npatch-visual.h>
 #include <dali-toolkit/internal/visuals/primitive/primitive-visual.h>
 #include <dali-toolkit/internal/visuals/svg/svg-visual.h>
-#include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
 #include <dali-toolkit/internal/visuals/text-visual-shader-factory.h>
 #include <dali-toolkit/internal/visuals/text/text-visual.h>
 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
@@ -52,7 +53,6 @@
 #include <dali-toolkit/public-api/visuals/text-visual-properties.h>
 #include <dali-toolkit/public-api/visuals/visual-properties.h>
 
-
 namespace Dali
 {
 namespace Toolkit
@@ -76,15 +76,13 @@ DALI_TYPE_REGISTRATION_BEGIN_CREATE(Toolkit::VisualFactory, Dali::BaseHandle, Cr
 DALI_TYPE_REGISTRATION_END()
 const char* const BROKEN_IMAGE_FILE_NAME = "broken.png"; ///< The file name of the broken image.
 
-static constexpr auto          SHADER_TYPE_COUNT = 2u;
-const std::string_view VertexPredefines[SHADER_TYPE_COUNT]
-{
-  "", //VisualFactoryCache::COLOR_SHADER
+static constexpr auto  SHADER_TYPE_COUNT = 2u;
+const std::string_view VertexPredefines[SHADER_TYPE_COUNT]{
+  "",                                     //VisualFactoryCache::COLOR_SHADER
   "#define IS_REQUIRED_ROUNDED_CORNER\n", //VisualFactoryCache::COLOR_SHADER_ROUNDED_CORNER
 };
-const std::string_view FragmentPredefines[SHADER_TYPE_COUNT]
-{
-  "", //VisualFactoryCache::COLOR_SHADER
+const std::string_view FragmentPredefines[SHADER_TYPE_COUNT]{
+  "",                                     //VisualFactoryCache::COLOR_SHADER
   "#define IS_REQUIRED_ROUNDED_CORNER\n", //VisualFactoryCache::COLOR_SHADER_ROUNDED_CORNER
 };
 
@@ -95,6 +93,7 @@ VisualFactory::VisualFactory(bool debugEnabled)
   mImageVisualShaderFactory(),
   mTextVisualShaderFactory(),
   mSlotDelegate(this),
+  mIdleCallback(nullptr),
   mDebugEnabled(debugEnabled),
   mPreMultiplyOnLoad(true)
 {
@@ -102,6 +101,12 @@ VisualFactory::VisualFactory(bool debugEnabled)
 
 VisualFactory::~VisualFactory()
 {
+  if(mIdleCallback && Adaptor::IsAvailable())
+  {
+    // Removes the callback from the callback manager in case the control is destroyed before the callback is executed.
+    Adaptor::Get().RemoveIdle(mIdleCallback);
+    mIdleCallback = nullptr;
+  }
 }
 
 void VisualFactory::OnStyleChangedSignal(Toolkit::StyleManager styleManager, StyleChange::Type type)
@@ -404,7 +409,7 @@ void VisualFactory::UsePreCompiledShader()
 
   // Get image shader
   std::vector<RawShaderData> rawShaderList;
-  RawShaderData imageShaderData;
+  RawShaderData              imageShaderData;
   GetImageVisualShaderFactory().GetPrecompiledShader(imageShaderData);
   rawShaderList.push_back(imageShaderData);
 
@@ -418,11 +423,17 @@ void VisualFactory::UsePreCompiledShader()
   GetPrecompiledShader(colorShaderData);
   rawShaderList.push_back(colorShaderData);
 
-
   // Save all shader
   Integration::ShaderPrecompiler::Get().SavePrecomipleShaderList(rawShaderList);
 }
 
+void VisualFactory::DiscardVisual(Toolkit::Visual::Base visual)
+{
+  mDiscardedVisuals.emplace_back(visual);
+
+  RegisterDiscardCallback();
+}
+
 Internal::TextureManager& VisualFactory::GetTextureManager()
 {
   return GetFactoryCache().GetTextureManager();
@@ -452,20 +463,20 @@ void VisualFactory::GetPrecompiledShader(RawShaderData& shaders)
 {
   std::vector<std::string_view> vertexPrefix;
   std::vector<std::string_view> fragmentPrefix;
-  int shaderCount = 0;
-  shaders.shaderCount = 0;
-  for(int i=0; i< SHADER_TYPE_COUNT; ++i)
+  int                           shaderCount = 0;
+  shaders.shaderCount                       = 0;
+  for(int i = 0; i < SHADER_TYPE_COUNT; ++i)
   {
     vertexPrefix.push_back(VertexPredefines[i]);
     fragmentPrefix.push_back(FragmentPredefines[i]);
     shaderCount++;
   }
 
-  shaders.vertexPrefix = vertexPrefix;
+  shaders.vertexPrefix   = vertexPrefix;
   shaders.fragmentPrefix = fragmentPrefix;
-  shaders.vertexShader = SHADER_COLOR_VISUAL_SHADER_VERT;
+  shaders.vertexShader   = SHADER_COLOR_VISUAL_SHADER_VERT;
   shaders.fragmentShader = SHADER_COLOR_VISUAL_SHADER_FRAG;
-  shaders.shaderCount = shaderCount;
+  shaders.shaderCount    = shaderCount;
 }
 
 Internal::VisualFactoryCache& VisualFactory::GetFactoryCache()
@@ -505,6 +516,31 @@ TextVisualShaderFactory& VisualFactory::GetTextVisualShaderFactory()
   return *mTextVisualShaderFactory;
 }
 
+void VisualFactory::OnDiscardCallback()
+{
+  mIdleCallback = nullptr;
+
+  // Discard visual now.
+  mDiscardedVisuals.clear();
+}
+
+void VisualFactory::RegisterDiscardCallback()
+{
+  if(!mIdleCallback && Adaptor::IsAvailable())
+  {
+    // The callback manager takes the ownership of the callback object.
+    mIdleCallback = MakeCallback(this, &VisualFactory::OnDiscardCallback);
+
+    Adaptor& adaptor = Adaptor::Get();
+
+    if(!adaptor.AddIdle(mIdleCallback, false))
+    {
+      // Fail to add idle. (Maybe adaptor is paused.)
+      mIdleCallback = nullptr;
+    }
+  }
+}
+
 } // namespace Internal
 
 } // namespace Toolkit
index f516e4517d5656d1f59190968fd447a609930596..68ccb7835dd12d0ac0ce19db69b88ffb63a97791 100644 (file)
@@ -18,8 +18,9 @@
  */
 
 // EXTERNAL INCLUDES
-#include <dali/public-api/object/base-object.h>
 #include <dali/integration-api/shader-precompiler.h>
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/object/base-object.h>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/visual-factory/visual-base.h>
@@ -90,6 +91,11 @@ public:
    */
   void UsePreCompiledShader();
 
+  /**
+   * @copydoc Toolkit::VisualFactory::DiscardVisual()
+   */
+  void DiscardVisual(Toolkit::Visual::Base visual);
+
   /**
    * @return the reference to texture manager
    */
@@ -129,6 +135,16 @@ private:
    */
   TextVisualShaderFactory& GetTextVisualShaderFactory();
 
+  /**
+   * @brief Callbacks called for clear discarded visuals.
+   */
+  void OnDiscardCallback();
+
+  /**
+   * @brief Register idle callback for discard visuals if need.
+   */
+  void RegisterDiscardCallback();
+
   VisualFactory(const VisualFactory&) = delete;
 
   VisualFactory& operator=(const VisualFactory& rhs) = delete;
@@ -138,9 +154,14 @@ private:
   std::unique_ptr<ImageVisualShaderFactory> mImageVisualShaderFactory;
   std::unique_ptr<TextVisualShaderFactory>  mTextVisualShaderFactory;
   SlotDelegate<VisualFactory>               mSlotDelegate;
-  bool                                      mDebugEnabled : 1;
-  bool                                      mPreMultiplyOnLoad : 1; ///< Local store for this flag
-  bool                                      mPrecompiledShaderRequested{false};
+  CallbackBase*                             mIdleCallback;
+
+  using DiscardedVisualContainer = std::vector<Toolkit::Visual::Base>;
+  DiscardedVisualContainer mDiscardedVisuals{};
+
+  bool mDebugEnabled : 1;
+  bool mPreMultiplyOnLoad : 1; ///< Local store for this flag
+  bool mPrecompiledShaderRequested{false};
 };
 
 /**