Split texture-manager-impl files for/devel/master
authorEunki, Hong <eunkiki.hong@samsung.com>
Wed, 16 Feb 2022 11:27:33 +0000 (20:27 +0900)
committerEunki, Hong <eunkiki.hong@samsung.com>
Thu, 17 Feb 2022 13:32:01 +0000 (22:32 +0900)
Collect all TextureManager relative files in one folder.

And split TextureManager API's job as three files.
 - texture-manager-impl :
   Control texture loading it self. like alpha masking / synchronous / atlas / etc...
 - texture-cache-manager :
   Control internal texture caching container, external texture set, external encoded image buffers.
   Generate new TextureId, and we can access TextureInfo by TextureCacheIndex.
 - texture-async-loading-helper :
   Help async loader thread create, and callback load finished.

And make most API's input parameters from 'T' to 'const T&' if we can.

And also, make TextureManagerType namespace s.t. texture-manager-impl and textuer-cache-manager
both class need to be use, and should be shared each other.

Change-Id: Ia522a7b36da51d64282ca6b9ab4190a4e0476ad1
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
24 files changed:
automated-tests/src/dali-toolkit-internal/utc-Dali-TextureManager.cpp
dali-toolkit/internal/file.list
dali-toolkit/internal/image-loader/image-url-impl.cpp
dali-toolkit/internal/visuals/animated-image/fixed-image-cache.h
dali-toolkit/internal/visuals/animated-image/image-cache.h
dali-toolkit/internal/visuals/animated-image/rolling-animated-image-cache.h
dali-toolkit/internal/visuals/animated-image/rolling-image-cache.h
dali-toolkit/internal/visuals/image/image-visual.cpp
dali-toolkit/internal/visuals/image/image-visual.h
dali-toolkit/internal/visuals/npatch-data.h
dali-toolkit/internal/visuals/npatch-loader.h
dali-toolkit/internal/visuals/npatch/npatch-visual.h
dali-toolkit/internal/visuals/texture-manager-impl.cpp [deleted file]
dali-toolkit/internal/visuals/texture-manager-impl.h [deleted file]
dali-toolkit/internal/visuals/texture-manager/texture-async-loading-helper.cpp [new file with mode: 0644]
dali-toolkit/internal/visuals/texture-manager/texture-async-loading-helper.h [new file with mode: 0644]
dali-toolkit/internal/visuals/texture-manager/texture-cache-manager.cpp [new file with mode: 0644]
dali-toolkit/internal/visuals/texture-manager/texture-cache-manager.h [new file with mode: 0644]
dali-toolkit/internal/visuals/texture-manager/texture-manager-impl.cpp [new file with mode: 0644]
dali-toolkit/internal/visuals/texture-manager/texture-manager-impl.h [new file with mode: 0644]
dali-toolkit/internal/visuals/texture-manager/texture-manager-type.h [new file with mode: 0644]
dali-toolkit/internal/visuals/texture-manager/texture-upload-observer.cpp [moved from dali-toolkit/internal/visuals/texture-upload-observer.cpp with 88% similarity]
dali-toolkit/internal/visuals/texture-manager/texture-upload-observer.h [moved from dali-toolkit/internal/visuals/texture-upload-observer.h with 98% similarity]
dali-toolkit/internal/visuals/visual-factory-cache.h

index d279482..6431228 100644 (file)
@@ -22,8 +22,8 @@
 #include <dali-toolkit-test-suite-utils.h>
 #include <toolkit-timer.h>
 #include <toolkit-event-thread-callback.h>
-#include <dali-toolkit/internal/visuals/texture-manager-impl.h>
-#include <dali-toolkit/internal/visuals/texture-upload-observer.h>
+#include <dali-toolkit/internal/visuals/texture-manager/texture-manager-impl.h>
+#include <dali-toolkit/internal/visuals/texture-manager/texture-upload-observer.h>
 #include <dali/devel-api/adaptor-framework/pixel-buffer.h>
 #include <dali-toolkit/internal/visuals/image-atlas-manager.h>
 #include <dali-toolkit/internal/visuals/visual-factory-impl.h> ///< For VisualFactory's member TextureManager.
@@ -112,7 +112,7 @@ int UtcTextureManagerRequestLoad(void)
     ImageDimensions(),
     FittingMode::SCALE_TO_FILL,
     SamplingMode::BOX_THEN_LINEAR,
-    TextureManager::NO_ATLAS,
+    TextureManager::UseAtlas::NO_ATLAS,
     &observer,
     true,
     TextureManager::ReloadPolicy::CACHED,
@@ -139,7 +139,7 @@ int UtcTextureManagerGenerateHash(void)
     ImageDimensions(),
     FittingMode::SCALE_TO_FILL,
     SamplingMode::BOX_THEN_LINEAR,
-    TextureManager::USE_ATLAS,
+    TextureManager::UseAtlas::NO_ATLAS,
     &observer,
     true,
     TextureManager::ReloadPolicy::CACHED,
@@ -187,7 +187,7 @@ int UtcTextureManagerEncodedImageBuffer(void)
     ImageDimensions(),
     FittingMode::SCALE_TO_FILL,
     SamplingMode::BOX_THEN_LINEAR,
-    TextureManager::NO_ATLAS,
+    TextureManager::UseAtlas::NO_ATLAS,
     &observer1,
     true, ///< orientationCorrection
     TextureManager::ReloadPolicy::CACHED,
@@ -261,7 +261,7 @@ int UtcTextureManagerEncodedImageBuffer(void)
     ImageDimensions(),
     FittingMode::SCALE_TO_FILL,
     SamplingMode::BOX_THEN_LINEAR,
-    TextureManager::NO_ATLAS,
+    TextureManager::UseAtlas::NO_ATLAS,
     &observer3,
     true, ///< orientationCorrection
     TextureManager::ReloadPolicy::CACHED,
@@ -278,7 +278,7 @@ int UtcTextureManagerEncodedImageBuffer(void)
     ImageDimensions(),
     FittingMode::SCALE_TO_FILL,
     SamplingMode::BOX_THEN_LINEAR,
-    TextureManager::NO_ATLAS,
+    TextureManager::UseAtlas::NO_ATLAS,
     &observer4,
     true, ///< orientationCorrection
     TextureManager::ReloadPolicy::FORCED,
@@ -396,7 +396,7 @@ int UtcTextureManagerEncodedImageBufferReferenceCount(void)
     ImageDimensions(),
     FittingMode::SCALE_TO_FILL,
     SamplingMode::BOX_THEN_LINEAR,
-    TextureManager::NO_ATLAS,
+    TextureManager::UseAtlas::NO_ATLAS,
     &observer1,
     true, ///< orientationCorrection
     TextureManager::ReloadPolicy::CACHED,
@@ -476,7 +476,7 @@ int UtcTextureManagerCachingForDifferentLoadingType(void)
     ImageDimensions(),
     FittingMode::SCALE_TO_FILL,
     SamplingMode::BOX_THEN_LINEAR,
-    TextureManager::NO_ATLAS,
+    TextureManager::UseAtlas::NO_ATLAS,
     &observer1,
     true,
     TextureManager::ReloadPolicy::CACHED,
index e57fa31..8781439 100644 (file)
@@ -41,9 +41,11 @@ SET( toolkit_src_files
    ${toolkit_src_dir}/visuals/svg/svg-rasterize-thread.cpp
    ${toolkit_src_dir}/visuals/svg/svg-visual.cpp
    ${toolkit_src_dir}/visuals/text/text-visual.cpp
+   ${toolkit_src_dir}/visuals/texture-manager/texture-async-loading-helper.cpp
+   ${toolkit_src_dir}/visuals/texture-manager/texture-cache-manager.cpp
+   ${toolkit_src_dir}/visuals/texture-manager/texture-manager-impl.cpp
+   ${toolkit_src_dir}/visuals/texture-manager/texture-upload-observer.cpp
    ${toolkit_src_dir}/visuals/transition-data-impl.cpp
-   ${toolkit_src_dir}/visuals/texture-manager-impl.cpp
-   ${toolkit_src_dir}/visuals/texture-upload-observer.cpp
    ${toolkit_src_dir}/visuals/image-visual-shader-factory.cpp
    ${toolkit_src_dir}/visuals/visual-base-data-impl.cpp
    ${toolkit_src_dir}/visuals/visual-base-impl.cpp
index 52ba6c4..bc7c540 100644 (file)
@@ -21,7 +21,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/image-loader/texture-manager.h>
 #include <dali-toolkit/internal/visuals/visual-factory-impl.h>
-#include <dali-toolkit/internal/visuals/texture-manager-impl.h>
+#include <dali-toolkit/internal/visuals/texture-manager/texture-manager-impl.h>
 #include <dali-toolkit/internal/visuals/visual-url.h>
 
 namespace Dali
index dc19937..bdec325 100644 (file)
@@ -19,7 +19,7 @@
 
 // EXTERNAL INCLUDES
 #include <dali-toolkit/internal/visuals/animated-image/image-cache.h>
-#include <dali-toolkit/internal/visuals/texture-manager-impl.h>
+#include <dali-toolkit/internal/visuals/texture-manager/texture-manager-impl.h>
 
 namespace Dali
 {
index f21d707..060808f 100644 (file)
@@ -18,8 +18,8 @@
  */
 
 // EXTERNAL INCLUDES
-#include <dali-toolkit/internal/visuals/texture-manager-impl.h>
-#include <dali-toolkit/internal/visuals/texture-upload-observer.h>
+#include <dali-toolkit/internal/visuals/texture-manager/texture-manager-impl.h>
+#include <dali-toolkit/internal/visuals/texture-manager/texture-upload-observer.h>
 
 namespace Dali
 {
index e1d201b..16ae8f8 100644 (file)
@@ -19,7 +19,7 @@
 
 // EXTERNAL INCLUDES
 #include <dali-toolkit/internal/visuals/animated-image/image-cache.h>
-#include <dali-toolkit/internal/visuals/texture-manager-impl.h>
+#include <dali-toolkit/internal/visuals/texture-manager/texture-manager-impl.h>
 #include <dali/devel-api/adaptor-framework/animated-image-loading.h>
 #include <dali/devel-api/common/circular-queue.h>
 
index 1490c41..f07883c 100644 (file)
@@ -20,7 +20,7 @@
 // EXTERNAL INCLUDES
 
 #include <dali-toolkit/internal/visuals/animated-image/image-cache.h>
-#include <dali-toolkit/internal/visuals/texture-manager-impl.h>
+#include <dali-toolkit/internal/visuals/texture-manager/texture-manager-impl.h>
 #include <dali/devel-api/common/circular-queue.h>
 
 namespace Dali
index c5344a4..71770a1 100644 (file)
@@ -33,7 +33,7 @@
 #include <dali-toolkit/devel-api/visuals/image-visual-actions-devel.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/texture-manager/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>
index bc94ffb..7cdd535 100644 (file)
@@ -28,7 +28,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/image-loader/atlas-upload-observer.h>
 #include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
-#include <dali-toolkit/internal/visuals/texture-upload-observer.h>
+#include <dali-toolkit/internal/visuals/texture-manager/texture-upload-observer.h>
 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
 #include <dali-toolkit/internal/visuals/visual-url.h>
 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
index 94d7f2b..91c04dd 100644 (file)
@@ -24,7 +24,7 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/utility/npatch-utilities.h>
-#include <dali-toolkit/internal/visuals/texture-manager-impl.h>
+#include <dali-toolkit/internal/visuals/texture-manager/texture-manager-impl.h>
 #include <dali-toolkit/internal/visuals/visual-url.h>
 
 namespace Dali
index dd7f022..146c506 100644 (file)
@@ -26,7 +26,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/utility/npatch-utilities.h>
 #include <dali-toolkit/internal/visuals/npatch-data.h>
-#include <dali-toolkit/internal/visuals/texture-manager-impl.h>
+#include <dali-toolkit/internal/visuals/texture-manager/texture-manager-impl.h>
 #include <dali-toolkit/internal/visuals/visual-url.h>
 
 namespace Dali
index a266edc..d7bbd80 100644 (file)
@@ -27,7 +27,7 @@
 #include <dali/public-api/rendering/shader.h>
 
 // INTERNAL INCLUDES
-#include <dali-toolkit/internal/visuals/texture-upload-observer.h>
+#include <dali-toolkit/internal/visuals/texture-manager/texture-upload-observer.h>
 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
 #include <dali-toolkit/internal/visuals/visual-url.h>
 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
diff --git a/dali-toolkit/internal/visuals/texture-manager-impl.cpp b/dali-toolkit/internal/visuals/texture-manager-impl.cpp
deleted file mode 100644 (file)
index 3578ede..0000000
+++ /dev/null
@@ -1,1555 +0,0 @@
-/*
- * Copyright (c) 2021 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// CLASS HEADER
-#include <dali-toolkit/internal/visuals/texture-manager-impl.h>
-
-// EXTERNAL HEADERS
-#include <dali/devel-api/adaptor-framework/environment-variable.h>
-#include <dali/devel-api/adaptor-framework/image-loading.h>
-#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
-#include <dali/devel-api/common/hash.h>
-#include <dali/integration-api/debug.h>
-#include <dali/public-api/math/vector4.h>
-#include <dali/public-api/rendering/geometry.h>
-#include <cstdlib>
-#include <string>
-
-// INTERNAL HEADERS
-#include <dali-toolkit/internal/image-loader/async-image-loader-impl.h>
-#include <dali-toolkit/internal/image-loader/image-atlas-impl.h>
-#include <dali-toolkit/internal/visuals/image-atlas-manager.h>
-#include <dali-toolkit/internal/visuals/rendering-addon.h>
-#include <dali-toolkit/public-api/image-loader/sync-image-loader.h>
-
-namespace
-{
-constexpr auto INITIAL_CACHE_NUMBER                    = size_t{0u};
-constexpr auto DEFAULT_NUMBER_OF_LOCAL_LOADER_THREADS  = size_t{4u};
-constexpr auto DEFAULT_NUMBER_OF_REMOTE_LOADER_THREADS = size_t{8u};
-
-constexpr auto NUMBER_OF_LOCAL_LOADER_THREADS_ENV  = "DALI_TEXTURE_LOCAL_THREADS";
-constexpr auto NUMBER_OF_REMOTE_LOADER_THREADS_ENV = "DALI_TEXTURE_REMOTE_THREADS";
-
-size_t GetNumberOfThreads(const char* environmentVariable, size_t defaultValue)
-{
-  using Dali::EnvironmentVariable::GetEnvironmentVariable;
-  auto           numberString          = GetEnvironmentVariable(environmentVariable);
-  auto           numberOfThreads       = numberString ? std::strtoul(numberString, nullptr, 10) : 0;
-  constexpr auto MAX_NUMBER_OF_THREADS = 100u;
-  DALI_ASSERT_DEBUG(numberOfThreads < MAX_NUMBER_OF_THREADS);
-  return (numberOfThreads > 0 && numberOfThreads < MAX_NUMBER_OF_THREADS) ? numberOfThreads : defaultValue;
-}
-
-size_t GetNumberOfLocalLoaderThreads()
-{
-  return GetNumberOfThreads(NUMBER_OF_LOCAL_LOADER_THREADS_ENV, DEFAULT_NUMBER_OF_LOCAL_LOADER_THREADS);
-}
-
-size_t GetNumberOfRemoteLoaderThreads()
-{
-  return GetNumberOfThreads(NUMBER_OF_REMOTE_LOADER_THREADS_ENV, DEFAULT_NUMBER_OF_REMOTE_LOADER_THREADS);
-}
-
-} // namespace
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Internal
-{
-namespace
-{
-#ifdef DEBUG_ENABLED
-Debug::Filter* gTextureManagerLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_TEXTURE_MANAGER");
-
-#define GET_LOAD_STATE_STRING(loadState)                                                                                                              \
-  loadState == TextureManager::LoadState::NOT_STARTED ? "NOT_STARTED" : loadState == TextureManager::LoadState::LOADING          ? "LOADING"          \
-                                                                      : loadState == TextureManager::LoadState::LOAD_FINISHED    ? "LOAD_FINISHED"    \
-                                                                      : loadState == TextureManager::LoadState::WAITING_FOR_MASK ? "WAITING_FOR_MASK" \
-                                                                      : loadState == TextureManager::LoadState::MASK_APPLYING    ? "MASK_APPLYING"    \
-                                                                      : loadState == TextureManager::LoadState::MASK_APPLIED     ? "MASK_APPLIED"     \
-                                                                      : loadState == TextureManager::LoadState::UPLOADED         ? "UPLOADED"         \
-                                                                      : loadState == TextureManager::LoadState::CANCELLED        ? "CANCELLED"        \
-                                                                      : loadState == TextureManager::LoadState::LOAD_FAILED      ? "LOAD_FAILED"      \
-                                                                                                                                 : "Unknown"
-
-#endif
-
-const uint32_t DEFAULT_ATLAS_SIZE(1024u);               ///< This size can fit 8 by 8 images of average size 128 * 128
-const Vector4  FULL_ATLAS_RECT(0.0f, 0.0f, 1.0f, 1.0f); ///< UV Rectangle that covers the full Texture
-const int      INVALID_INDEX(-1);                       ///< Invalid index used to represent a non-existant TextureInfo struct
-const int      INVALID_CACHE_INDEX(-1);                 ///< Invalid Cache index
-
-void PreMultiply(Devel::PixelBuffer pixelBuffer, TextureManager::MultiplyOnLoad& preMultiplyOnLoad)
-{
-  if(Pixel::HasAlpha(pixelBuffer.GetPixelFormat()))
-  {
-    if(preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD)
-    {
-      pixelBuffer.MultiplyColorByAlpha();
-    }
-  }
-  else
-  {
-    preMultiplyOnLoad = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
-  }
-}
-
-} // Anonymous namespace
-
-TextureManager::MaskingData::MaskingData()
-: mAlphaMaskUrl(),
-  mAlphaMaskId(INVALID_TEXTURE_ID),
-  mContentScaleFactor(1.0f),
-  mCropToMask(true)
-{
-}
-
-TextureManager::TextureManager()
-: mAsyncLocalLoaders(GetNumberOfLocalLoaderThreads(), [&]()
-                     { return AsyncLoadingHelper(*this); }),
-  mAsyncRemoteLoaders(GetNumberOfRemoteLoaderThreads(), [&]()
-                      { return AsyncLoadingHelper(*this); }),
-  mExternalTextures(),
-  mLifecycleObservers(),
-  mLoadQueue(),
-  mCurrentTextureId(0),
-  mQueueLoadFlag(false)
-{
-  // Initialize the AddOn
-  RenderingAddOn::Get();
-}
-
-TextureManager::~TextureManager()
-{
-  for(auto iter = mLifecycleObservers.Begin(), endIter = mLifecycleObservers.End(); iter != endIter; ++iter)
-  {
-    (*iter)->TextureManagerDestroyed();
-  }
-}
-
-TextureSet TextureManager::LoadAnimatedImageTexture(
-  Dali::AnimatedImageLoading animatedImageLoading, uint32_t frameIndex, Dali::SamplingMode::Type samplingMode, bool synchronousLoading, TextureManager::TextureId& textureId, Dali::WrapMode::Type wrapModeU, Dali::WrapMode::Type wrapModeV, TextureUploadObserver* textureObserver)
-{
-  TextureSet textureSet;
-
-  if(synchronousLoading)
-  {
-    Devel::PixelBuffer pixelBuffer;
-    if(animatedImageLoading)
-    {
-      pixelBuffer = animatedImageLoading.LoadFrame(frameIndex);
-    }
-    if(!pixelBuffer)
-    {
-      DALI_LOG_ERROR("TextureManager::LoadAnimatedImageTexture: Synchronous loading is failed\n");
-    }
-    else
-    {
-      PixelData pixelData = Devel::PixelBuffer::Convert(pixelBuffer); // takes ownership of buffer
-      if(!textureSet)
-      {
-        Texture texture = Texture::New(Dali::TextureType::TEXTURE_2D, pixelData.GetPixelFormat(), pixelData.GetWidth(), pixelData.GetHeight());
-        texture.Upload(pixelData);
-        textureSet = TextureSet::New();
-        textureSet.SetTexture(0u, texture);
-      }
-    }
-  }
-  else
-  {
-    auto preMultiply                    = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
-    textureId                           = RequestLoadInternal(animatedImageLoading.GetUrl(), INVALID_TEXTURE_ID, 1.0f, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::BOX_THEN_LINEAR, TextureManager::NO_ATLAS, false, StorageType::UPLOAD_TO_TEXTURE, textureObserver, true, TextureManager::ReloadPolicy::CACHED, preMultiply, animatedImageLoading, frameIndex, false);
-    TextureManager::LoadState loadState = GetTextureStateInternal(textureId);
-    if(loadState == TextureManager::LoadState::UPLOADED)
-    {
-      // LoadComplete has already been called - keep the same texture set
-      textureSet = GetTextureSet(textureId);
-    }
-  }
-
-  if(textureSet)
-  {
-    Sampler sampler = Sampler::New();
-    sampler.SetWrapMode(wrapModeU, wrapModeV);
-    textureSet.SetSampler(0u, sampler);
-  }
-
-  return textureSet;
-}
-
-Devel::PixelBuffer TextureManager::LoadPixelBuffer(
-  const VisualUrl& url, Dali::ImageDimensions desiredSize, Dali::FittingMode::Type fittingMode, Dali::SamplingMode::Type samplingMode, bool synchronousLoading, TextureUploadObserver* textureObserver, bool orientationCorrection, TextureManager::MultiplyOnLoad& preMultiplyOnLoad)
-{
-  Devel::PixelBuffer pixelBuffer;
-  if(synchronousLoading)
-  {
-    if(url.IsValid())
-    {
-      if(url.IsBufferResource())
-      {
-        const EncodedImageBuffer& encodedImageBuffer = GetEncodedImageBuffer(url.GetUrl());
-        if(encodedImageBuffer)
-        {
-          pixelBuffer = LoadImageFromBuffer(encodedImageBuffer.GetRawBuffer(), desiredSize, fittingMode, samplingMode, orientationCorrection);
-        }
-      }
-      else
-      {
-        pixelBuffer = LoadImageFromFile(url.GetUrl(), desiredSize, fittingMode, samplingMode, orientationCorrection);
-      }
-      if(pixelBuffer && preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD)
-      {
-        PreMultiply(pixelBuffer, preMultiplyOnLoad);
-      }
-    }
-  }
-  else
-  {
-    RequestLoadInternal(url, INVALID_TEXTURE_ID, 1.0f, desiredSize, fittingMode, samplingMode, TextureManager::NO_ATLAS, false, StorageType::RETURN_PIXEL_BUFFER, textureObserver, orientationCorrection, TextureManager::ReloadPolicy::FORCED, preMultiplyOnLoad, Dali::AnimatedImageLoading(), 0u, false);
-  }
-
-  return pixelBuffer;
-}
-
-TextureSet TextureManager::LoadTexture(
-  const VisualUrl& url, Dali::ImageDimensions desiredSize, Dali::FittingMode::Type fittingMode, Dali::SamplingMode::Type samplingMode, MaskingDataPointer& maskInfo, bool synchronousLoading, TextureManager::TextureId& textureId, Vector4& textureRect, Dali::ImageDimensions& textureRectSize, bool& atlasingStatus, bool& loadingStatus, Dali::WrapMode::Type wrapModeU, Dali::WrapMode::Type wrapModeV, TextureUploadObserver* textureObserver, AtlasUploadObserver* atlasObserver, ImageAtlasManagerPtr imageAtlasManager, bool orientationCorrection, TextureManager::ReloadPolicy reloadPolicy, TextureManager::MultiplyOnLoad& preMultiplyOnLoad)
-{
-  TextureSet textureSet;
-
-  loadingStatus = false;
-  textureRect   = FULL_ATLAS_RECT;
-
-  if(VisualUrl::TEXTURE == url.GetProtocolType())
-  {
-    std::string location = url.GetLocation();
-    if(location.size() > 0u)
-    {
-      TextureId id = std::stoi(location);
-      for(auto&& elem : mExternalTextures)
-      {
-        if(elem.textureId == id)
-        {
-          preMultiplyOnLoad = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
-          textureId         = elem.textureId;
-          return elem.textureSet;
-        }
-      }
-    }
-  }
-  else
-  {
-    // For Atlas
-    if(synchronousLoading && atlasingStatus && imageAtlasManager->CheckAtlasAvailable(url, desiredSize))
-    {
-      Devel::PixelBuffer pixelBuffer = LoadImageSynchronously(url, desiredSize, fittingMode, samplingMode, orientationCorrection);
-
-      if(maskInfo && maskInfo->mAlphaMaskUrl.IsValid())
-      {
-        Devel::PixelBuffer maskPixelBuffer = LoadImageSynchronously(maskInfo->mAlphaMaskUrl.GetUrl(), ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::NO_FILTER, true);
-        if(maskPixelBuffer)
-        {
-          pixelBuffer.ApplyMask(maskPixelBuffer, maskInfo->mContentScaleFactor, maskInfo->mCropToMask);
-        }
-      }
-
-      PixelData data;
-      if(pixelBuffer)
-      {
-        PreMultiply(pixelBuffer, preMultiplyOnLoad);
-        data = Devel::PixelBuffer::Convert(pixelBuffer); // takes ownership of buffer
-
-        if(data)
-        {
-          textureSet = imageAtlasManager->Add(textureRect, data);
-          if(textureSet)
-          {
-            textureRectSize.SetWidth(data.GetWidth());
-            textureRectSize.SetHeight(data.GetHeight());
-          }
-        }
-        else
-        {
-          DALI_LOG_ERROR("TextureManager::LoadTexture: Synchronous Texture loading with atlasing is failed.\n");
-        }
-      }
-      if(!textureSet)
-      {
-        atlasingStatus = false;
-      }
-    }
-
-    if(!textureSet)
-    {
-      loadingStatus = true;
-      if(atlasingStatus)
-      {
-        textureSet = imageAtlasManager->Add(textureRect, url.GetUrl(), desiredSize, fittingMode, true, atlasObserver);
-      }
-      if(!textureSet) // big image, no atlasing or atlasing failed
-      {
-        atlasingStatus = false;
-        if(!maskInfo || !maskInfo->mAlphaMaskUrl.IsValid())
-        {
-          textureId = RequestLoad(url, desiredSize, fittingMode, samplingMode, TextureManager::NO_ATLAS, textureObserver, orientationCorrection, reloadPolicy, preMultiplyOnLoad, synchronousLoading);
-        }
-        else
-        {
-          maskInfo->mAlphaMaskId = RequestMaskLoad(maskInfo->mAlphaMaskUrl, synchronousLoading);
-          textureId              = RequestLoad(url,
-                                  maskInfo->mAlphaMaskId,
-                                  maskInfo->mContentScaleFactor,
-                                  desiredSize,
-                                  fittingMode,
-                                  samplingMode,
-                                  TextureManager::NO_ATLAS,
-                                  maskInfo->mCropToMask,
-                                  textureObserver,
-                                  orientationCorrection,
-                                  reloadPolicy,
-                                  preMultiplyOnLoad,
-                                  synchronousLoading);
-        }
-
-        TextureManager::LoadState loadState = GetTextureStateInternal(textureId);
-        if(loadState == TextureManager::LoadState::UPLOADED)
-        {
-          // LoadComplete has already been called - keep the same texture set
-          textureSet = GetTextureSet(textureId);
-        }
-
-        // If we are loading the texture, or waiting for the ready signal handler to complete, inform
-        // caller that they need to wait.
-        loadingStatus = (loadState == TextureManager::LoadState::LOADING ||
-                         loadState == TextureManager::LoadState::WAITING_FOR_MASK ||
-                         loadState == TextureManager::LoadState::MASK_APPLYING ||
-                         loadState == TextureManager::LoadState::MASK_APPLIED ||
-                         loadState == TextureManager::LoadState::NOT_STARTED ||
-                         mQueueLoadFlag);
-      }
-      else
-      {
-        textureRectSize = desiredSize;
-      }
-    }
-  }
-
-  if(!atlasingStatus && textureSet)
-  {
-    Sampler sampler = Sampler::New();
-    sampler.SetWrapMode(wrapModeU, wrapModeV);
-    textureSet.SetSampler(0u, sampler);
-  }
-
-  if(synchronousLoading)
-  {
-    loadingStatus = false;
-  }
-
-  return textureSet;
-}
-
-TextureManager::TextureId TextureManager::RequestLoad(
-  const VisualUrl&                url,
-  const ImageDimensions           desiredSize,
-  FittingMode::Type               fittingMode,
-  Dali::SamplingMode::Type        samplingMode,
-  const UseAtlas                  useAtlas,
-  TextureUploadObserver*          observer,
-  bool                            orientationCorrection,
-  TextureManager::ReloadPolicy    reloadPolicy,
-  TextureManager::MultiplyOnLoad& preMultiplyOnLoad,
-  bool                            synchronousLoading)
-{
-  return RequestLoadInternal(url, INVALID_TEXTURE_ID, 1.0f, desiredSize, fittingMode, samplingMode, useAtlas, false, StorageType::UPLOAD_TO_TEXTURE, observer, orientationCorrection, reloadPolicy, preMultiplyOnLoad, Dali::AnimatedImageLoading(), 0u, synchronousLoading);
-}
-
-TextureManager::TextureId TextureManager::RequestLoad(
-  const VisualUrl&                url,
-  TextureId                       maskTextureId,
-  float                           contentScale,
-  const ImageDimensions           desiredSize,
-  FittingMode::Type               fittingMode,
-  Dali::SamplingMode::Type        samplingMode,
-  const UseAtlas                  useAtlas,
-  bool                            cropToMask,
-  TextureUploadObserver*          observer,
-  bool                            orientationCorrection,
-  TextureManager::ReloadPolicy    reloadPolicy,
-  TextureManager::MultiplyOnLoad& preMultiplyOnLoad,
-  bool                            synchronousLoading)
-{
-  return RequestLoadInternal(url, maskTextureId, contentScale, desiredSize, fittingMode, samplingMode, useAtlas, cropToMask, StorageType::UPLOAD_TO_TEXTURE, observer, orientationCorrection, reloadPolicy, preMultiplyOnLoad, Dali::AnimatedImageLoading(), 0u, synchronousLoading);
-}
-
-TextureManager::TextureId TextureManager::RequestMaskLoad(const VisualUrl& maskUrl, bool synchronousLoading)
-{
-  // Use the normal load procedure to get the alpha mask.
-  auto preMultiply = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
-  return RequestLoadInternal(maskUrl, INVALID_TEXTURE_ID, 1.0f, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::NO_FILTER, NO_ATLAS, false, StorageType::KEEP_PIXEL_BUFFER, NULL, true, TextureManager::ReloadPolicy::CACHED, preMultiply, Dali::AnimatedImageLoading(), 0u, synchronousLoading);
-}
-
-TextureManager::TextureId TextureManager::RequestLoadInternal(
-  const VisualUrl&                url,
-  TextureId                       maskTextureId,
-  float                           contentScale,
-  const ImageDimensions           desiredSize,
-  FittingMode::Type               fittingMode,
-  Dali::SamplingMode::Type        samplingMode,
-  UseAtlas                        useAtlas,
-  bool                            cropToMask,
-  StorageType                     storageType,
-  TextureUploadObserver*          observer,
-  bool                            orientationCorrection,
-  TextureManager::ReloadPolicy    reloadPolicy,
-  TextureManager::MultiplyOnLoad& preMultiplyOnLoad,
-  Dali::AnimatedImageLoading      animatedImageLoading,
-  uint32_t                        frameIndex,
-  bool                            synchronousLoading)
-{
-  // First check if the requested Texture is cached.
-  bool isAnimatedImage = (animatedImageLoading) ? true : false;
-
-  TextureHash textureHash = INITIAL_CACHE_NUMBER;
-  int         cacheIndex  = INVALID_CACHE_INDEX;
-  if(storageType != StorageType::RETURN_PIXEL_BUFFER && !isAnimatedImage)
-  {
-    textureHash = GenerateHash(url.GetUrl(), desiredSize, fittingMode, samplingMode, useAtlas, maskTextureId);
-
-    // Look up the texture by hash. Note: The extra parameters are used in case of a hash collision.
-    cacheIndex = FindCachedTexture(textureHash, url.GetUrl(), desiredSize, fittingMode, samplingMode, useAtlas, maskTextureId, preMultiplyOnLoad);
-  }
-
-  TextureManager::TextureId textureId = INVALID_TEXTURE_ID;
-  // Check if the requested Texture exists in the cache.
-  if(cacheIndex != INVALID_CACHE_INDEX)
-  {
-    if(TextureManager::ReloadPolicy::CACHED == reloadPolicy)
-    {
-      // Mark this texture being used by another client resource. Forced reload would replace the current texture
-      // without the need for incrementing the reference count.
-      ++(mTextureInfoContainer[cacheIndex].referenceCount);
-    }
-    textureId = mTextureInfoContainer[cacheIndex].textureId;
-
-    // Update preMultiplyOnLoad value. It should be changed according to preMultiplied value of the cached info.
-    preMultiplyOnLoad = mTextureInfoContainer[cacheIndex].preMultiplied ? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD : TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
-
-    DALI_LOG_INFO(gTextureManagerLogFilter, Debug::General, "TextureManager::RequestLoad( url=%s observer=%p ) Using cached texture id@%d, textureId=%d\n", url.GetUrl().c_str(), observer, cacheIndex, textureId);
-  }
-
-  if(textureId == INVALID_TEXTURE_ID) // There was no caching, or caching not required
-  {
-    if(VisualUrl::BUFFER == url.GetProtocolType())
-    {
-      std::string location = url.GetLocation();
-      if(location.size() > 0u)
-      {
-        TextureId                 targetId           = std::stoi(location);
-        const EncodedImageBuffer& encodedImageBuffer = GetEncodedImageBuffer(targetId);
-        if(encodedImageBuffer)
-        {
-          textureId = targetId;
-
-          // Increase EncodedImageBuffer reference during it contains mTextureInfoContainer.
-          UseExternalResource(url.GetUrl());
-        }
-      }
-    }
-
-    if(textureId == INVALID_TEXTURE_ID)
-    {
-      textureId = GenerateUniqueTextureId();
-    }
-
-    bool preMultiply = (preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD);
-    mTextureInfoContainer.push_back(TextureInfo(textureId, maskTextureId, url, desiredSize, contentScale, fittingMode, samplingMode, false, cropToMask, useAtlas, textureHash, orientationCorrection, preMultiply, animatedImageLoading, frameIndex));
-    cacheIndex = mTextureInfoContainer.size() - 1u;
-
-    DALI_LOG_INFO(gTextureManagerLogFilter, Debug::General, "TextureManager::RequestLoad( url=%s observer=%p ) New texture, cacheIndex:%d, textureId=%d\n", url.GetUrl().c_str(), observer, cacheIndex, textureId);
-  }
-
-  // The below code path is common whether we are using the cache or not.
-  // The textureInfoIndex now refers to either a pre-existing cached TextureInfo,
-  // or a new TextureInfo just created.
-  TextureInfo& textureInfo(mTextureInfoContainer[cacheIndex]);
-  textureInfo.maskTextureId         = maskTextureId;
-  textureInfo.storageType           = storageType;
-  textureInfo.orientationCorrection = orientationCorrection;
-
-  DALI_LOG_INFO(gTextureManagerLogFilter, Debug::General, "TextureInfo loadState:%s\n", GET_LOAD_STATE_STRING(textureInfo.loadState));
-
-  // Force reloading of texture by setting loadState unless already loading or cancelled.
-  if(TextureManager::ReloadPolicy::FORCED == reloadPolicy &&
-     TextureManager::LoadState::LOADING != textureInfo.loadState &&
-     TextureManager::LoadState::WAITING_FOR_MASK != textureInfo.loadState &&
-     TextureManager::LoadState::MASK_APPLYING != textureInfo.loadState &&
-     TextureManager::LoadState::MASK_APPLIED != textureInfo.loadState &&
-     TextureManager::LoadState::CANCELLED != textureInfo.loadState)
-  {
-    DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Verbose, "TextureManager::RequestLoad( url=%s observer=%p ) ForcedReload cacheIndex:%d, textureId=%d\n", url.GetUrl().c_str(), observer, cacheIndex, textureId);
-
-    textureInfo.loadState = TextureManager::LoadState::NOT_STARTED;
-  }
-
-  if(!synchronousLoading)
-  {
-    // Check if we should add the observer.
-    // Only do this if we have not loaded yet and it will not have loaded by the end of this method.
-    switch(textureInfo.loadState)
-    {
-      case TextureManager::LoadState::LOAD_FAILED: // Failed notifies observer which then stops observing.
-      case TextureManager::LoadState::NOT_STARTED:
-      {
-        LoadOrQueueTexture(textureInfo, observer); // If called inside NotifyObservers, queues until afterwards
-        break;
-      }
-      case TextureManager::LoadState::LOADING:
-      case TextureManager::LoadState::WAITING_FOR_MASK:
-      case TextureManager::LoadState::MASK_APPLYING:
-      case TextureManager::LoadState::MASK_APPLIED:
-      {
-        ObserveTexture(textureInfo, observer);
-        break;
-      }
-      case TextureManager::LoadState::UPLOADED:
-      {
-        if(observer)
-        {
-          LoadOrQueueTexture(textureInfo, observer);
-        }
-        break;
-      }
-      case TextureManager::LoadState::CANCELLED:
-      {
-        // A cancelled texture hasn't finished loading yet. Treat as a loading texture
-        // (it's ref count has already been incremented, above)
-        textureInfo.loadState = TextureManager::LoadState::LOADING;
-        ObserveTexture(textureInfo, observer);
-        break;
-      }
-      case TextureManager::LoadState::LOAD_FINISHED:
-      {
-        // Loading has already completed.
-        if(observer && textureInfo.storageType == StorageType::RETURN_PIXEL_BUFFER)
-        {
-          LoadOrQueueTexture(textureInfo, observer);
-        }
-        break;
-      }
-    }
-  }
-  else
-  {
-    // If the image is already finished to load, use cached texture.
-    // We don't need to consider Observer becaouse this is synchronous loading.
-    if(textureInfo.loadState == TextureManager::LoadState::UPLOADED ||
-       textureInfo.loadState == TextureManager::LoadState::LOAD_FINISHED)
-    {
-      return textureId;
-    }
-    else
-    {
-      Devel::PixelBuffer pixelBuffer = LoadImageSynchronously(url, desiredSize, fittingMode, samplingMode, orientationCorrection);;
-
-      if(!pixelBuffer)
-      {
-        // If pixelBuffer loading is failed in synchronously, call Remove() method.
-        Remove(textureId, nullptr);
-        return INVALID_TEXTURE_ID;
-      }
-
-      if(storageType == StorageType::KEEP_PIXEL_BUFFER) // For the mask image loading.
-      {
-        textureInfo.pixelBuffer = pixelBuffer; // Store the pixel data
-        textureInfo.loadState   = LoadState::LOAD_FINISHED;
-      }
-      else // For the image loading.
-      {
-        if(maskTextureId != INVALID_TEXTURE_ID)
-        {
-          int maskCacheIndex = GetCacheIndexFromId(maskTextureId);
-          if(maskCacheIndex != INVALID_CACHE_INDEX)
-          {
-            Devel::PixelBuffer maskPixelBuffer = mTextureInfoContainer[maskCacheIndex].pixelBuffer;
-            if(maskPixelBuffer)
-            {
-              pixelBuffer.ApplyMask(maskPixelBuffer, contentScale, cropToMask);
-            }
-          }
-          else
-          {
-            DALI_LOG_ERROR("Mask image is not stored in cache.\n");
-          }
-        }
-        PreMultiply(pixelBuffer, preMultiplyOnLoad);
-
-        // Upload texture
-        UploadTexture(pixelBuffer, textureInfo);
-      }
-    }
-  }
-
-  // Return the TextureId for which this Texture can now be referenced by externally.
-  return textureId;
-}
-
-void TextureManager::Remove(const TextureManager::TextureId textureId, TextureUploadObserver* observer)
-{
-  int textureInfoIndex = GetCacheIndexFromId(textureId);
-
-  if(textureInfoIndex != INVALID_INDEX)
-  {
-    TextureInfo& textureInfo(mTextureInfoContainer[textureInfoIndex]);
-
-    DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureManager::Remove(%d) url:%s\n  cacheIdx:%d loadState:%s reference count = %d\n", textureId, textureInfo.url.GetUrl().c_str(), textureInfoIndex, GET_LOAD_STATE_STRING(textureInfo.loadState), textureInfo.referenceCount);
-
-    // Decrement the reference count and check if this is the last user of this Texture.
-    if(--textureInfo.referenceCount <= 0)
-    {
-      // This is the last remove for this Texture.
-      textureInfo.referenceCount = 0;
-      bool removeTextureInfo     = false;
-
-      // If loaded, we can remove the TextureInfo and the Atlas (if atlased).
-      if(textureInfo.loadState == LoadState::UPLOADED)
-      {
-        if(textureInfo.atlas)
-        {
-          textureInfo.atlas.Remove(textureInfo.atlasRect);
-        }
-        removeTextureInfo = true;
-      }
-      else if(textureInfo.loadState == LoadState::LOADING)
-      {
-        // We mark the textureInfo for removal.
-        // Once the load has completed, this method will be called again.
-        textureInfo.loadState = LoadState::CANCELLED;
-      }
-      else
-      {
-        // In other states, we are not waiting for a load so we are safe to remove the TextureInfo data.
-        removeTextureInfo = true;
-      }
-
-      // If the state allows us to remove the TextureInfo data, we do so.
-      if(removeTextureInfo)
-      {
-        // If url location is BUFFER, decrease reference count of EncodedImageBuffer.
-        if(textureInfo.url.IsBufferResource())
-        {
-          RemoveExternalEncodedImageBuffer(textureInfo.url.GetUrl());
-        }
-        // Permanently remove the textureInfo struct.
-        mTextureInfoContainer.erase(mTextureInfoContainer.begin() + textureInfoIndex);
-      }
-    }
-
-    if(observer)
-    {
-      // Remove element from the LoadQueue
-      for(auto&& element : mLoadQueue)
-      {
-        if(element.mObserver == observer)
-        {
-          // Do not erase the item. We will clear it later in ProcessQueuedTextures().
-          element.mObserver = nullptr;
-          break;
-        }
-      }
-    }
-  }
-}
-
-VisualUrl TextureManager::GetVisualUrl(TextureId textureId)
-{
-  VisualUrl visualUrl("");
-  int       cacheIndex = GetCacheIndexFromId(textureId);
-
-  if(cacheIndex != INVALID_CACHE_INDEX)
-  {
-    DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureManager::GetVisualUrl. Using cached texture id=%d, textureId=%d\n", cacheIndex, textureId);
-
-    TextureInfo& cachedTextureInfo(mTextureInfoContainer[cacheIndex]);
-    visualUrl = cachedTextureInfo.url;
-  }
-  return visualUrl;
-}
-
-TextureManager::LoadState TextureManager::GetTextureState(TextureId textureId)
-{
-  LoadState loadState = TextureManager::LoadState::NOT_STARTED;
-
-  int cacheIndex = GetCacheIndexFromId(textureId);
-  if(cacheIndex != INVALID_CACHE_INDEX)
-  {
-    TextureInfo& cachedTextureInfo(mTextureInfoContainer[cacheIndex]);
-    loadState = cachedTextureInfo.loadState;
-  }
-  else
-  {
-    for(auto&& elem : mExternalTextures)
-    {
-      if(elem.textureId == textureId)
-      {
-        loadState = LoadState::UPLOADED;
-        break;
-      }
-    }
-  }
-  return loadState;
-}
-
-TextureManager::LoadState TextureManager::GetTextureStateInternal(TextureId textureId)
-{
-  LoadState loadState = TextureManager::LoadState::NOT_STARTED;
-
-  int cacheIndex = GetCacheIndexFromId(textureId);
-  if(cacheIndex != INVALID_CACHE_INDEX)
-  {
-    TextureInfo& cachedTextureInfo(mTextureInfoContainer[cacheIndex]);
-    loadState = cachedTextureInfo.loadState;
-  }
-
-  return loadState;
-}
-
-Devel::PixelBuffer TextureManager::LoadImageSynchronously(const VisualUrl&         url,
-                                                          const ImageDimensions    desiredSize,
-                                                          FittingMode::Type        fittingMode,
-                                                          Dali::SamplingMode::Type samplingMode,
-                                                          bool                     orientationCorrection)
-{
-  Devel::PixelBuffer pixelBuffer;
-  if(url.IsBufferResource())
-  {
-    const EncodedImageBuffer& encodedImageBuffer = GetEncodedImageBuffer(url.GetUrl());
-    if(encodedImageBuffer)
-    {
-      pixelBuffer = LoadImageFromBuffer(encodedImageBuffer.GetRawBuffer(), desiredSize, fittingMode, samplingMode, orientationCorrection);
-    }
-  }
-  else
-  {
-    pixelBuffer = LoadImageFromFile(url.GetUrl(), desiredSize, fittingMode, samplingMode, orientationCorrection);
-  }
-  return pixelBuffer;
-}
-
-TextureSet TextureManager::GetTextureSet(TextureId textureId)
-{
-  TextureSet textureSet; // empty handle
-
-  int cacheIndex = GetCacheIndexFromId(textureId);
-  if(cacheIndex != INVALID_CACHE_INDEX)
-  {
-    TextureInfo& cachedTextureInfo(mTextureInfoContainer[cacheIndex]);
-    textureSet = cachedTextureInfo.textureSet;
-  }
-  else
-  {
-    for(auto&& elem : mExternalTextures)
-    {
-      if(elem.textureId == textureId)
-      {
-        textureSet = elem.textureSet;
-        break;
-      }
-    }
-  }
-  return textureSet;
-}
-
-EncodedImageBuffer TextureManager::GetEncodedImageBuffer(TextureId textureId)
-{
-  EncodedImageBuffer encodedImageBuffer; // empty handle
-  for(auto&& elem : mEncodedBufferTextures)
-  {
-    if(elem.textureId == textureId)
-    {
-      encodedImageBuffer = elem.encodedImageBuffer;
-      break;
-    }
-  }
-  return encodedImageBuffer;
-}
-
-EncodedImageBuffer TextureManager::GetEncodedImageBuffer(const std::string& url)
-{
-  EncodedImageBuffer encodedImageBuffer; // empty handle
-  if(url.size() > 0 && VisualUrl::BUFFER == VisualUrl::GetProtocolType(url))
-  {
-    std::string location = VisualUrl::GetLocation(url);
-    if(location.size() > 0u)
-    {
-      TextureId targetId = std::stoi(location);
-      return GetEncodedImageBuffer(targetId);
-    }
-  }
-  return encodedImageBuffer;
-}
-
-std::string TextureManager::AddExternalTexture(TextureSet& textureSet)
-{
-  TextureManager::ExternalTextureInfo info;
-  info.textureId  = GenerateUniqueTextureId();
-  info.textureSet = textureSet;
-  mExternalTextures.emplace_back(info);
-
-  return VisualUrl::CreateTextureUrl(std::to_string(info.textureId));
-}
-
-std::string TextureManager::AddExternalEncodedImageBuffer(const EncodedImageBuffer& encodedImageBuffer)
-{
-  // Duplication check
-  for(auto&& elem : mEncodedBufferTextures)
-  {
-    if(elem.encodedImageBuffer == encodedImageBuffer)
-    {
-      // If same buffer added, increase reference count and return.
-      elem.referenceCount++;
-      return VisualUrl::CreateBufferUrl(std::to_string(elem.textureId));
-    }
-  }
-  TextureManager::EncodedBufferTextureInfo info(GenerateUniqueTextureId(), encodedImageBuffer);
-  mEncodedBufferTextures.emplace_back(info);
-  return VisualUrl::CreateBufferUrl(std::to_string(info.textureId));
-}
-
-TextureSet TextureManager::RemoveExternalTexture(const std::string& url)
-{
-  if(url.size() > 0u)
-  {
-    if(VisualUrl::TEXTURE == VisualUrl::GetProtocolType(url))
-    {
-      // get the location from the Url
-      std::string location = VisualUrl::GetLocation(url);
-      if(location.size() > 0u)
-      {
-        TextureId  id  = std::stoi(location);
-        const auto end = mExternalTextures.end();
-        for(auto iter = mExternalTextures.begin(); iter != end; ++iter)
-        {
-          if(iter->textureId == id)
-          {
-            auto textureSet = iter->textureSet;
-            if(--(iter->referenceCount) <= 0)
-            {
-              mExternalTextures.erase(iter);
-            }
-            return textureSet;
-          }
-        }
-      }
-    }
-  }
-  return TextureSet();
-}
-
-EncodedImageBuffer TextureManager::RemoveExternalEncodedImageBuffer(const std::string& url)
-{
-  if(url.size() > 0u)
-  {
-    if(VisualUrl::BUFFER == VisualUrl::GetProtocolType(url))
-    {
-      // get the location from the Url
-      std::string location = VisualUrl::GetLocation(url);
-      if(location.size() > 0u)
-      {
-        TextureId  id  = std::stoi(location);
-        const auto end = mEncodedBufferTextures.end();
-        for(auto iter = mEncodedBufferTextures.begin(); iter != end; ++iter)
-        {
-          if(iter->textureId == id)
-          {
-            auto encodedImageBuffer = iter->encodedImageBuffer;
-            if(--(iter->referenceCount) <= 0)
-            {
-              mEncodedBufferTextures.erase(iter);
-            }
-            return encodedImageBuffer;
-          }
-        }
-      }
-    }
-  }
-  return EncodedImageBuffer();
-}
-
-void TextureManager::UseExternalResource(const VisualUrl& url)
-{
-  if(VisualUrl::TEXTURE == url.GetProtocolType())
-  {
-    std::string location = url.GetLocation();
-    if(location.size() > 0u)
-    {
-      TextureId id = std::stoi(location);
-      for(auto&& elem : mExternalTextures)
-      {
-        if(elem.textureId == id)
-        {
-          elem.referenceCount++;
-          return;
-        }
-      }
-    }
-  }
-  else if(VisualUrl::BUFFER == url.GetProtocolType())
-  {
-    std::string location = url.GetLocation();
-    if(location.size() > 0u)
-    {
-      TextureId id = std::stoi(location);
-      for(auto&& elem : mEncodedBufferTextures)
-      {
-        if(elem.textureId == id)
-        {
-          elem.referenceCount++;
-          return;
-        }
-      }
-    }
-  }
-}
-
-void TextureManager::AddObserver(TextureManager::LifecycleObserver& observer)
-{
-  // make sure an observer doesn't observe the same object twice
-  // otherwise it will get multiple calls to ObjectDestroyed()
-  DALI_ASSERT_DEBUG(mLifecycleObservers.End() == std::find(mLifecycleObservers.Begin(), mLifecycleObservers.End(), &observer));
-  mLifecycleObservers.PushBack(&observer);
-}
-
-void TextureManager::RemoveObserver(TextureManager::LifecycleObserver& observer)
-{
-  // Find the observer...
-  auto endIter = mLifecycleObservers.End();
-  for(auto iter = mLifecycleObservers.Begin(); iter != endIter; ++iter)
-  {
-    if((*iter) == &observer)
-    {
-      mLifecycleObservers.Erase(iter);
-      break;
-    }
-  }
-  DALI_ASSERT_DEBUG(endIter != mLifecycleObservers.End());
-}
-
-void TextureManager::LoadOrQueueTexture(TextureInfo& textureInfo, TextureUploadObserver* observer)
-{
-  switch(textureInfo.loadState)
-  {
-    case LoadState::NOT_STARTED:
-    case LoadState::LOAD_FAILED:
-    {
-      if(mQueueLoadFlag)
-      {
-        QueueLoadTexture(textureInfo, observer);
-      }
-      else
-      {
-        LoadTexture(textureInfo, observer);
-      }
-      break;
-    }
-    case LoadState::UPLOADED:
-    {
-      if(mQueueLoadFlag)
-      {
-        QueueLoadTexture(textureInfo, observer);
-      }
-      else
-      {
-        // The Texture has already loaded. The other observers have already been notified.
-        // We need to send a "late" loaded notification for this observer.
-        observer->LoadComplete(true, TextureUploadObserver::TextureInformation(TextureUploadObserver::ReturnType::TEXTURE, textureInfo.textureId, textureInfo.textureSet, textureInfo.useAtlas, textureInfo.atlasRect, textureInfo.preMultiplied));
-      }
-      break;
-    }
-    case LoadState::LOADING:
-    case LoadState::CANCELLED:
-    case LoadState::LOAD_FINISHED:
-    case LoadState::WAITING_FOR_MASK:
-    case LoadState::MASK_APPLYING:
-    case LoadState::MASK_APPLIED:
-    {
-      break;
-    }
-  }
-}
-
-void TextureManager::QueueLoadTexture(TextureInfo& textureInfo, TextureUploadObserver* observer)
-{
-  auto textureId = textureInfo.textureId;
-  mLoadQueue.PushBack(LoadQueueElement(textureId, observer));
-
-  observer->DestructionSignal().Connect(this, &TextureManager::ObserverDestroyed);
-}
-
-void TextureManager::LoadTexture(TextureInfo& textureInfo, TextureUploadObserver* observer)
-{
-  DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureManager::LoadTexture(): url:%s sync:%s\n", textureInfo.url.GetUrl().c_str(), textureInfo.loadSynchronously ? "T" : "F");
-
-  textureInfo.loadState = LoadState::LOADING;
-  if(!textureInfo.loadSynchronously)
-  {
-    auto& loadersContainer  = (textureInfo.url.IsLocalResource() || textureInfo.url.IsBufferResource()) ? mAsyncLocalLoaders : mAsyncRemoteLoaders;
-    auto  loadingHelperIt   = loadersContainer.GetNext();
-    auto  premultiplyOnLoad = (textureInfo.preMultiplyOnLoad && textureInfo.maskTextureId == INVALID_TEXTURE_ID) ? DevelAsyncImageLoader::PreMultiplyOnLoad::ON : DevelAsyncImageLoader::PreMultiplyOnLoad::OFF;
-    DALI_ASSERT_ALWAYS(loadingHelperIt != loadersContainer.End());
-    if(textureInfo.animatedImageLoading)
-    {
-      loadingHelperIt->LoadAnimatedImage(textureInfo.textureId, textureInfo.animatedImageLoading, textureInfo.frameIndex);
-    }
-    else
-    {
-      loadingHelperIt->Load(textureInfo.textureId, textureInfo.url, textureInfo.desiredSize, textureInfo.fittingMode, textureInfo.samplingMode, textureInfo.orientationCorrection, premultiplyOnLoad);
-    }
-  }
-  ObserveTexture(textureInfo, observer);
-}
-
-void TextureManager::ProcessQueuedTextures()
-{
-  for(auto&& element : mLoadQueue)
-  {
-    if(!element.mObserver)
-    {
-      continue;
-    }
-
-    int cacheIndex = GetCacheIndexFromId(element.mTextureId);
-    if(cacheIndex != INVALID_CACHE_INDEX)
-    {
-      TextureInfo& textureInfo(mTextureInfoContainer[cacheIndex]);
-      if(textureInfo.loadState == LoadState::UPLOADED)
-      {
-        element.mObserver->LoadComplete(true, TextureUploadObserver::TextureInformation(TextureUploadObserver::ReturnType::TEXTURE, textureInfo.textureId, textureInfo.textureSet, textureInfo.useAtlas, textureInfo.atlasRect, textureInfo.preMultiplied));
-      }
-      else if(textureInfo.loadState == LoadState::LOAD_FINISHED && textureInfo.storageType == StorageType::RETURN_PIXEL_BUFFER)
-      {
-        element.mObserver->LoadComplete(true, TextureUploadObserver::TextureInformation(TextureUploadObserver::ReturnType::PIXEL_BUFFER, textureInfo.pixelBuffer, textureInfo.url.GetUrl(), textureInfo.preMultiplied));
-      }
-      else
-      {
-        LoadTexture(textureInfo, element.mObserver);
-      }
-    }
-  }
-  mLoadQueue.Clear();
-}
-
-void TextureManager::ObserveTexture(TextureInfo&           textureInfo,
-                                    TextureUploadObserver* observer)
-{
-  DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureManager::ObserveTexture(): url:%s observer:%p\n", textureInfo.url.GetUrl().c_str(), observer);
-
-  if(observer)
-  {
-    textureInfo.observerList.PushBack(observer);
-    observer->DestructionSignal().Connect(this, &TextureManager::ObserverDestroyed);
-  }
-}
-
-void TextureManager::AsyncLoadComplete(AsyncLoadingInfoContainerType& loadingContainer, uint32_t id, Devel::PixelBuffer pixelBuffer)
-{
-  DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureManager::AsyncLoadComplete( id:%d )\n", id);
-
-  if(loadingContainer.size() >= 1u)
-  {
-    AsyncLoadingInfo loadingInfo = loadingContainer.front();
-
-    if(loadingInfo.loadId == id)
-    {
-      int cacheIndex = GetCacheIndexFromId(loadingInfo.textureId);
-      if(cacheIndex != INVALID_CACHE_INDEX)
-      {
-        TextureInfo& textureInfo(mTextureInfoContainer[cacheIndex]);
-
-        DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "  textureId:%d Url:%s CacheIndex:%d LoadState: %d\n", textureInfo.textureId, textureInfo.url.GetUrl().c_str(), cacheIndex, textureInfo.loadState);
-
-        if(textureInfo.loadState != LoadState::CANCELLED)
-        {
-          // textureInfo can be invalidated after this call (as the mTextureInfoContainer may be modified)
-          PostLoad(textureInfo, pixelBuffer);
-        }
-        else
-        {
-          Remove(textureInfo.textureId, nullptr);
-        }
-      }
-    }
-
-    loadingContainer.pop_front();
-  }
-}
-
-void TextureManager::PostLoad(TextureInfo& textureInfo, Devel::PixelBuffer& pixelBuffer)
-{
-  // Was the load successful?
-  if(pixelBuffer && (pixelBuffer.GetWidth() != 0) && (pixelBuffer.GetHeight() != 0))
-  {
-    // No atlas support for now
-    textureInfo.useAtlas      = NO_ATLAS;
-    textureInfo.preMultiplied = pixelBuffer.IsAlphaPreMultiplied();
-
-    if(textureInfo.storageType == StorageType::UPLOAD_TO_TEXTURE)
-    {
-      // If there is a mask texture ID associated with this texture, then apply the mask
-      // if it's already loaded. If it hasn't, and the mask is still loading,
-      // wait for the mask to finish loading.
-      // note, If the texture is already uploaded synchronously during loading,
-      // we don't need to apply mask.
-      if(textureInfo.loadState != LoadState::UPLOADED &&
-         textureInfo.maskTextureId != INVALID_TEXTURE_ID)
-      {
-        if(textureInfo.loadState == LoadState::MASK_APPLYING)
-        {
-          textureInfo.loadState = LoadState::MASK_APPLIED;
-          UploadTexture(pixelBuffer, textureInfo);
-          NotifyObservers(textureInfo, true);
-        }
-        else
-        {
-          LoadState maskLoadState = GetTextureStateInternal(textureInfo.maskTextureId);
-          textureInfo.pixelBuffer = pixelBuffer; // Store the pixel buffer temporarily
-          if(maskLoadState == LoadState::LOADING)
-          {
-            textureInfo.loadState = LoadState::WAITING_FOR_MASK;
-          }
-          else if(maskLoadState == LoadState::LOAD_FINISHED)
-          {
-            // Send New Task to Thread
-            ApplyMask(textureInfo, textureInfo.maskTextureId);
-          }
-        }
-      }
-      else
-      {
-        UploadTexture(pixelBuffer, textureInfo);
-        NotifyObservers(textureInfo, true);
-      }
-    }
-    else
-    {
-      textureInfo.pixelBuffer = pixelBuffer; // Store the pixel data
-      textureInfo.loadState   = LoadState::LOAD_FINISHED;
-
-      if(textureInfo.storageType == StorageType::RETURN_PIXEL_BUFFER)
-      {
-        NotifyObservers(textureInfo, true);
-      }
-      else
-      {
-        // Check if there was another texture waiting for this load to complete
-        // (e.g. if this was an image mask, and its load is on a different thread)
-        CheckForWaitingTexture(textureInfo);
-      }
-    }
-  }
-  else
-  {
-    textureInfo.loadState = LoadState::LOAD_FAILED;
-    CheckForWaitingTexture(textureInfo);
-    NotifyObservers(textureInfo, false);
-  }
-}
-
-void TextureManager::CheckForWaitingTexture(TextureInfo& maskTextureInfo)
-{
-  // Search the cache, checking if any texture has this texture id as a
-  // maskTextureId:
-  const unsigned int size = mTextureInfoContainer.size();
-
-  for(unsigned int cacheIndex = 0; cacheIndex < size; ++cacheIndex)
-  {
-    if(mTextureInfoContainer[cacheIndex].maskTextureId == maskTextureInfo.textureId &&
-       mTextureInfoContainer[cacheIndex].loadState == LoadState::WAITING_FOR_MASK)
-    {
-      TextureInfo& textureInfo(mTextureInfoContainer[cacheIndex]);
-
-      if(maskTextureInfo.loadState == LoadState::LOAD_FINISHED)
-      {
-        // Send New Task to Thread
-        ApplyMask(textureInfo, maskTextureInfo.textureId);
-      }
-      else
-      {
-        textureInfo.pixelBuffer.Reset();
-        textureInfo.loadState = LoadState::LOAD_FAILED;
-        NotifyObservers(textureInfo, false);
-      }
-    }
-  }
-}
-
-void TextureManager::ApplyMask(TextureInfo& textureInfo, TextureId maskTextureId)
-{
-  int maskCacheIndex = GetCacheIndexFromId(maskTextureId);
-  if(maskCacheIndex != INVALID_CACHE_INDEX)
-  {
-    Devel::PixelBuffer maskPixelBuffer = mTextureInfoContainer[maskCacheIndex].pixelBuffer;
-    Devel::PixelBuffer pixelBuffer     = textureInfo.pixelBuffer;
-    textureInfo.pixelBuffer.Reset();
-
-    DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureManager::ApplyMask(): url:%s sync:%s\n", textureInfo.url.GetUrl().c_str(), textureInfo.loadSynchronously ? "T" : "F");
-
-    textureInfo.loadState   = LoadState::MASK_APPLYING;
-    auto& loadersContainer  = (textureInfo.url.IsLocalResource() || textureInfo.url.IsBufferResource()) ? mAsyncLocalLoaders : mAsyncRemoteLoaders;
-    auto  loadingHelperIt   = loadersContainer.GetNext();
-    auto  premultiplyOnLoad = textureInfo.preMultiplyOnLoad ? DevelAsyncImageLoader::PreMultiplyOnLoad::ON : DevelAsyncImageLoader::PreMultiplyOnLoad::OFF;
-    DALI_ASSERT_ALWAYS(loadingHelperIt != loadersContainer.End());
-    loadingHelperIt->ApplyMask(textureInfo.textureId, pixelBuffer, maskPixelBuffer, textureInfo.scaleFactor, textureInfo.cropToMask, premultiplyOnLoad);
-  }
-}
-
-void TextureManager::UploadTexture(Devel::PixelBuffer& pixelBuffer, TextureInfo& textureInfo)
-{
-  if(textureInfo.loadState != LoadState::UPLOADED && textureInfo.useAtlas != USE_ATLAS)
-  {
-    DALI_LOG_INFO(gTextureManagerLogFilter, Debug::General, "  TextureManager::UploadTexture() New Texture for textureId:%d\n", textureInfo.textureId);
-
-    // Check if this pixelBuffer is premultiplied
-    textureInfo.preMultiplied = pixelBuffer.IsAlphaPreMultiplied();
-
-    auto& renderingAddOn = RenderingAddOn::Get();
-    if(renderingAddOn.IsValid())
-    {
-      renderingAddOn.CreateGeometry(textureInfo.textureId, pixelBuffer);
-    }
-
-    Texture texture = Texture::New(Dali::TextureType::TEXTURE_2D, pixelBuffer.GetPixelFormat(), pixelBuffer.GetWidth(), pixelBuffer.GetHeight());
-
-    PixelData pixelData = Devel::PixelBuffer::Convert(pixelBuffer);
-    texture.Upload(pixelData);
-    if(!textureInfo.textureSet)
-    {
-      textureInfo.textureSet = TextureSet::New();
-    }
-    textureInfo.textureSet.SetTexture(0u, texture);
-  }
-
-  // Update the load state.
-  // Note: This is regardless of success as we care about whether a
-  // load attempt is in progress or not.  If unsuccessful, a broken
-  // image is still loaded.
-  textureInfo.loadState = LoadState::UPLOADED;
-}
-
-void TextureManager::NotifyObservers(TextureInfo& textureInfo, bool success)
-{
-  TextureId textureId = textureInfo.textureId;
-
-  // If there is an observer: Notify the load is complete, whether successful or not,
-  // and erase it from the list
-  TextureInfo* info = &textureInfo;
-
-  mQueueLoadFlag = true;
-
-  while(info->observerList.Count())
-  {
-    TextureUploadObserver* observer = info->observerList[0];
-
-    // During LoadComplete() a Control ResourceReady() signal is emitted.
-    // During that signal the app may add remove /add Textures (e.g. via
-    // ImageViews).
-    // It is possible for observers to be removed from the observer list,
-    // and it is also possible for the mTextureInfoContainer to be modified,
-    // invalidating the reference to the textureInfo struct.
-    // Texture load requests for the same URL are deferred until the end of this
-    // method.
-    DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "NotifyObservers() url:%s loadState:%s\n", textureInfo.url.GetUrl().c_str(), GET_LOAD_STATE_STRING(textureInfo.loadState));
-
-    // It is possible for the observer to be deleted.
-    // Disconnect and remove the observer first.
-    observer->DestructionSignal().Disconnect(this, &TextureManager::ObserverDestroyed);
-
-    info->observerList.Erase(info->observerList.begin());
-
-    if(info->storageType == StorageType::RETURN_PIXEL_BUFFER)
-    {
-      observer->LoadComplete(success, TextureUploadObserver::TextureInformation(TextureUploadObserver::ReturnType::PIXEL_BUFFER, info->pixelBuffer, info->url.GetUrl(), info->preMultiplied));
-    }
-    else
-    {
-      observer->LoadComplete(success, TextureUploadObserver::TextureInformation(TextureUploadObserver::ReturnType::TEXTURE, info->textureId, info->textureSet, info->useAtlas, info->atlasRect, info->preMultiplied));
-    }
-
-    // Get the textureInfo from the container again as it may have been invalidated.
-    int textureInfoIndex = GetCacheIndexFromId(textureId);
-    if(textureInfoIndex == INVALID_CACHE_INDEX)
-    {
-      break; // texture has been removed - can stop.
-    }
-    info = &mTextureInfoContainer[textureInfoIndex];
-  }
-
-  mQueueLoadFlag = false;
-  ProcessQueuedTextures();
-
-  if(info->storageType == StorageType::RETURN_PIXEL_BUFFER && info->observerList.Count() == 0)
-  {
-    Remove(info->textureId, nullptr);
-  }
-}
-
-TextureManager::TextureId TextureManager::GenerateUniqueTextureId()
-{
-  return mCurrentTextureId++;
-}
-
-int TextureManager::GetCacheIndexFromId(const TextureId textureId)
-{
-  const unsigned int size = mTextureInfoContainer.size();
-
-  for(unsigned int i = 0; i < size; ++i)
-  {
-    if(mTextureInfoContainer[i].textureId == textureId)
-    {
-      return i;
-    }
-  }
-
-  return INVALID_CACHE_INDEX;
-}
-
-TextureManager::TextureHash TextureManager::GenerateHash(
-  const std::string&             url,
-  const ImageDimensions          size,
-  const FittingMode::Type        fittingMode,
-  const Dali::SamplingMode::Type samplingMode,
-  const UseAtlas                 useAtlas,
-  TextureId                      maskTextureId)
-{
-  std::string    hashTarget(url);
-  const size_t   urlLength = hashTarget.length();
-  const uint16_t width     = size.GetWidth();
-  const uint16_t height    = size.GetWidth();
-
-  // If either the width or height has been specified, include the resizing options in the hash
-  if(width != 0 || height != 0)
-  {
-    // We are appending 5 bytes to the URL to form the hash input.
-    hashTarget.resize(urlLength + 5u);
-    char* hashTargetPtr = &(hashTarget[urlLength]);
-
-    // Pack the width and height (4 bytes total).
-    *hashTargetPtr++ = size.GetWidth() & 0xff;
-    *hashTargetPtr++ = (size.GetWidth() >> 8u) & 0xff;
-    *hashTargetPtr++ = size.GetHeight() & 0xff;
-    *hashTargetPtr++ = (size.GetHeight() >> 8u) & 0xff;
-
-    // Bit-pack the FittingMode, SamplingMode and atlasing.
-    // FittingMode=2bits, SamplingMode=3bits, useAtlas=1bit
-    *hashTargetPtr = (fittingMode << 4u) | (samplingMode << 1) | useAtlas;
-  }
-  else
-  {
-    // We are not including sizing information, but we still need an extra byte for atlasing.
-    hashTarget.resize(urlLength + 1u);
-
-    // Add the atlasing to the hash input.
-    switch(useAtlas)
-    {
-      case UseAtlas::NO_ATLAS:
-      {
-        hashTarget[urlLength] = 'f';
-        break;
-      }
-      case UseAtlas::USE_ATLAS:
-      {
-        hashTarget[urlLength] = 't';
-        break;
-      }
-    }
-  }
-
-  if(maskTextureId != INVALID_TEXTURE_ID)
-  {
-    auto textureIdIndex = hashTarget.length();
-    hashTarget.resize(hashTarget.length() + sizeof(TextureId));
-    unsigned char* hashTargetPtr = reinterpret_cast<unsigned char*>(&(hashTarget[textureIdIndex]));
-
-    // Append the texture id to the end of the URL byte by byte:
-    // (to avoid SIGBUS / alignment issues)
-    for(size_t byteIter = 0; byteIter < sizeof(TextureId); ++byteIter)
-    {
-      *hashTargetPtr++ = maskTextureId & 0xff;
-      maskTextureId >>= 8u;
-    }
-  }
-
-  return Dali::CalculateHash(hashTarget);
-}
-
-int TextureManager::FindCachedTexture(
-  const TextureManager::TextureHash hash,
-  const std::string&                url,
-  const ImageDimensions             size,
-  const FittingMode::Type           fittingMode,
-  const Dali::SamplingMode::Type    samplingMode,
-  const bool                        useAtlas,
-  TextureId                         maskTextureId,
-  TextureManager::MultiplyOnLoad    preMultiplyOnLoad)
-{
-  // Default to an invalid ID, in case we do not find a match.
-  int cacheIndex = INVALID_CACHE_INDEX;
-
-  // Iterate through our hashes to find a match.
-  const unsigned int count = mTextureInfoContainer.size();
-  for(unsigned int i = 0u; i < count; ++i)
-  {
-    if(mTextureInfoContainer[i].hash == hash)
-    {
-      // We have a match, now we check all the original parameters in case of a hash collision.
-      TextureInfo& textureInfo(mTextureInfoContainer[i]);
-
-      if((url == textureInfo.url.GetUrl()) &&
-         (useAtlas == textureInfo.useAtlas) &&
-         (maskTextureId == textureInfo.maskTextureId) &&
-         (size == textureInfo.desiredSize) &&
-         ((size.GetWidth() == 0 && size.GetHeight() == 0) ||
-          (fittingMode == textureInfo.fittingMode &&
-           samplingMode == textureInfo.samplingMode)))
-      {
-        // 1. If preMultiplyOnLoad is MULTIPLY_ON_LOAD, then textureInfo.preMultiplyOnLoad should be true. The premultiplication result can be different.
-        // 2. If preMultiplyOnLoad is LOAD_WITHOUT_MULTIPLY, then textureInfo.preMultiplied should be false.
-        if((preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD && textureInfo.preMultiplyOnLoad) || (preMultiplyOnLoad == TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY && !textureInfo.preMultiplied))
-        {
-          // The found Texture is a match.
-          cacheIndex = i;
-          break;
-        }
-      }
-    }
-  }
-
-  return cacheIndex;
-}
-
-void TextureManager::ObserverDestroyed(TextureUploadObserver* observer)
-{
-  const unsigned int count = mTextureInfoContainer.size();
-  for(unsigned int i = 0; i < count; ++i)
-  {
-    TextureInfo& textureInfo(mTextureInfoContainer[i]);
-    for(TextureInfo::ObserverListType::Iterator j = textureInfo.observerList.Begin();
-        j != textureInfo.observerList.End();)
-    {
-      if(*j == observer)
-      {
-        j = textureInfo.observerList.Erase(j);
-      }
-      else
-      {
-        ++j;
-      }
-    }
-  }
-
-  // Remove element from the LoadQueue
-  for(auto&& element : mLoadQueue)
-  {
-    if(element.mObserver == observer)
-    {
-      element.mObserver = nullptr;
-    }
-  }
-}
-
-TextureManager::AsyncLoadingHelper::AsyncLoadingHelper(TextureManager& textureManager)
-: AsyncLoadingHelper(Toolkit::AsyncImageLoader::New(), textureManager, AsyncLoadingInfoContainerType())
-{
-}
-
-void TextureManager::AsyncLoadingHelper::LoadAnimatedImage(TextureId                  textureId,
-                                                           Dali::AnimatedImageLoading animatedImageLoading,
-                                                           uint32_t                   frameIndex)
-{
-  mLoadingInfoContainer.push_back(AsyncLoadingInfo(textureId));
-  auto id                             = GetImplementation(mLoader).LoadAnimatedImage(animatedImageLoading, frameIndex);
-  mLoadingInfoContainer.back().loadId = id;
-}
-
-void TextureManager::AsyncLoadingHelper::Load(TextureId                                textureId,
-                                              const VisualUrl&                         url,
-                                              ImageDimensions                          desiredSize,
-                                              FittingMode::Type                        fittingMode,
-                                              SamplingMode::Type                       samplingMode,
-                                              bool                                     orientationCorrection,
-                                              DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
-{
-  mLoadingInfoContainer.push_back(AsyncLoadingInfo(textureId));
-  if(DALI_UNLIKELY(url.IsBufferResource()))
-  {
-    auto id                             = GetImplementation(mLoader).LoadEncodedImageBuffer(mTextureManager.GetEncodedImageBuffer(url.GetUrl()), desiredSize, fittingMode, samplingMode, orientationCorrection, preMultiplyOnLoad);
-    mLoadingInfoContainer.back().loadId = id;
-  }
-  else
-  {
-    auto id                             = GetImplementation(mLoader).Load(url, desiredSize, fittingMode, samplingMode, orientationCorrection, preMultiplyOnLoad);
-    mLoadingInfoContainer.back().loadId = id;
-  }
-}
-
-void TextureManager::AsyncLoadingHelper::ApplyMask(TextureId                                textureId,
-                                                   Devel::PixelBuffer                       pixelBuffer,
-                                                   Devel::PixelBuffer                       maskPixelBuffer,
-                                                   float                                    contentScale,
-                                                   bool                                     cropToMask,
-                                                   DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
-{
-  mLoadingInfoContainer.push_back(AsyncLoadingInfo(textureId));
-  auto id                             = GetImplementation(mLoader).ApplyMask(pixelBuffer, maskPixelBuffer, contentScale, cropToMask, preMultiplyOnLoad);
-  mLoadingInfoContainer.back().loadId = id;
-}
-
-TextureManager::AsyncLoadingHelper::AsyncLoadingHelper(AsyncLoadingHelper&& rhs)
-: AsyncLoadingHelper(rhs.mLoader, rhs.mTextureManager, std::move(rhs.mLoadingInfoContainer))
-{
-}
-
-TextureManager::AsyncLoadingHelper::AsyncLoadingHelper(
-  Toolkit::AsyncImageLoader       loader,
-  TextureManager&                 textureManager,
-  AsyncLoadingInfoContainerType&& loadingInfoContainer)
-: mLoader(loader),
-  mTextureManager(textureManager),
-  mLoadingInfoContainer(std::move(loadingInfoContainer))
-{
-  DevelAsyncImageLoader::PixelBufferLoadedSignal(mLoader).Connect(
-    this, &AsyncLoadingHelper::AsyncLoadComplete);
-}
-
-void TextureManager::AsyncLoadingHelper::AsyncLoadComplete(uint32_t           id,
-                                                           Devel::PixelBuffer pixelBuffer)
-{
-  mTextureManager.AsyncLoadComplete(mLoadingInfoContainer, id, pixelBuffer);
-}
-
-Geometry TextureManager::GetRenderGeometry(TextureId textureId, uint32_t& frontElements, uint32_t& backElements)
-{
-  return RenderingAddOn::Get().IsValid() ? RenderingAddOn::Get().GetGeometry(textureId, frontElements, backElements) : Geometry();
-}
-
-} // namespace Internal
-
-} // namespace Toolkit
-
-} // namespace Dali
diff --git a/dali-toolkit/internal/visuals/texture-manager-impl.h b/dali-toolkit/internal/visuals/texture-manager-impl.h
deleted file mode 100644 (file)
index 7ca7a05..0000000
+++ /dev/null
@@ -1,957 +0,0 @@
-#ifndef DALI_TOOLKIT_TEXTURE_MANAGER_IMPL_H
-#define DALI_TOOLKIT_TEXTURE_MANAGER_IMPL_H
-
-/*
- * Copyright (c) 2021 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// EXTERNAL INCLUDES
-#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
-#include <dali/devel-api/common/owner-container.h>
-#include <dali/public-api/adaptor-framework/encoded-image-buffer.h>
-#include <dali/public-api/common/dali-vector.h>
-#include <dali/public-api/object/ref-object.h>
-#include <dali/public-api/rendering/geometry.h>
-#include <dali/public-api/rendering/texture-set.h>
-#include <deque>
-#include <functional>
-#include <memory>
-#include <string>
-
-// INTERNAL INCLUDES
-#include <dali-toolkit/devel-api/image-loader/async-image-loader-devel.h>
-#include <dali-toolkit/devel-api/image-loader/image-atlas.h>
-#include <dali-toolkit/internal/helpers/round-robin-container-view.h>
-#include <dali-toolkit/internal/image-loader/async-image-loader-impl.h>
-#include <dali-toolkit/internal/visuals/texture-upload-observer.h>
-#include <dali-toolkit/internal/visuals/visual-url.h>
-#include <dali-toolkit/public-api/image-loader/async-image-loader.h>
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Internal
-{
-class ImageAtlasManager;
-typedef IntrusivePtr<ImageAtlasManager> ImageAtlasManagerPtr;
-
-/**
- * The TextureManager provides a common Image loading API for Visuals.
- *
- * The TextureManager is responsible for providing sync, async, atlased and non-atlased loads.
- * Texture caching is provided and performed when possible.
- * Broken Images are automatically provided on load failure.
- */
-class TextureManager : public ConnectionTracker
-{
-public:
-  typedef int32_t  TextureId;               ///< The TextureId type. This is used as a handle to refer to a particular Texture.
-  static const int INVALID_TEXTURE_ID = -1; ///< Used to represent a null TextureId or error
-
-  /**
-   * Whether the texture should be atlased or uploaded into it's own GPU texture
-   */
-  enum UseAtlas
-  {
-    NO_ATLAS,
-    USE_ATLAS
-  };
-
-  /**
-   * Whether the pixel data should be kept in TextureManager, returned with pixelBuffer or uploaded for rendering
-   */
-  enum class StorageType : uint8_t
-  {
-    KEEP_PIXEL_BUFFER,    ///< Keep loaded pixel buffer inside of texture manager without making texture. This could be used for inside pixel process like mask image.
-    RETURN_PIXEL_BUFFER,  ///< Return loaded pixel buffer without making texture.
-                          ///  Because a pixel buffer cannot be used multiple texture, this pixel buffer only cached during loading, and is removed after loading is finished.
-    UPLOAD_TO_TEXTURE     ///< Loaded image will be uploaded to texture and the texture will be returned.
-  };
-
-  /**
-   * Whether the texture should be loaded synchronously or asynchronously.
-   */
-  enum class LoadType : uint8_t
-  {
-    LOAD_ASYNCHRONOUSLY,
-    LOAD_SYNCHRONOUSLY
-  };
-
-  /**
-   * @brief The LoadState Enumeration represents the current state of a particular Texture's life-cycle.
-   */
-  enum class LoadState : uint8_t
-  {
-    NOT_STARTED,      ///< Default
-    LOADING,          ///< Loading has been started, but not finished.
-    LOAD_FINISHED,    ///< Loading has finished. (for CPU storage only)
-    WAITING_FOR_MASK, ///< Loading has finished, but waiting for mask image
-    MASK_APPLYING,    ///< Loading has finished, Mask is applying
-    MASK_APPLIED,     ///< Loading has finished, Mask is applyied by GPU
-    UPLOADED,         ///< Uploaded and ready. (For GPU upload only)
-    CANCELLED,        ///< Removed before loading completed
-    LOAD_FAILED       ///< Async loading failed, e.g. connection problem
-  };
-
-  /**
-   * @brief Types of reloading policies
-   */
-  enum class ReloadPolicy
-  {
-    CACHED = 0, ///< Loads cached texture if it exists.
-    FORCED      ///< Forces reloading of texture.
-  };
-
-  /**
-   * @brief Whether to multiply alpha into color channels on load
-   */
-  enum class MultiplyOnLoad
-  {
-    LOAD_WITHOUT_MULTIPLY = 0, ///< Don't modify the image
-    MULTIPLY_ON_LOAD           ///< Multiply alpha into color channels on load
-  };
-
-public:
-  struct MaskingData
-  {
-    MaskingData();
-    ~MaskingData() = default;
-
-    VisualUrl                 mAlphaMaskUrl;
-    TextureManager::TextureId mAlphaMaskId;
-    float                     mContentScaleFactor;
-    bool                      mCropToMask;
-  };
-  using MaskingDataPointer = std::unique_ptr<MaskingData>;
-
-  /**
-   * Class to provide lifecycle event on destruction of texture manager.
-   */
-  struct LifecycleObserver
-  {
-    /**
-     * Called shortly before the texture manager is destroyed.
-     */
-    virtual void TextureManagerDestroyed() = 0;
-  };
-
-  /**
-   * Constructor.
-   */
-  TextureManager();
-
-  /**
-   * Destructor.
-   */
-  ~TextureManager() override;
-
-  // TextureManager Main API:
-
-  /**
-   * @brief Requests an frame of animated image load.
-   *
-   * The parameters are used to specify how the animated image is loaded.
-   * The observer has the LoadComplete method called when the load is ready.
-   *
-   * @param[in] animatedImageLoading  The AnimatedImageLoading that contain the animated image information
-   * @param[in] frameIndex            The frame index to load.
-   * @param[in] samplingMode          The SamplingMode to use
-   * @param[in] synchronousLoading    true if the frame should be loaded synchronously
-   * @param[out] textureId            The textureId of the frame
-   * @param[in] wrapModeU             Horizontal Wrap mode
-   * @param[in] wrapModeV             Vertical Wrap mode
-   * @param[in] textureObserver       The client object should inherit from this and provide the "UploadCompleted" virtual.
-   *                                  This is called when an image load completes (or fails).
-   *
-   * @return                          The texture set containing the frame of animated image, or empty if still loading.
-   */
-  TextureSet LoadAnimatedImageTexture(Dali::AnimatedImageLoading animatedImageLoading,
-                                      uint32_t                   frameIndex,
-                                      Dali::SamplingMode::Type   samplingMode,
-                                      bool                       synchronousLoading,
-                                      TextureManager::TextureId& textureId,
-                                      Dali::WrapMode::Type       wrapModeU,
-                                      Dali::WrapMode::Type       wrapModeV,
-                                      TextureUploadObserver*     textureObserver);
-
-  /**
-   * @brief Requests an image load of the given URL to get PixelBuffer.
-   *
-   * The parameters are used to specify how the image is loaded.
-   * The observer has the LoadComplete method called when the load is ready.
-   *
-   * @param[in] url                   The URL of the image to load
-   * @param[in] desiredSize           The size the image is likely to appear at. This can be set to 0,0 for automatic
-   * @param[in] fittingMode           The FittingMode to use
-   * @param[in] samplingMode          The SamplingMode to use
-   * @param[in] synchronousLoading    true if the URL should be loaded synchronously
-   * @param[in] textureObserver       The client object should inherit from this and provide the "UploadCompleted" virtual.
-   *                                  This is called when an image load completes (or fails).
-   * @param[in] orientationCorrection Whether to rotate image to match embedded orientation data
-   * @param[in,out] preMultiplyOnLoad True if the image color should be multiplied by it's alpha. Set to false if the
-   *                                  image has no alpha channel
-   *
-   * @return                          The pixel buffer containing the image, or empty if still loading.
-   */
-  Devel::PixelBuffer LoadPixelBuffer(const VisualUrl&                url,
-                                     Dali::ImageDimensions           desiredSize,
-                                     Dali::FittingMode::Type         fittingMode,
-                                     Dali::SamplingMode::Type        samplingMode,
-                                     bool                            synchronousLoading,
-                                     TextureUploadObserver*          textureObserver,
-                                     bool                            orientationCorrection,
-                                     TextureManager::MultiplyOnLoad& preMultiplyOnLoad);
-
-  /**
-   * @brief Requests an image load of the given URL.
-   *
-   * The parameters are used to specify how the image is loaded.
-   * The observer has the LoadComplete method called when the load is ready.
-   *
-   * When the client has finished with the Texture, Remove() should be called.
-   *
-   * @param[in] url                   The URL of the image to load
-   * @param[in] desiredSize           The size the image is likely to appear at. This can be set to 0,0 for automatic
-   * @param[in] fittingMode           The FittingMode to use
-   * @param[in] samplingMode          The SamplingMode to use
-   * @param[in, out] maskInfo         Mask info structure
-   * @param[in] synchronousLoading    true if the URL should be loaded synchronously
-   * @param[out] textureId,           The textureId of the URL
-   * @param[out] textureRect          The rectangle within the texture atlas that this URL occupies,
-   *                                  this is the rectangle in normalized coordinates.
-   * @param[out] textureRectSize      The rectangle within the texture atlas that this URL occupies,
-   *                                  this is the same rectangle in pixels.
-   * @param[in,out] atlasingStatus    Set to USE_ATLAS to attempt atlasing. If atlasing fails, the image will still
-   *                                  be loaded, and marked successful, but this will be set to false.
-   *                                  If atlasing succeeds, this will be set to true.
-   * @param[out] loadingStatus        The loading status of the texture
-   * @param[in] wrapModeU             Horizontal Wrap mode
-   * @param[in] wrapModeV             Vertical Wrap mode
-   * @param[in] textureObserver       The client object should inherit from this and provide the "UploadCompleted" virtual.
-   *                                  This is called when an image load completes (or fails).
-   * @param[in] atlasObserver         This is used if the texture is atlased, and will be called instead of
-   *                                  textureObserver.UploadCompleted
-   * @param[in] imageAtlasManager     The atlas manager to use for atlasing textures
-   * @param[in] orientationCorrection Whether to rotate image to match embedded orientation data
-   * @param[in] reloadPolicy          Forces a reload of the texture even if already cached
-   * @param[in,out] preMultiplyOnLoad True if the image color should be multiplied by it's alpha. Set to false if the
-   *                                  image has no alpha channel
-   *
-   * @return                          The texture set containing the image, or empty if still loading.
-   */
-  TextureSet LoadTexture(const VisualUrl&             url,
-                         Dali::ImageDimensions        desiredSize,
-                         Dali::FittingMode::Type      fittingMode,
-                         Dali::SamplingMode::Type     samplingMode,
-                         MaskingDataPointer&          maskInfo,
-                         bool                         synchronousLoading,
-                         TextureManager::TextureId&   textureId,
-                         Vector4&                     textureRect,
-                         Dali::ImageDimensions&       textureRectSize,
-                         bool&                        atlasingStatus,
-                         bool&                        loadingStatus,
-                         Dali::WrapMode::Type         wrapModeU,
-                         Dali::WrapMode::Type         wrapModeV,
-                         TextureUploadObserver*       textureObserver,
-                         AtlasUploadObserver*         atlasObserver,
-                         ImageAtlasManagerPtr         imageAtlasManager,
-                         bool                         orientationCorrection,
-                         TextureManager::ReloadPolicy reloadPolicy,
-                         MultiplyOnLoad&              preMultiplyOnLoad);
-
-  /**
-   * @brief Requests an image load of the given URL.
-   *
-   * The parameters are used to specify how the image is loaded.
-   * The observer has the LoadComplete method called when the load is ready.
-   *
-   * When the client has finished with the Texture, Remove() should be called.
-   *
-   * @param[in] url                   The URL of the image to load
-   * @param[in] desiredSize           The size the image is likely to appear at. This can be set to 0,0 for automatic
-   * @param[in] fittingMode           The FittingMode to use
-   * @param[in] samplingMode          The SamplingMode to use
-   * @param[in] useAtlasing           Set to USE_ATLAS to attempt atlasing. If atlasing fails, the image will still be loaded, and marked successful,
-   *                                  but "useAtlasing" will be set to false in the "UploadCompleted" callback from the TextureManagerUploadObserver.
-   * @param[in] observer              The client object should inherit from this and provide the "UploadCompleted" virtual.
-   *                                  This is called when an image load completes (or fails).
-   * @param[in] orientationCorrection Whether to rotate image to match embedded orientation data
-   * @param[in] reloadPolicy          Forces a reload of the texture even if already cached
-   * @param[in,out] preMultiplyOnLoad     True if the image color should be multiplied by it's alpha. Set to false if the image has no alpha channel
-   * @param[in] synchronousLoading    true if the frame should be loaded synchronously
-   * @return                          A TextureId to use as a handle to reference this Texture
-   */
-  TextureId RequestLoad(const VisualUrl&             url,
-                        const ImageDimensions        desiredSize,
-                        FittingMode::Type            fittingMode,
-                        Dali::SamplingMode::Type     samplingMode,
-                        const UseAtlas               useAtlasing,
-                        TextureUploadObserver*       observer,
-                        bool                         orientationCorrection,
-                        TextureManager::ReloadPolicy reloadPolicy,
-                        MultiplyOnLoad&              preMultiplyOnLoad,
-                        bool                         synchronousLoading = false);
-
-  /**
-   * @brief Requests an image load of the given URL, when the texture has
-   * have loaded, it will perform a blend with the image mask, and upload
-   * the blended texture.
-   *
-   * The parameters are used to specify how the image is loaded.
-   * The observer has the LoadComplete method called when the load is ready.
-   *
-   * When the client has finished with the Texture, Remove() should be called.
-   *
-   * @param[in] url                   The URL of the image to load
-   * @param[in] maskTextureId         The texture id of an image to mask this with
-   *                                  (can be INVALID if no masking required)
-   * @param[in] contentScale          The scale factor to apply to the image before masking
-   * @param[in] desiredSize           The size the image is likely to appear at. This can be set to 0,0 for automatic
-   * @param[in] fittingMode           The FittingMode to use
-   * @param[in] samplingMode          The SamplingMode to use
-   * @param[in] useAtlasing           Set to USE_ATLAS to attempt atlasing. If atlasing fails, the image will still
-   *                                  be loaded, and marked successful,
-   *                                  but "useAtlasing" will be set to false in the "UploadCompleted" callback from
-   *                                  the TextureManagerUploadObserver.
-   * @param[in] cropToMask            Only used with masking, this will crop the scaled image to the mask size.
-   *                                  If false, then the mask will be scaled to fit the image before being applied.
-   * @param[in] observer              The client object should inherit from this and provide the "UploadCompleted"
-   *                                  virtual.
-   *                                  This is called when an image load completes (or fails).
-   * @param[in] orientationCorrection Whether to rotate image to match embedded orientation data
-   * @param[in] reloadPolicy          Forces a reload of the texture even if already cached
-   * @param[in] preMultiplyOnLoad     True if the image color should be multiplied by it's alpha. Set to false if the
-   *                                  image has no alpha channel
-   * @param[in] synchronousLoading    true if the frame should be loaded synchronously
-   * @return                          A TextureId to use as a handle to reference this Texture
-   */
-  TextureId RequestLoad(const VisualUrl&             url,
-                        TextureId                    maskTextureId,
-                        float                        contentScale,
-                        const ImageDimensions        desiredSize,
-                        FittingMode::Type            fittingMode,
-                        Dali::SamplingMode::Type     samplingMode,
-                        const UseAtlas               useAtlasing,
-                        bool                         cropToMask,
-                        TextureUploadObserver*       observer,
-                        bool                         orientationCorrection,
-                        TextureManager::ReloadPolicy reloadPolicy,
-                        MultiplyOnLoad&              preMultiplyOnLoad,
-                        bool                         synchronousLoading = false);
-
-  /**
-   * Requests a masking image to be loaded. This mask is not uploaded to GL,
-   * instead, it is stored in CPU memory, and can be used for CPU blending.
-   */
-  TextureId RequestMaskLoad(const VisualUrl& maskUrl,
-                            bool             synchronousLoading = false);
-
-  /**
-   * @brief Remove a Texture from the TextureManager.
-   *
-   * Textures are cached and therefore only the removal of the last
-   * occurrence of a Texture will cause its removal internally.
-   *
-   * @param[in] textureId The ID of the Texture to remove.
-   * @param[in] textureObserver The texture observer.
-   */
-  void Remove(const TextureManager::TextureId textureId, TextureUploadObserver* textureObserver);
-
-  /**
-   * @brief Get the visualUrl associated with the texture id.
-   * @param[in] textureId The texture Id to get
-   * @return The visual Url associated with the texture id.
-   */
-  VisualUrl GetVisualUrl(TextureId textureId);
-
-  /**
-   * @brief Get the current state of a texture
-   * @param[in] textureId The texture id to query
-   * @return The loading state if the texture is valid, or NOT_STARTED if the textureId
-   * is not valid.
-   */
-  LoadState GetTextureState(TextureId textureId);
-
-  /**
-   * @brief Get the associated texture set if the texture id is valid
-   * @param[in] textureId The texture Id to look up
-   * @return the associated texture set, or an empty handle if textureId is not valid
-   */
-  TextureSet GetTextureSet(TextureId textureId);
-
-  /**
-   * @brief Get the encoded image buffer
-   * @param[in] textureId The textureId to look up
-   * @return the encoded image buffer, or an empty handle if textureId is not valid
-   */
-  EncodedImageBuffer GetEncodedImageBuffer(TextureId textureId);
-
-  /**
-   * @brief Get the encoded image buffer by VisualUrl
-   * @param[in] url The url to look up
-   * @return the encoded image buffer, or an empty handle if url is not buffer resource or buffer is not valid
-   */
-  EncodedImageBuffer GetEncodedImageBuffer(const std::string& url);
-
-  /**
-   * Adds an external texture to the texture manager
-   * @param[in] texture The texture to add
-   * @return string containing the URL for the texture
-   */
-  std::string AddExternalTexture(TextureSet& texture);
-
-  /**
-   * Adds an external encoded image buffer to the texture manager
-   * @param[in] encodedImageBuffer The image buffer to add
-   * @return string containing the URL for the texture
-   */
-  std::string AddExternalEncodedImageBuffer(const EncodedImageBuffer& encodedImageBuffer);
-
-  /**
-   * Removes an external texture from texture manager
-   * @param[in] url The string containing the texture to remove
-   * @return handle to the texture
-   */
-  TextureSet RemoveExternalTexture(const std::string& url);
-
-  /**
-   * Removes an external encoded image buffer from texture manager
-   * @param[in] url The string containing the encoded image buffer to remove
-   * @return handle to the encoded image buffer
-   */
-  EncodedImageBuffer RemoveExternalEncodedImageBuffer(const std::string& url);
-
-  /**
-   * @brief Notify that external textures or external encoded image buffers are used.
-   * @param[in] url The URL of the texture to use.
-   */
-  void UseExternalResource(const VisualUrl& url);
-
-  /**
-   * Add an observer to the object.
-   * @param[in] observer The observer to add.
-   */
-  void AddObserver(TextureManager::LifecycleObserver& observer);
-
-  /**
-   * Remove an observer from the object
-   * @pre The observer has already been added.
-   * @param[in] observer The observer to remove.
-   */
-  void RemoveObserver(TextureManager::LifecycleObserver& observer);
-
-  /**
-   * @brief Returns the geometry associated with texture.
-   * @param[in] textureId Id of the texture
-   * @param[out] frontElements number of front elements
-   * @param[out] backElements number of back elements
-   * @return Returns valid geometry object
-   */
-  Geometry GetRenderGeometry(TextureId textureId, uint32_t& frontElements, uint32_t& backElements);
-
-private:
-  /**
-   * @brief Requests an image load of the given URL, when the texture has
-   * have loaded, if there is a valid maskTextureId, it will perform a
-   * CPU blend with the mask, and upload the blend texture.
-   *
-   * The parameters are used to specify how the image is loaded.
-   * The observer has the LoadComplete method called when the load is ready.
-   *
-   * When the client has finished with the Texture, Remove() should be called.
-   *
-   * @param[in] url                   The URL of the image to load
-   * @param[in] maskTextureId         The texture id of an image to use as a mask. If no mask is required, then set
-   *                                  to INVALID_TEXTURE_ID
-   * @param[in] contentScale          The scaling factor to apply to the content when masking
-   * @param[in] desiredSize           The size the image is likely to appear at. This can be set to 0,0 for automatic
-   * @param[in] fittingMode           The FittingMode to use
-   * @param[in] samplingMode          The SamplingMode to use
-   * @param[in] useAtlasing           Set to USE_ATLAS to attempt atlasing. If atlasing fails, the image will still be
-   *                                  loaded, and marked successful, but "useAtlasing" will be set to false in the
-   *                                  "UploadCompleted" callback from the TextureManagerUploadObserver.
-   * @param[in] cropToMask            Whether to crop the target after masking, or scale the mask to the image before
-   *                                  masking.
-   * @param[in] storageType,          Whether the pixel data is stored in the cache or uploaded to the GPU
-   * @param[in] observer              The client object should inherit from this and provide the "UploadCompleted"
-   *                                  virtual.
-   *                                  This is called when an image load completes (or fails).
-   * @param[in] orientationCorrection Whether to rotate image to match embedded orientation data
-   * @param[in] reloadPolicy          Forces a reload of the texture even if already cached
-   * @param[in] preMultiplyOnLoad     True if the image color should be multiplied by it's alpha. Set to false if
-   *                                  there is no alpha
-   * @param[in] animatedImageLoading  The AnimatedImageLoading to load animated image
-   * @param[in] frameIndex            The frame index of a frame to be loaded frame
-   * @param[in] synchronousLoading    true if the frame should be loaded synchronously
-   * @return                          A TextureId to use as a handle to reference this Texture
-   */
-  TextureId RequestLoadInternal(
-    const VisualUrl&             url,
-    TextureId                    maskTextureId,
-    float                        contentScale,
-    const ImageDimensions        desiredSize,
-    FittingMode::Type            fittingMode,
-    Dali::SamplingMode::Type     samplingMode,
-    UseAtlas                     useAtlas,
-    bool                         cropToMask,
-    StorageType                  storageType,
-    TextureUploadObserver*       observer,
-    bool                         orientationCorrection,
-    TextureManager::ReloadPolicy reloadPolicy,
-    MultiplyOnLoad&              preMultiplyOnLoad,
-    Dali::AnimatedImageLoading   animatedImageLoading,
-    uint32_t                     frameIndex,
-    bool                         synchronousLoading);
-
-  /**
-   * @brief Get the current state of a texture
-   * @param[in] textureId The texture id to query
-   * @return The loading state if the texture is valid, or NOT_STARTED if the textureId
-   * is not valid.
-   */
-  LoadState GetTextureStateInternal(TextureId textureId);
-
-  /**
-   * @brief Load a new image synchronously.
-   * @param[in] url                   The URL of the image to load
-   * @param[in] desiredSize           The size the image is likely to appear at.
-   *                                  This can be set to 0,0 for automatic
-   * @param[in] fittingMode           The FittingMode to use
-   * @param[in] samplingMode          The SamplingMode to use
-   * @param[in] orientationCorrection Whether to use image metadata to rotate or flip the image,
-   *                                  e.g., from portrait to landscape
-   * @return PixelBuffer of loaded image.
-   */
-  Devel::PixelBuffer LoadImageSynchronously(const VisualUrl&         url,
-                                            const ImageDimensions    desiredSize,
-                                            FittingMode::Type        fittingMode,
-                                            Dali::SamplingMode::Type samplingMode,
-                                            bool                     orientationCorrection);
-
-  typedef size_t TextureHash; ///< The type used to store the hash used for Texture caching.
-
-  // Structs:
-
-  /**
-   * @brief This struct is used to manage the life-cycle of Texture loading and caching.
-   */
-  struct TextureInfo
-  {
-    TextureInfo(TextureId                   textureId,
-                TextureId                   maskTextureId,
-                const VisualUrl&            url,
-                ImageDimensions             desiredSize,
-                float                       scaleFactor,
-                FittingMode::Type           fittingMode,
-                Dali::SamplingMode::Type    samplingMode,
-                bool                        loadSynchronously,
-                bool                        cropToMask,
-                UseAtlas                    useAtlas,
-                TextureManager::TextureHash hash,
-                bool                        orientationCorrection,
-                bool                        preMultiplyOnLoad,
-                Dali::AnimatedImageLoading  animatedImageLoading,
-                uint32_t                    frameIndex)
-    : url(url),
-      desiredSize(desiredSize),
-      useSize(desiredSize),
-      atlasRect(0.0f, 0.0f, 1.0f, 1.0f), // Full atlas rectangle
-      textureId(textureId),
-      maskTextureId(maskTextureId),
-      hash(hash),
-      scaleFactor(scaleFactor),
-      referenceCount(1u),
-      loadState(LoadState::NOT_STARTED),
-      fittingMode(fittingMode),
-      samplingMode(samplingMode),
-      storageType(StorageType::UPLOAD_TO_TEXTURE),
-      animatedImageLoading(animatedImageLoading),
-      frameIndex(frameIndex),
-      loadSynchronously(loadSynchronously),
-      useAtlas(useAtlas),
-      cropToMask(cropToMask),
-      orientationCorrection(true),
-      preMultiplyOnLoad(preMultiplyOnLoad),
-      preMultiplied(false)
-    {
-    }
-
-    /**
-     * Container type used to store all observer clients of this Texture
-     */
-    typedef Dali::Vector<TextureUploadObserver*> ObserverListType;
-
-    ObserverListType            observerList;          ///< Container used to store all observer clients of this Texture
-    Toolkit::ImageAtlas         atlas;                 ///< The atlas this Texture lays within (if any)
-    Devel::PixelBuffer          pixelBuffer;           ///< The PixelBuffer holding the image data (May be empty after upload)
-    TextureSet                  textureSet;            ///< The TextureSet holding the Texture
-    VisualUrl                   url;                   ///< The URL of the image
-    ImageDimensions             desiredSize;           ///< The size requested
-    ImageDimensions             useSize;               ///< The size used
-    Vector4                     atlasRect;             ///< The atlas rect used if atlased
-    TextureId                   textureId;             ///< The TextureId associated with this Texture
-    TextureId                   maskTextureId;         ///< The mask TextureId to be applied on load
-    TextureManager::TextureHash hash;                  ///< The hash used to cache this Texture
-    float                       scaleFactor;           ///< The scale factor to apply to the Texture when masking
-    int16_t                     referenceCount;        ///< The reference count of clients using this Texture
-    LoadState                   loadState;             ///< The load state showing the load progress of the Texture
-    FittingMode::Type           fittingMode : 3;       ///< The requested FittingMode
-    Dali::SamplingMode::Type    samplingMode : 3;      ///< The requested SamplingMode
-    StorageType                 storageType;           ///< CPU storage / GPU upload;
-    Dali::AnimatedImageLoading  animatedImageLoading;  ///< AnimatedImageLoading that contains animated image information.
-    uint32_t                    frameIndex;            ///< frame index that be loaded, in case of animated image
-    bool                        loadSynchronously : 1; ///< True if synchronous loading was requested
-    UseAtlas                    useAtlas : 2;          ///< USE_ATLAS if an atlas was requested.
-                                                       ///< This is updated to false if atlas is not used
-    bool cropToMask : 1;                               ///< true if the image should be cropped to the mask size.
-    bool orientationCorrection : 1;                    ///< true if the image should be rotated to match exif orientation data
-    bool preMultiplyOnLoad : 1;                        ///< true if the image's color should be multiplied by it's alpha
-    bool preMultiplied : 1;                            ///< true if the image's color was multiplied by it's alpha
-  };
-
-  /**
-   * Structure to hold info about a texture load queued during NotifyObservers
-   */
-  struct LoadQueueElement
-  {
-    LoadQueueElement(TextureId textureId, TextureUploadObserver* observer)
-    : mTextureId(textureId),
-      mObserver(observer)
-    {
-    }
-
-    TextureId              mTextureId; ///< The texture id of the requested load.
-    TextureUploadObserver* mObserver;  ///< Observer of texture load.
-  };
-
-  /**
-   * Struct to hold information about a requested Async load.
-   * This is used to look up a TextureManager::TextureId from the returned AsyncLoad Id.
-   */
-  struct AsyncLoadingInfo
-  {
-    AsyncLoadingInfo(TextureId textureId)
-    : textureId(textureId),
-      loadId(0)
-    {
-    }
-
-    TextureId textureId; ///< The external Texture Id assigned to this load
-    uint32_t  loadId;    ///< The load Id used by the async loader to reference this load
-  };
-
-  // Private typedefs:
-
-  typedef std::deque<AsyncLoadingInfo> AsyncLoadingInfoContainerType; ///< The container type used to manage Asynchronous loads in progress
-  typedef std::vector<TextureInfo>     TextureInfoContainerType;      ///< The container type used to manage the life-cycle and caching of Textures
-
-  /**
-   * @brief Initiate a load or queue load if NotifyObservers is invoking callbacks
-   * @param[in] textureInfo The TextureInfo struct associated with the Texture
-   * @param[in] observer The observer wishing to observe the texture upload
-   */
-  void LoadOrQueueTexture(TextureInfo& textureInfo, TextureUploadObserver* observer);
-
-  /**
-   * @brief Queue a texture load to be subsequently handled by ProcessQueuedTextures.
-   * @param[in] textureInfo The TextureInfo struct associated with the Texture
-   * @param[in] observer The observer wishing to observe the texture upload
-   */
-  void QueueLoadTexture(TextureInfo& textureInfo, TextureUploadObserver* observer);
-
-  /**
-   * @brief Used internally to initiate a load.
-   * @param[in] textureInfo The TextureInfo struct associated with the Texture
-   * @param[in] observer The observer wishing to observe the texture upload
-   */
-  void LoadTexture(TextureInfo& textureInfo, TextureUploadObserver* observer);
-
-  /**
-   * @brief Initiate load of textures queued whilst NotifyObservers invoking callbacks.
-   */
-  void ProcessQueuedTextures();
-
-  /**
-   * Add the observer to the observer list
-   * @param[in] textureInfo The TextureInfo struct associated with the texture
-   * @param[in] observer The observer wishing to observe the texture upload
-   */
-  void ObserveTexture(TextureInfo& textureInfo, TextureUploadObserver* observer);
-
-  /**
-   * @brief This signal handler is called when the async local loader finishes loading.
-   * @param[in] id        This is the async image loaders Id
-   * @param[in] pixelBuffer The loaded image data
-   */
-  void AsyncLocalLoadComplete(uint32_t id, Devel::PixelBuffer pixelBuffer);
-
-  /**
-   * @brief This signal handler is called when the async local loader finishes loading.
-   * @param[in] id        This is the async image loaders Id
-   * @param[in] pixelBuffer The loaded image data
-   */
-  void AsyncRemoteLoadComplete(uint32_t id, Devel::PixelBuffer pixelBuffer);
-
-  /**
-   * Common method to handle loading completion
-   * @param[in] container The Async loading container
-   * @param[in] id        This is the async image loaders Id
-   * @param[in] pixelBuffer The loaded image data
-   */
-  void AsyncLoadComplete(AsyncLoadingInfoContainerType& container, uint32_t id, Devel::PixelBuffer pixelBuffer);
-
-  /**
-   * @brief Performs Post-Load steps including atlasing.
-   * @param[in] textureInfo The struct associated with this Texture
-   * @param[in] pixelBuffer The image pixelBuffer
-   * @return    True if successful
-   */
-  void PostLoad(TextureManager::TextureInfo& textureInfo, Devel::PixelBuffer& pixelBuffer);
-
-  /**
-   * Check if there is a texture waiting to be masked. If there
-   * is then apply this mask and upload it.
-   * @param[in] maskTextureInfo The texture info of the mask that has just loaded.
-   */
-  void CheckForWaitingTexture(TextureInfo& maskTextureInfo);
-
-  /**
-   * Apply the mask to the pixelBuffer.
-   * @param[in] textureInfo The information of texture to apply the mask to
-   * @param[in] maskTextureId The texture id of the mask.
-   */
-  void ApplyMask(TextureInfo& textureInfo, TextureId maskTextureId);
-
-  /**
-   * Upload the texture specified in pixelBuffer to the appropriate location
-   * @param[in] pixelBuffer The image data to upload
-   * @param[in] textureInfo The texture info containing the location to
-   * store the data to.
-   */
-  void UploadTexture(Devel::PixelBuffer& pixelBuffer, TextureInfo& textureInfo);
-
-  /**
-   * Creates tiled geometry of for the texture which separates fully-opaque
-   * tiles from ones which use transparency.
-   * @param pixelBuffer
-   * @param textureInfo
-   */
-  bool CreateTiledGeometry(const Devel::PixelBuffer& pixelBuffer, TextureInfo& textureInfo);
-
-  /**
-   * Notify the current observers that the texture upload is complete,
-   * then remove the observers from the list.
-   * @param[in] textureInfo The struct associated with this Texture
-   * @param[in] success If the pixel data was retrieved successfully and uploaded to GPU
-   */
-  void NotifyObservers(TextureInfo& textureInfo, bool success);
-
-  /**
-   * @brief Generates a new, unique TextureId
-   * @return A unique TextureId
-   */
-  TextureManager::TextureId GenerateUniqueTextureId();
-
-  /**
-   * @brief Used to lookup an index into the TextureInfoContainer from a TextureId
-   * @param[in] textureId The TextureId to look up
-   * @return              The cache index
-   */
-  int GetCacheIndexFromId(TextureId textureId);
-
-  /**
-   * @brief Generates a hash for caching based on the input parameters.
-   * Only applies size, fitting mode andsampling mode if the size is specified.
-   * Only applies maskTextureId if it isn't INVALID_TEXTURE_ID
-   * Always applies useAtlas.
-   * @param[in] url              The URL of the image to load
-   * @param[in] size             The image size
-   * @param[in] fittingMode      The FittingMode to use
-   * @param[in] samplingMode     The SamplingMode to use
-   * @param[in] useAtlas         True if atlased
-   * @param[in] maskTextureId    The masking texture id (or INVALID_TEXTURE_ID)
-   * @return                     A hash of the provided data for caching.
-   */
-  TextureHash GenerateHash(const std::string& url, const ImageDimensions size, const FittingMode::Type fittingMode, const Dali::SamplingMode::Type samplingMode, const UseAtlas useAtlas, TextureId maskTextureId);
-
-  /**
-   * @brief Looks up a cached texture by its hash.
-   * If found, the given parameters are used to check there is no hash-collision.
-   * @param[in] hash              The hash to look up
-   * @param[in] url               The URL of the image to load
-   * @param[in] size              The image size
-   * @param[in] fittingMode       The FittingMode to use
-   * @param[in] samplingMode      The SamplingMode to use
-   * @param[in] useAtlas          True if atlased
-   * @param[in] maskTextureId     Optional texture ID to use to mask this image
-   * @param[in] preMultiplyOnLoad if the image's color should be multiplied by it's alpha. Set to OFF if there is no alpha.
-   * @return                      A TextureId of a cached Texture if found. Or INVALID_TEXTURE_ID if not found.
-   */
-  TextureManager::TextureId FindCachedTexture(
-    const TextureManager::TextureHash hash,
-    const std::string&                url,
-    const ImageDimensions             size,
-    const FittingMode::Type           fittingMode,
-    const Dali::SamplingMode::Type    samplingMode,
-    const bool                        useAtlas,
-    TextureId                         maskTextureId,
-    MultiplyOnLoad                    preMultiplyOnLoad);
-
-private:
-  /**
-   * @brief Helper class to keep the relation between AsyncImageLoader and corresponding LoadingInfo container
-   */
-  class AsyncLoadingHelper : public ConnectionTracker
-  {
-  public:
-    /**
-     * @brief Create an AsyncLoadingHelper.
-     * @param[in] textureManager Reference to the texture manager
-     */
-    AsyncLoadingHelper(TextureManager& textureManager);
-
-    /**
-     * @brief Load a new frame of animated image
-     * @param[in] textureId             TextureId to reference the texture that will be loaded
-     * @param[in] animatedImageLoading  The AnimatedImageLoading to load animated image
-     * @param[in] frameIndex            The frame index of a frame to be loaded frame
-     */
-    void LoadAnimatedImage(TextureId                  textureId,
-                           Dali::AnimatedImageLoading animatedImageLoading,
-                           uint32_t                   frameIndex);
-
-    /**
-     * @brief Load a new texture.
-     * @param[in] textureId             TextureId to reference the texture that will be loaded
-     * @param[in] url                   The URL of the image to load
-     * @param[in] desiredSize           The size the image is likely to appear at.
-     *                                  This can be set to 0,0 for automatic
-     * @param[in] fittingMode           The FittingMode to use
-     * @param[in] samplingMode          The SamplingMode to use
-     * @param[in] orientationCorrection Whether to use image metadata to rotate or flip the image,
-     *                                  e.g., from portrait to landscape
-     * @param[in] preMultiplyOnLoad     if the image's color should be multiplied by it's alpha. Set to OFF if there is no alpha or if the image need to be applied alpha mask.
-     */
-    void Load(TextureId                                textureId,
-              const VisualUrl&                         url,
-              ImageDimensions                          desiredSize,
-              FittingMode::Type                        fittingMode,
-              SamplingMode::Type                       samplingMode,
-              bool                                     orientationCorrection,
-              DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad);
-
-    /**
-     * @brief Apply mask
-     * @param [in] id of the texture
-     * @param [in] pixelBuffer of the to be masked image
-     * @param [in] maskPixelBuffer of the mask image
-     * @param [in] contentScale The factor to scale the content
-     * @param [in] cropToMask Whether to crop the content to the mask size
-     * @param [in] preMultiplyOnLoad if the image's color should be multiplied by it's alpha. Set to OFF if there is no alpha.
-     */
-    void ApplyMask(TextureId                                textureId,
-                   Devel::PixelBuffer                       pixelBuffer,
-                   Devel::PixelBuffer                       maskPixelBuffer,
-                   float                                    contentScale,
-                   bool                                     cropToMask,
-                   DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad);
-
-  public:
-    AsyncLoadingHelper(const AsyncLoadingHelper&) = delete;
-    AsyncLoadingHelper& operator=(const AsyncLoadingHelper&) = delete;
-
-    AsyncLoadingHelper(AsyncLoadingHelper&& rhs);
-    AsyncLoadingHelper& operator=(AsyncLoadingHelper&& rhs) = delete;
-
-  private:
-    /**
-     * @brief Main constructor that used by all other constructors
-     */
-    AsyncLoadingHelper(Toolkit::AsyncImageLoader       loader,
-                       TextureManager&                 textureManager,
-                       AsyncLoadingInfoContainerType&& loadingInfoContainer);
-
-    /**
-     * @brief Callback to be called when texture loading is complete, it passes the pixel buffer on to texture manager.
-     * @param[in] id          Loader id
-     * @param[in] pixelBuffer Image data
-     */
-    void AsyncLoadComplete(uint32_t id, Devel::PixelBuffer pixelBuffer);
-
-  private:
-    Toolkit::AsyncImageLoader     mLoader;
-    TextureManager&               mTextureManager;
-    AsyncLoadingInfoContainerType mLoadingInfoContainer;
-  };
-
-  struct ExternalTextureInfo
-  {
-    TextureId  textureId;
-    TextureSet textureSet;
-    int16_t    referenceCount{1};
-  };
-
-  struct EncodedBufferTextureInfo
-  {
-    EncodedBufferTextureInfo(TextureId                 textureId,
-                             const EncodedImageBuffer& encodedImageBuffer)
-    : textureId(textureId),
-      encodedImageBuffer(encodedImageBuffer),
-      referenceCount(1u)
-    {
-    }
-    TextureId          textureId;
-    EncodedImageBuffer encodedImageBuffer;
-    int16_t            referenceCount;
-  };
-
-private:
-  /**
-   * Deleted copy constructor.
-   */
-  TextureManager(const TextureManager&) = delete;
-
-  /**
-   * Deleted assignment operator.
-   */
-  TextureManager& operator=(const TextureManager& rhs) = delete;
-
-  /**
-   * This is called by the TextureManagerUploadObserver when an observer is destroyed.
-   * We use the callback to know when to remove an observer from our notify list.
-   * @param[in] observer The observer that generated the callback
-   */
-  void ObserverDestroyed(TextureUploadObserver* observer);
-
-private:                                                              // Member Variables:
-  TextureInfoContainerType                    mTextureInfoContainer;  ///< Used to manage the life-cycle and caching of Textures
-  RoundRobinContainerView<AsyncLoadingHelper> mAsyncLocalLoaders;     ///< The Asynchronous image loaders used to provide all local async loads
-  RoundRobinContainerView<AsyncLoadingHelper> mAsyncRemoteLoaders;    ///< The Asynchronous image loaders used to provide all remote async loads
-  std::vector<ExternalTextureInfo>            mExternalTextures;      ///< Externally provided textures
-  std::vector<EncodedBufferTextureInfo>       mEncodedBufferTextures; ///< Externally encoded buffer textures
-  Dali::Vector<LifecycleObserver*>            mLifecycleObservers;    ///< Lifecycle observers of texture manager
-  Dali::Vector<LoadQueueElement>              mLoadQueue;             ///< Queue of textures to load after NotifyObservers
-  TextureId                                   mCurrentTextureId;      ///< The current value used for the unique Texture Id generation
-  bool                                        mQueueLoadFlag;         ///< Flag that causes Load Textures to be queued.
-};
-
-} // namespace Internal
-
-} // namespace Toolkit
-
-} // namespace Dali
-
-#endif // DALI_TOOLKIT_TEXTURE_MANAGER_IMPL_H
diff --git a/dali-toolkit/internal/visuals/texture-manager/texture-async-loading-helper.cpp b/dali-toolkit/internal/visuals/texture-manager/texture-async-loading-helper.cpp
new file mode 100644 (file)
index 0000000..1eee5bc
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include "texture-async-loading-helper.h"
+
+// EXTERNAL HEADERS
+#include <dali/integration-api/debug.h>
+
+// INTERNAL HEADERS
+#include <dali-toolkit/internal/image-loader/async-image-loader-impl.h>
+#include <dali-toolkit/public-api/image-loader/sync-image-loader.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+#ifdef DEBUG_ENABLED
+extern Debug::Filter* gTextureManagerLogFilter; ///< Define at texture-manager-impl.cpp
+#endif
+
+TextureAsyncLoadingHelper::TextureAsyncLoadingHelper(TextureManager& textureManager)
+: TextureAsyncLoadingHelper(Toolkit::AsyncImageLoader::New(), textureManager, AsyncLoadingInfoContainerType())
+{
+}
+
+void TextureAsyncLoadingHelper::LoadAnimatedImage(const TextureManager::TextureId& textureId,
+                                                  Dali::AnimatedImageLoading       animatedImageLoading,
+                                                  const std::uint32_t&             frameIndex)
+{
+  mLoadingInfoContainer.push_back(AsyncLoadingInfo(textureId));
+  auto id                             = GetImplementation(mLoader).LoadAnimatedImage(animatedImageLoading, frameIndex);
+  mLoadingInfoContainer.back().loadId = id;
+}
+
+void TextureAsyncLoadingHelper::Load(const TextureManager::TextureId&                textureId,
+                                     const VisualUrl&                                url,
+                                     const Dali::ImageDimensions&                    desiredSize,
+                                     const Dali::FittingMode::Type&                  fittingMode,
+                                     const Dali::SamplingMode::Type&                 samplingMode,
+                                     const bool&                                     orientationCorrection,
+                                     const DevelAsyncImageLoader::PreMultiplyOnLoad& preMultiplyOnLoad)
+{
+  mLoadingInfoContainer.push_back(AsyncLoadingInfo(textureId));
+  if(DALI_UNLIKELY(url.IsBufferResource()))
+  {
+    auto id                             = GetImplementation(mLoader).LoadEncodedImageBuffer(mTextureManager.GetEncodedImageBuffer(url.GetUrl()), desiredSize, fittingMode, samplingMode, orientationCorrection, preMultiplyOnLoad);
+    mLoadingInfoContainer.back().loadId = id;
+  }
+  else
+  {
+    auto id                             = GetImplementation(mLoader).Load(url, desiredSize, fittingMode, samplingMode, orientationCorrection, preMultiplyOnLoad);
+    mLoadingInfoContainer.back().loadId = id;
+  }
+}
+
+void TextureAsyncLoadingHelper::ApplyMask(const TextureManager::TextureId&                textureId,
+                                          Devel::PixelBuffer                              pixelBuffer,
+                                          Devel::PixelBuffer                              maskPixelBuffer,
+                                          const float&                                    contentScale,
+                                          const bool&                                     cropToMask,
+                                          const DevelAsyncImageLoader::PreMultiplyOnLoad& preMultiplyOnLoad)
+{
+  mLoadingInfoContainer.push_back(AsyncLoadingInfo(textureId));
+  auto id                             = GetImplementation(mLoader).ApplyMask(pixelBuffer, maskPixelBuffer, contentScale, cropToMask, preMultiplyOnLoad);
+  mLoadingInfoContainer.back().loadId = id;
+}
+
+TextureAsyncLoadingHelper::TextureAsyncLoadingHelper(TextureAsyncLoadingHelper&& rhs)
+: TextureAsyncLoadingHelper(rhs.mLoader, rhs.mTextureManager, std::move(rhs.mLoadingInfoContainer))
+{
+}
+
+TextureAsyncLoadingHelper::TextureAsyncLoadingHelper(
+  Toolkit::AsyncImageLoader       loader,
+  TextureManager&                 textureManager,
+  AsyncLoadingInfoContainerType&& loadingInfoContainer)
+: mLoader(loader),
+  mTextureManager(textureManager),
+  mLoadingInfoContainer(std::move(loadingInfoContainer))
+{
+  DevelAsyncImageLoader::PixelBufferLoadedSignal(mLoader).Connect(
+    this, &TextureAsyncLoadingHelper::AsyncLoadComplete);
+}
+
+void TextureAsyncLoadingHelper::AsyncLoadComplete(uint32_t           id,
+                                                  Devel::PixelBuffer pixelBuffer)
+{
+  DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureAsyncLoadingHelper::AsyncLoadComplete( loadId :%d )\n", id);
+  if(mLoadingInfoContainer.size() >= 1u)
+  {
+    AsyncLoadingInfo loadingInfo = mLoadingInfoContainer.front();
+
+    // We can assume that First Loading task comes First.
+    if(loadingInfo.loadId == id)
+    {
+      // Call TextureManager::AsyncLoadComplete
+      mTextureManager.AsyncLoadComplete(loadingInfo.textureId, pixelBuffer);
+    }
+
+    mLoadingInfoContainer.pop_front();
+  }
+}
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/visuals/texture-manager/texture-async-loading-helper.h b/dali-toolkit/internal/visuals/texture-manager/texture-async-loading-helper.h
new file mode 100644 (file)
index 0000000..089ab1c
--- /dev/null
@@ -0,0 +1,146 @@
+#ifndef DALI_TOOLKIT_TEXTURE_ASYNC_LOADING_HELPER_H
+#define DALI_TOOLKIT_TEXTURE_ASYNC_LOADING_HELPER_H
+
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/signals/connection-tracker.h>
+#include <deque>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/visuals/texture-manager/texture-manager-impl.h>
+#include <dali-toolkit/internal/image-loader/async-image-loader-impl.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+
+/**
+ * @brief Helper class to keep the relation between AsyncImageLoader and corresponding LoadingInfo container
+ */
+class TextureAsyncLoadingHelper : public ConnectionTracker
+{
+  /**
+   * Struct to hold information about a requested Async load.
+   * This is used to look up a TextureManager::TextureId from the returned AsyncLoad Id.
+   */
+  struct AsyncLoadingInfo
+  {
+    AsyncLoadingInfo(TextureManager::TextureId textureId)
+    : textureId(textureId),
+      loadId(0)
+    {
+    }
+
+    TextureManager::TextureId textureId; ///< The external Texture Id assigned to this load
+    std::uint32_t             loadId;    ///< The load Id used by the async loader to reference this load
+  };
+
+public:
+  /**
+   * @brief Create an TextureAsyncLoadingHelper.
+   * @param[in] textureManager Reference to the texture manager
+   */
+  TextureAsyncLoadingHelper(TextureManager& textureManager);
+
+  /**
+   * @brief Load a new frame of animated image
+   * @param[in] textureId             TextureId to reference the texture that will be loaded
+   * @param[in] animatedImageLoading  The AnimatedImageLoading to load animated image
+   * @param[in] frameIndex            The frame index of a frame to be loaded frame
+   */
+  void LoadAnimatedImage(const TextureManager::TextureId& textureId,
+                         Dali::AnimatedImageLoading       animatedImageLoading,
+                         const std::uint32_t&             frameIndex);
+
+  /**
+   * @brief Load a new texture.
+   * @param[in] textureId             TextureId to reference the texture that will be loaded
+   * @param[in] url                   The URL of the image to load
+   * @param[in] desiredSize           The size the image is likely to appear at.
+   *                                  This can be set to 0,0 for automatic
+   * @param[in] fittingMode           The FittingMode to use
+   * @param[in] samplingMode          The SamplingMode to use
+   * @param[in] orientationCorrection Whether to use image metadata to rotate or flip the image,
+   *                                  e.g., from portrait to landscape
+   * @param[in] preMultiplyOnLoad     if the image's color should be multiplied by it's alpha. Set to OFF if there is no alpha or if the image need to be applied alpha mask.
+   */
+  void Load(const TextureManager::TextureId&                textureId,
+            const VisualUrl&                                url,
+            const Dali::ImageDimensions&                    desiredSize,
+            const Dali::FittingMode::Type&                  fittingMode,
+            const Dali::SamplingMode::Type&                 samplingMode,
+            const bool&                                     orientationCorrection,
+            const DevelAsyncImageLoader::PreMultiplyOnLoad& preMultiplyOnLoad);
+
+  /**
+   * @brief Apply mask
+   * @param [in] textureId of the texture
+   * @param [in] pixelBuffer of the to be masked image
+   * @param [in] maskPixelBuffer of the mask image
+   * @param [in] contentScale The factor to scale the content
+   * @param [in] cropToMask Whether to crop the content to the mask size
+   * @param [in] preMultiplyOnLoad if the image's color should be multiplied by it's alpha. Set to OFF if there is no alpha.
+   */
+  void ApplyMask(const TextureManager::TextureId&                textureId,
+                 Devel::PixelBuffer                              pixelBuffer,
+                 Devel::PixelBuffer                              maskPixelBuffer,
+                 const float&                                    contentScale,
+                 const bool&                                     cropToMask,
+                 const DevelAsyncImageLoader::PreMultiplyOnLoad& preMultiplyOnLoad);
+
+public:
+  TextureAsyncLoadingHelper(const TextureAsyncLoadingHelper&) = delete;
+  TextureAsyncLoadingHelper& operator=(const TextureAsyncLoadingHelper&) = delete;
+
+  TextureAsyncLoadingHelper(TextureAsyncLoadingHelper&& rhs);
+  TextureAsyncLoadingHelper& operator=(TextureAsyncLoadingHelper&& rhs) = delete;
+
+private: // Private typedefs:
+  typedef std::deque<AsyncLoadingInfo> AsyncLoadingInfoContainerType; ///< The container type used to manage Asynchronous loads in progress
+
+private:
+  /**
+   * @brief Main constructor that used by all other constructors
+   */
+  TextureAsyncLoadingHelper(Toolkit::AsyncImageLoader       loader,
+                            TextureManager&                 textureManager,
+                            AsyncLoadingInfoContainerType&& loadingInfoContainer);
+
+  /**
+   * @brief Callback to be called when texture loading is complete, it passes the pixel buffer on to texture manager.
+   * @param[in] id          Loader id
+   * @param[in] pixelBuffer Image data
+   */
+  void AsyncLoadComplete(std::uint32_t id, Devel::PixelBuffer pixelBuffer);
+
+private: // Member Variables:
+  Toolkit::AsyncImageLoader     mLoader;
+  TextureManager&               mTextureManager;
+  AsyncLoadingInfoContainerType mLoadingInfoContainer;
+};
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXTURE_ASYNC_LOADING_HELPER_H
diff --git a/dali-toolkit/internal/visuals/texture-manager/texture-cache-manager.cpp b/dali-toolkit/internal/visuals/texture-manager/texture-cache-manager.cpp
new file mode 100644 (file)
index 0000000..73b26a5
--- /dev/null
@@ -0,0 +1,503 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include "texture-cache-manager.h"
+
+// EXTERNAL HEADERS
+#include <dali/devel-api/common/hash.h>
+#include <dali/integration-api/debug.h>
+
+// INTERNAL HEADERS
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+#ifdef DEBUG_ENABLED
+extern Debug::Filter* gTextureManagerLogFilter; ///< Define at texture-manager-impl.cpp
+
+// clang-format off
+#define GET_LOAD_STATE_STRING(loadState) \
+  loadState == TextureManagerType::LoadState::NOT_STARTED      ? "NOT_STARTED"      : \
+  loadState == TextureManagerType::LoadState::LOADING          ? "LOADING"          : \
+  loadState == TextureManagerType::LoadState::LOAD_FINISHED    ? "LOAD_FINISHED"    : \
+  loadState == TextureManagerType::LoadState::WAITING_FOR_MASK ? "WAITING_FOR_MASK" : \
+  loadState == TextureManagerType::LoadState::MASK_APPLYING    ? "MASK_APPLYING"    : \
+  loadState == TextureManagerType::LoadState::MASK_APPLIED     ? "MASK_APPLIED"     : \
+  loadState == TextureManagerType::LoadState::UPLOADED         ? "UPLOADED"         : \
+  loadState == TextureManagerType::LoadState::CANCELLED        ? "CANCELLED"        : \
+  loadState == TextureManagerType::LoadState::LOAD_FAILED      ? "LOAD_FAILED"      : \
+                                                                 "Unknown"
+
+// clang-format on
+#endif
+namespace
+{
+} // Anonymous namespace
+
+TextureCacheManager::TextureCacheManager()
+: mCurrentTextureId(0)
+{
+}
+
+TextureCacheManager::~TextureCacheManager()
+{
+}
+
+VisualUrl TextureCacheManager::GetVisualUrl(const TextureCacheManager::TextureId& textureId)
+{
+  VisualUrl         visualUrl("");
+  TextureCacheIndex cacheIndex = GetCacheIndexFromId(textureId);
+
+  if(cacheIndex != INVALID_CACHE_INDEX)
+  {
+    DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureCacheManager::GetVisualUrl. Using cached texture id=%d, textureId=%d\n", cacheIndex, textureId);
+
+    TextureInfo& cachedTextureInfo(mTextureInfoContainer[cacheIndex]);
+    visualUrl = cachedTextureInfo.url;
+  }
+  return visualUrl;
+}
+
+TextureCacheManager::LoadState TextureCacheManager::GetTextureState(const TextureCacheManager::TextureId& textureId)
+{
+  LoadState loadState = TextureCacheManager::LoadState::NOT_STARTED;
+
+  TextureCacheIndex cacheIndex = GetCacheIndexFromId(textureId);
+  if(cacheIndex != INVALID_CACHE_INDEX)
+  {
+    TextureInfo& cachedTextureInfo(mTextureInfoContainer[cacheIndex]);
+    loadState = cachedTextureInfo.loadState;
+  }
+  else
+  {
+    for(auto&& elem : mExternalTextures)
+    {
+      if(elem.textureId == textureId)
+      {
+        loadState = LoadState::UPLOADED;
+        break;
+      }
+    }
+  }
+  return loadState;
+}
+
+TextureCacheManager::LoadState TextureCacheManager::GetTextureStateInternal(const TextureCacheManager::TextureId& textureId)
+{
+  LoadState loadState = TextureCacheManager::LoadState::NOT_STARTED;
+
+  TextureCacheIndex cacheIndex = GetCacheIndexFromId(textureId);
+  if(cacheIndex != INVALID_CACHE_INDEX)
+  {
+    TextureInfo& cachedTextureInfo(mTextureInfoContainer[cacheIndex]);
+    loadState = cachedTextureInfo.loadState;
+  }
+
+  return loadState;
+}
+
+TextureSet TextureCacheManager::GetTextureSet(const TextureCacheManager::TextureId& textureId)
+{
+  TextureSet textureSet; // empty handle
+
+  TextureCacheIndex cacheIndex = GetCacheIndexFromId(textureId);
+  if(cacheIndex != INVALID_CACHE_INDEX)
+  {
+    TextureInfo& cachedTextureInfo(mTextureInfoContainer[cacheIndex]);
+    textureSet = cachedTextureInfo.textureSet;
+  }
+  else
+  {
+    for(auto&& elem : mExternalTextures)
+    {
+      if(elem.textureId == textureId)
+      {
+        textureSet = elem.textureSet;
+        break;
+      }
+    }
+  }
+  return textureSet;
+}
+
+TextureSet TextureCacheManager::GetExternalTextureSet(const TextureCacheManager::TextureId& textureId)
+{
+  TextureSet textureSet; // empty handle
+  for(auto&& elem : mExternalTextures)
+  {
+    if(elem.textureId == textureId)
+    {
+      textureSet = elem.textureSet;
+      break;
+    }
+  }
+  return textureSet;
+}
+
+EncodedImageBuffer TextureCacheManager::GetEncodedImageBuffer(const TextureCacheManager::TextureId& textureId)
+{
+  EncodedImageBuffer encodedImageBuffer; // empty handle
+  for(auto&& elem : mEncodedBufferTextures)
+  {
+    if(elem.textureId == textureId)
+    {
+      encodedImageBuffer = elem.encodedImageBuffer;
+      break;
+    }
+  }
+  return encodedImageBuffer;
+}
+
+EncodedImageBuffer TextureCacheManager::GetEncodedImageBuffer(const std::string& url)
+{
+  EncodedImageBuffer encodedImageBuffer; // empty handle
+  if(url.size() > 0 && VisualUrl::BUFFER == VisualUrl::GetProtocolType(url))
+  {
+    std::string location = VisualUrl::GetLocation(url);
+    if(location.size() > 0u)
+    {
+      TextureId targetId = std::stoi(location);
+      return GetEncodedImageBuffer(targetId);
+    }
+  }
+  return encodedImageBuffer;
+}
+
+std::string TextureCacheManager::AddExternalTexture(const TextureSet& textureSet)
+{
+  TextureCacheManager::ExternalTextureInfo info(GenerateUniqueTextureId(), textureSet);
+  mExternalTextures.emplace_back(info);
+  return VisualUrl::CreateTextureUrl(std::to_string(info.textureId));
+}
+
+std::string TextureCacheManager::AddExternalEncodedImageBuffer(const EncodedImageBuffer& encodedImageBuffer)
+{
+  // Duplication check
+  for(auto&& elem : mEncodedBufferTextures)
+  {
+    if(elem.encodedImageBuffer == encodedImageBuffer)
+    {
+      // If same buffer added, increase reference count and return.
+      elem.referenceCount++;
+      return VisualUrl::CreateBufferUrl(std::to_string(elem.textureId));
+    }
+  }
+  TextureCacheManager::EncodedBufferTextureInfo info(GenerateUniqueTextureId(), encodedImageBuffer);
+  mEncodedBufferTextures.emplace_back(info);
+  return VisualUrl::CreateBufferUrl(std::to_string(info.textureId));
+}
+
+TextureSet TextureCacheManager::RemoveExternalTexture(const std::string& url)
+{
+  if(url.size() > 0u)
+  {
+    if(VisualUrl::TEXTURE == VisualUrl::GetProtocolType(url))
+    {
+      // get the location from the Url
+      std::string location = VisualUrl::GetLocation(url);
+      if(location.size() > 0u)
+      {
+        TextureId  id  = std::stoi(location);
+        const auto end = mExternalTextures.end();
+        for(auto iter = mExternalTextures.begin(); iter != end; ++iter)
+        {
+          if(iter->textureId == id)
+          {
+            auto textureSet = iter->textureSet;
+            if(--(iter->referenceCount) <= 0)
+            {
+              mExternalTextures.erase(iter);
+            }
+            return textureSet;
+          }
+        }
+      }
+    }
+  }
+  return TextureSet();
+}
+
+EncodedImageBuffer TextureCacheManager::RemoveExternalEncodedImageBuffer(const std::string& url)
+{
+  if(url.size() > 0u)
+  {
+    if(VisualUrl::BUFFER == VisualUrl::GetProtocolType(url))
+    {
+      // get the location from the Url
+      std::string location = VisualUrl::GetLocation(url);
+      if(location.size() > 0u)
+      {
+        TextureId  id  = std::stoi(location);
+        const auto end = mEncodedBufferTextures.end();
+        for(auto iter = mEncodedBufferTextures.begin(); iter != end; ++iter)
+        {
+          if(iter->textureId == id)
+          {
+            auto encodedImageBuffer = iter->encodedImageBuffer;
+            if(--(iter->referenceCount) <= 0)
+            {
+              mEncodedBufferTextures.erase(iter);
+            }
+            return encodedImageBuffer;
+          }
+        }
+      }
+    }
+  }
+  return EncodedImageBuffer();
+}
+
+void TextureCacheManager::UseExternalResource(const VisualUrl& url)
+{
+  if(VisualUrl::TEXTURE == url.GetProtocolType())
+  {
+    std::string location = url.GetLocation();
+    if(location.size() > 0u)
+    {
+      TextureId id = std::stoi(location);
+      for(auto&& elem : mExternalTextures)
+      {
+        if(elem.textureId == id)
+        {
+          elem.referenceCount++;
+          return;
+        }
+      }
+    }
+  }
+  else if(VisualUrl::BUFFER == url.GetProtocolType())
+  {
+    std::string location = url.GetLocation();
+    if(location.size() > 0u)
+    {
+      TextureId id = std::stoi(location);
+      for(auto&& elem : mEncodedBufferTextures)
+      {
+        if(elem.textureId == id)
+        {
+          elem.referenceCount++;
+          return;
+        }
+      }
+    }
+  }
+}
+
+TextureCacheManager::TextureId TextureCacheManager::GenerateUniqueTextureId()
+{
+  return mCurrentTextureId++;
+}
+
+TextureCacheManager::TextureCacheIndex TextureCacheManager::GetCacheIndexFromId(const TextureCacheManager::TextureId& textureId)
+{
+  const TextureCacheIndex size = static_cast<TextureCacheIndex>(mTextureInfoContainer.size());
+
+  for(TextureCacheIndex i = 0; i < size; ++i)
+  {
+    if(mTextureInfoContainer[i].textureId == textureId)
+    {
+      return i;
+    }
+  }
+
+  return INVALID_CACHE_INDEX;
+}
+
+TextureCacheManager::TextureHash TextureCacheManager::GenerateHash(
+  const std::string&                    url,
+  const Dali::ImageDimensions&          size,
+  const Dali::FittingMode::Type&        fittingMode,
+  const Dali::SamplingMode::Type&       samplingMode,
+  const TextureCacheManager::UseAtlas&  useAtlas,
+  const TextureCacheManager::TextureId& maskTextureId)
+{
+  std::string    hashTarget(url);
+  const size_t   urlLength = hashTarget.length();
+  const uint16_t width     = size.GetWidth();
+  const uint16_t height    = size.GetWidth();
+
+  // If either the width or height has been specified, include the resizing options in the hash
+  if(width != 0 || height != 0)
+  {
+    // We are appending 5 bytes to the URL to form the hash input.
+    hashTarget.resize(urlLength + 5u);
+    char* hashTargetPtr = &(hashTarget[urlLength]);
+
+    // Pack the width and height (4 bytes total).
+    *hashTargetPtr++ = size.GetWidth() & 0xff;
+    *hashTargetPtr++ = (size.GetWidth() >> 8u) & 0xff;
+    *hashTargetPtr++ = size.GetHeight() & 0xff;
+    *hashTargetPtr++ = (size.GetHeight() >> 8u) & 0xff;
+
+    // Bit-pack the FittingMode, SamplingMode and atlasing.
+    // FittingMode=2bits, SamplingMode=3bits, useAtlas=1bit
+    *hashTargetPtr = (fittingMode << 4u) | (samplingMode << 1) | (useAtlas == UseAtlas::USE_ATLAS ? 1 : 0);
+  }
+  else
+  {
+    // We are not including sizing information, but we still need an extra byte for atlasing.
+    hashTarget.resize(urlLength + 1u);
+
+    // Add the atlasing to the hash input.
+    switch(useAtlas)
+    {
+      case UseAtlas::NO_ATLAS:
+      {
+        hashTarget[urlLength] = 'f';
+        break;
+      }
+      case UseAtlas::USE_ATLAS:
+      {
+        hashTarget[urlLength] = 't';
+        break;
+      }
+    }
+  }
+
+  if(maskTextureId != INVALID_TEXTURE_ID)
+  {
+    auto textureIdIndex = hashTarget.length();
+    hashTarget.resize(hashTarget.length() + sizeof(TextureId));
+    unsigned char* hashTargetPtr = reinterpret_cast<unsigned char*>(&(hashTarget[textureIdIndex]));
+
+    // Append the texture id to the end of the URL byte by byte:
+    // (to avoid SIGBUS / alignment issues)
+    TextureId saltedMaskTextureId = maskTextureId;
+    for(size_t byteIter = 0; byteIter < sizeof(TextureId); ++byteIter)
+    {
+      *hashTargetPtr++ = saltedMaskTextureId & 0xff;
+      saltedMaskTextureId >>= 8u;
+    }
+  }
+
+  return Dali::CalculateHash(hashTarget);
+}
+
+TextureCacheManager::TextureCacheIndex TextureCacheManager::FindCachedTexture(
+  const TextureCacheManager::TextureHash&    hash,
+  const std::string&                         url,
+  const Dali::ImageDimensions&               size,
+  const Dali::FittingMode::Type&             fittingMode,
+  const Dali::SamplingMode::Type&            samplingMode,
+  const TextureCacheManager::UseAtlas&       useAtlas,
+  const TextureCacheManager::TextureId&      maskTextureId,
+  const TextureCacheManager::MultiplyOnLoad& preMultiplyOnLoad)
+{
+  // Default to an invalid ID, in case we do not find a match.
+  TextureCacheIndex cacheIndex = INVALID_CACHE_INDEX;
+
+  // Iterate through our hashes to find a match.
+  const TextureCacheIndex count = static_cast<TextureCacheIndex>(mTextureInfoContainer.size());
+  for(TextureCacheIndex i = 0u; i < count; ++i)
+  {
+    if(mTextureInfoContainer[i].hash == hash)
+    {
+      // We have a match, now we check all the original parameters in case of a hash collision.
+      TextureInfo& textureInfo(mTextureInfoContainer[i]);
+
+      if((url == textureInfo.url.GetUrl()) &&
+         (useAtlas == textureInfo.useAtlas) &&
+         (maskTextureId == textureInfo.maskTextureId) &&
+         (size == textureInfo.desiredSize) &&
+         ((size.GetWidth() == 0 && size.GetHeight() == 0) ||
+          (fittingMode == textureInfo.fittingMode &&
+           samplingMode == textureInfo.samplingMode)))
+      {
+        // 1. If preMultiplyOnLoad is MULTIPLY_ON_LOAD, then textureInfo.preMultiplyOnLoad should be true. The premultiplication result can be different.
+        // 2. If preMultiplyOnLoad is LOAD_WITHOUT_MULTIPLY, then textureInfo.preMultiplied should be false.
+        if((preMultiplyOnLoad == MultiplyOnLoad::MULTIPLY_ON_LOAD && textureInfo.preMultiplyOnLoad) || (preMultiplyOnLoad == MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY && !textureInfo.preMultiplied))
+        {
+          // The found Texture is a match.
+          cacheIndex = i;
+          break;
+        }
+      }
+    }
+  }
+
+  return cacheIndex;
+}
+
+TextureCacheManager::TextureCacheIndex TextureCacheManager::AppendCache(const TextureCacheManager::TextureInfo& textureInfo)
+{
+  TextureCacheIndex cacheIndex = static_cast<TextureCacheIndex>(mTextureInfoContainer.size());
+  mTextureInfoContainer.emplace_back(textureInfo);
+  return cacheIndex;
+}
+
+void TextureCacheManager::RemoveCache(const TextureCacheManager::TextureId& textureId)
+{
+  TextureCacheIndex textureInfoIndex = GetCacheIndexFromId(textureId);
+
+  if(textureInfoIndex != INVALID_CACHE_INDEX)
+  {
+    TextureInfo& textureInfo(mTextureInfoContainer[textureInfoIndex]);
+
+    DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureCacheManager::Remove(textureId:%d) url:%s\n  cacheIdx:%d loadState:%s reference count = %d\n", textureId, textureInfo.url.GetUrl().c_str(), textureInfoIndex, GET_LOAD_STATE_STRING(textureInfo.loadState), textureInfo.referenceCount);
+
+    // Decrement the reference count and check if this is the last user of this Texture.
+    if(--textureInfo.referenceCount <= 0)
+    {
+      // This is the last remove for this Texture.
+      textureInfo.referenceCount = 0;
+      bool removeTextureInfo     = false;
+
+      // If loaded, we can remove the TextureInfo and the Atlas (if atlased).
+      if(textureInfo.loadState == LoadState::UPLOADED)
+      {
+        if(textureInfo.atlas)
+        {
+          textureInfo.atlas.Remove(textureInfo.atlasRect);
+        }
+        removeTextureInfo = true;
+      }
+      else if(textureInfo.loadState == LoadState::LOADING)
+      {
+        // We mark the textureInfo for removal.
+        // Once the load has completed, this method will be called again.
+        textureInfo.loadState = LoadState::CANCELLED;
+      }
+      else
+      {
+        // In other states, we are not waiting for a load so we are safe to remove the TextureInfo data.
+        removeTextureInfo = true;
+      }
+
+      // If the state allows us to remove the TextureInfo data, we do so.
+      if(removeTextureInfo)
+      {
+        // If url location is BUFFER, decrease reference count of EncodedImageBuffer.
+        if(textureInfo.url.IsBufferResource())
+        {
+          RemoveExternalEncodedImageBuffer(textureInfo.url.GetUrl());
+        }
+        // Permanently remove the textureInfo struct.
+        mTextureInfoContainer.erase(mTextureInfoContainer.begin() + textureInfoIndex);
+      }
+    }
+  }
+}
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/visuals/texture-manager/texture-cache-manager.h b/dali-toolkit/internal/visuals/texture-manager/texture-cache-manager.h
new file mode 100644 (file)
index 0000000..4bf99cb
--- /dev/null
@@ -0,0 +1,320 @@
+#ifndef DALI_TOOLKIT_TEXTURE_CACHE_MANAGER_H
+#define DALI_TOOLKIT_TEXTURE_CACHE_MANAGER_H
+
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/adaptor-framework/encoded-image-buffer.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/visuals/texture-manager/texture-manager-type.h>
+#include <dali-toolkit/internal/visuals/texture-manager/texture-upload-observer.h>
+#include <dali-toolkit/internal/visuals/visual-url.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+/**
+ * @brief The contain and managing cached textures.
+ * Each Texture hold there TextureId. These TextureId can be used outside of TextureManager.
+ * Internally, each cached texture can be accessed by TextureCacheIndex.
+ * You can Convert TextureId into TextureCacheIndex by this class.
+ *
+ * Also, You can store external TextureSet or EncodedImageBuffer here.
+ */
+class TextureCacheManager
+{
+public:
+  // Copy enum and types and const values that TextureCacheManager will use.
+  using TextureId         = TextureManagerType::TextureId;
+  using TextureCacheIndex = TextureManagerType::TextureCacheIndex;
+  using TextureHash       = TextureManagerType::TextureHash;
+
+  static constexpr TextureId         INVALID_TEXTURE_ID  = TextureManagerType::INVALID_TEXTURE_ID;
+  static constexpr TextureCacheIndex INVALID_CACHE_INDEX = TextureManagerType::INVALID_CACHE_INDEX;
+
+  using UseAtlas       = TextureManagerType::UseAtlas;
+  using StorageType    = TextureManagerType::StorageType;
+  using LoadType       = TextureManagerType::LoadType;
+  using LoadState      = TextureManagerType::LoadState;
+  using ReloadPolicy   = TextureManagerType::ReloadPolicy;
+  using MultiplyOnLoad = TextureManagerType::MultiplyOnLoad;
+  using TextureInfo    = TextureManagerType::TextureInfo;
+
+public:
+  /**
+   * Constructor.
+   */
+  TextureCacheManager();
+
+  /**
+   * Destructor.
+   */
+  ~TextureCacheManager();
+
+public:
+  // TextureCacheManager Main API:
+
+  /**
+   * @brief Get the visualUrl associated with the texture id.
+   * @param[in] textureId The texture Id to get
+   * @return The visual Url associated with the texture id.
+   */
+  VisualUrl GetVisualUrl(const TextureCacheManager::TextureId& textureId);
+
+  /**
+   * @brief Get the current state of a texture
+   * @param[in] textureId The texture id to query
+   * @return The loading state if the texture is valid, or NOT_STARTED if the textureId
+   * is not valid.
+   */
+  TextureCacheManager::LoadState GetTextureState(const TextureCacheManager::TextureId& textureId);
+
+  /**
+   * @brief Get the current state of a texture
+   * @param[in] textureId The texture id to query
+   * @return The loading state if the texture is valid, or NOT_STARTED if the textureId
+   * is not valid.
+   */
+  TextureCacheManager::LoadState GetTextureStateInternal(const TextureCacheManager::TextureId& textureId);
+
+  /**
+   * @brief Get the associated texture set if the texture id is valid
+   * @param[in] textureId The texture Id to look up
+   * @return the associated texture set, or an empty handle if textureId is not valid
+   */
+  TextureSet GetTextureSet(const TextureCacheManager::TextureId& textureId);
+
+  /**
+   * @brief Get the external texture set if the texture id is valid
+   * @param[in] textureId The texture Id to look up
+   * @return the external texture set, or an empty handle if textureId is not valid
+   */
+  TextureSet GetExternalTextureSet(const TextureCacheManager::TextureId& textureId);
+
+  /**
+   * @brief Get the encoded image buffer
+   * @param[in] textureId The textureId to look up
+   * @return the encoded image buffer, or an empty handle if textureId is not valid
+   */
+  EncodedImageBuffer GetEncodedImageBuffer(const TextureCacheManager::TextureId& textureId);
+
+  /**
+   * @brief Get the encoded image buffer by VisualUrl
+   * @param[in] url The url to look up
+   * @return the encoded image buffer, or an empty handle if url is not buffer resource or buffer is not valid
+   */
+  EncodedImageBuffer GetEncodedImageBuffer(const std::string& url);
+
+  /**
+   * Adds an external texture to the texture manager
+   * @param[in] texture The texture to add
+   * @return string containing the URL for the texture
+   */
+  std::string AddExternalTexture(const TextureSet& texture);
+
+  /**
+   * Adds an external encoded image buffer to the texture manager
+   * @param[in] encodedImageBuffer The image buffer to add
+   * @return string containing the URL for the texture
+   */
+  std::string AddExternalEncodedImageBuffer(const EncodedImageBuffer& encodedImageBuffer);
+
+  /**
+   * Removes an external texture from texture manager
+   * @param[in] url The string containing the texture to remove
+   * @return handle to the texture
+   */
+  TextureSet RemoveExternalTexture(const std::string& url);
+
+  /**
+   * Removes an external encoded image buffer from texture manager
+   * @param[in] url The string containing the encoded image buffer to remove
+   * @return handle to the encoded image buffer
+   */
+  EncodedImageBuffer RemoveExternalEncodedImageBuffer(const std::string& url);
+
+  /**
+   * @brief Notify that external textures or external encoded image buffers are used.
+   * @param[in] url The URL of the texture to use.
+   */
+  void UseExternalResource(const VisualUrl& url);
+
+public:
+  // To Generate / Get / Remove TextureId.
+
+  /**
+   * @brief Generates a new, unique TextureId
+   * @return A unique TextureId
+   */
+  TextureCacheManager::TextureId GenerateUniqueTextureId();
+
+  /**
+   * @brief Used to lookup an index into the TextureInfoContainer from a TextureId
+   * @param[in] textureId The TextureId to look up
+   * @return              The cache index
+   */
+  TextureCacheManager::TextureCacheIndex GetCacheIndexFromId(const TextureCacheManager::TextureId& textureId);
+
+  /**
+   * @brief Generates a hash for caching based on the input parameters.
+   * Only applies size, fitting mode andsampling mode if the size is specified.
+   * Only applies maskTextureId if it isn't INVALID_TEXTURE_ID
+   * Always applies useAtlas.
+   * @param[in] url              The URL of the image to load
+   * @param[in] size             The image size
+   * @param[in] fittingMode      The FittingMode to use
+   * @param[in] samplingMode     The SamplingMode to use
+   * @param[in] useAtlas         True if atlased
+   * @param[in] maskTextureId    The masking texture id (or INVALID_TEXTURE_ID)
+   * @return                     A hash of the provided data for caching.
+   */
+  TextureCacheManager::TextureHash GenerateHash(
+    const std::string&                    url,
+    const Dali::ImageDimensions&          size,
+    const Dali::FittingMode::Type&        fittingMode,
+    const Dali::SamplingMode::Type&       samplingMode,
+    const TextureCacheManager::UseAtlas&  useAtlas,
+    const TextureCacheManager::TextureId& maskTextureId);
+
+  /**
+   * @brief Looks up a cached texture by its hash.
+   * If found, the given parameters are used to check there is no hash-collision.
+   * @param[in] hash              The hash to look up
+   * @param[in] url               The URL of the image to load
+   * @param[in] size              The image size
+   * @param[in] fittingMode       The FittingMode to use
+   * @param[in] samplingMode      The SamplingMode to use
+   * @param[in] useAtlas          True if atlased
+   * @param[in] maskTextureId     Optional texture ID to use to mask this image
+   * @param[in] preMultiplyOnLoad if the image's color should be multiplied by it's alpha. Set to OFF if there is no alpha.
+   * @return                      A TextureCacheId of a cached Texture if found. Or INVALID_CACHE_INDEX if not found.
+   */
+  TextureCacheManager::TextureCacheIndex FindCachedTexture(
+    const TextureCacheManager::TextureHash&    hash,
+    const std::string&                         url,
+    const Dali::ImageDimensions&               size,
+    const Dali::FittingMode::Type&             fittingMode,
+    const Dali::SamplingMode::Type&            samplingMode,
+    const TextureCacheManager::UseAtlas&       useAtlas,
+    const TextureCacheManager::TextureId&      maskTextureId,
+    const TextureCacheManager::MultiplyOnLoad& preMultiplyOnLoad);
+
+  /**
+   * @brief Append a Texture to the TextureCacheManager.
+   * @note This API doesn't check duplication of TextureId.
+   *
+   * @param[in] textureInfo TextureInfo that want to cache in container.
+   * @return Index of newly appended texture info.
+   */
+  TextureCacheManager::TextureCacheIndex AppendCache(const TextureCacheManager::TextureInfo& textureInfo);
+
+  /**
+   * @brief Remove a Texture from the TextureCacheManager.
+   *
+   * Textures are cached and therefore only the removal of the last
+   * occurrence of a Texture will cause its removal internally.
+   *
+   * @param[in] textureId The Id of the Texture to remove at Cache.
+   */
+  void RemoveCache(const TextureCacheManager::TextureId& textureId);
+
+public:
+  /**
+   * @brief Get TextureInfo as TextureCacheIndex.
+   * @note This API doesn't consider external & encodedimagebuffer.
+   * @param[in] textureCacheIndex Index of cahced texture.
+   * @return TextureInfo as textureCacheIndex
+   */
+  inline TextureCacheManager::TextureInfo& operator[](const TextureCacheManager::TextureCacheIndex& textureCacheIndex) noexcept
+  {
+    return mTextureInfoContainer[textureCacheIndex];
+  }
+
+  /**
+   * @brief The number of associated cached image
+   * @note This API doesn't consider external & encodedimagebuffer.
+   * @return The number of associated cached image
+   */
+  inline std::size_t size() noexcept
+  {
+    return mTextureInfoContainer.size();
+  }
+
+private:
+  // Private defined structs.
+
+  struct ExternalTextureInfo
+  {
+    ExternalTextureInfo(const TextureCacheManager::TextureId& textureId,
+                        const TextureSet&                     textureSet)
+    : textureId(textureId),
+      textureSet(textureSet),
+      referenceCount(1u)
+    {
+    }
+    TextureCacheManager::TextureId textureId;
+    TextureSet                     textureSet;
+    std::int16_t                   referenceCount;
+  };
+
+  struct EncodedBufferTextureInfo
+  {
+    EncodedBufferTextureInfo(const TextureCacheManager::TextureId& textureId,
+                             const EncodedImageBuffer&             encodedImageBuffer)
+    : textureId(textureId),
+      encodedImageBuffer(encodedImageBuffer),
+      referenceCount(1u)
+    {
+    }
+    TextureCacheManager::TextureId textureId;
+    EncodedImageBuffer             encodedImageBuffer;
+    std::int16_t                   referenceCount;
+  };
+
+  typedef std::vector<TextureCacheManager::TextureInfo>              TextureInfoContainerType;              ///< The container type used to manage the life-cycle and caching of Textures
+  typedef std::vector<TextureCacheManager::ExternalTextureInfo>      ExternalTextureInfoContainerType;      ///< The container type used to manage the life-cycle and caching of Textures
+  typedef std::vector<TextureCacheManager::EncodedBufferTextureInfo> EncodedBufferTextureInfoContainerType; ///< The container type used to manage the life-cycle and caching of Textures
+
+private:
+  /**
+   * Deleted copy constructor.
+   */
+  TextureCacheManager(const TextureCacheManager&) = delete;
+
+  /**
+   * Deleted assignment operator.
+   */
+  TextureCacheManager& operator=(const TextureCacheManager& rhs) = delete;
+
+private:                                                          // Member Variables:
+  TextureInfoContainerType              mTextureInfoContainer{};  ///< Used to manage the life-cycle and caching of Textures
+  ExternalTextureInfoContainerType      mExternalTextures{};      ///< Externally provided textures
+  EncodedBufferTextureInfoContainerType mEncodedBufferTextures{}; ///< Externally encoded buffer textures
+  TextureCacheManager::TextureId        mCurrentTextureId;        ///< The current value used for the unique Texture Id generation
+};
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXTURE_CACHE_MANAGER_H
diff --git a/dali-toolkit/internal/visuals/texture-manager/texture-manager-impl.cpp b/dali-toolkit/internal/visuals/texture-manager/texture-manager-impl.cpp
new file mode 100644 (file)
index 0000000..54dd76c
--- /dev/null
@@ -0,0 +1,1110 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include "texture-manager-impl.h"
+
+// EXTERNAL HEADERS
+#include <dali/devel-api/adaptor-framework/environment-variable.h>
+#include <dali/devel-api/adaptor-framework/image-loading.h>
+#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/rendering/geometry.h>
+
+// INTERNAL HEADERS
+#include <dali-toolkit/internal/visuals/image-atlas-manager.h>
+#include <dali-toolkit/internal/visuals/rendering-addon.h>
+#include <dali-toolkit/internal/visuals/texture-manager/texture-async-loading-helper.h>
+#include <dali-toolkit/internal/visuals/texture-manager/texture-cache-manager.h>
+
+namespace
+{
+constexpr auto INITIAL_HASH_NUMBER                     = size_t{0u};
+constexpr auto DEFAULT_NUMBER_OF_LOCAL_LOADER_THREADS  = size_t{4u};
+constexpr auto DEFAULT_NUMBER_OF_REMOTE_LOADER_THREADS = size_t{8u};
+
+constexpr auto NUMBER_OF_LOCAL_LOADER_THREADS_ENV  = "DALI_TEXTURE_LOCAL_THREADS";
+constexpr auto NUMBER_OF_REMOTE_LOADER_THREADS_ENV = "DALI_TEXTURE_REMOTE_THREADS";
+
+size_t GetNumberOfThreads(const char* environmentVariable, size_t defaultValue)
+{
+  using Dali::EnvironmentVariable::GetEnvironmentVariable;
+  auto           numberString          = GetEnvironmentVariable(environmentVariable);
+  auto           numberOfThreads       = numberString ? std::strtoul(numberString, nullptr, 10) : 0;
+  constexpr auto MAX_NUMBER_OF_THREADS = 100u;
+  DALI_ASSERT_DEBUG(numberOfThreads < MAX_NUMBER_OF_THREADS);
+  return (numberOfThreads > 0 && numberOfThreads < MAX_NUMBER_OF_THREADS) ? numberOfThreads : defaultValue;
+}
+
+size_t GetNumberOfLocalLoaderThreads()
+{
+  return GetNumberOfThreads(NUMBER_OF_LOCAL_LOADER_THREADS_ENV, DEFAULT_NUMBER_OF_LOCAL_LOADER_THREADS);
+}
+
+size_t GetNumberOfRemoteLoaderThreads()
+{
+  return GetNumberOfThreads(NUMBER_OF_REMOTE_LOADER_THREADS_ENV, DEFAULT_NUMBER_OF_REMOTE_LOADER_THREADS);
+}
+
+} // namespace
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+#ifdef DEBUG_ENABLED
+// Define logfilter Internal namespace level so other files (e.g. texture-cache-manager.cpp) can also use this filter.
+Debug::Filter* gTextureManagerLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_TEXTURE_MANAGER");
+
+// clang-format off
+#define GET_LOAD_STATE_STRING(loadState) \
+  loadState == TextureManagerType::LoadState::NOT_STARTED      ? "NOT_STARTED"      : \
+  loadState == TextureManagerType::LoadState::LOADING          ? "LOADING"          : \
+  loadState == TextureManagerType::LoadState::LOAD_FINISHED    ? "LOAD_FINISHED"    : \
+  loadState == TextureManagerType::LoadState::WAITING_FOR_MASK ? "WAITING_FOR_MASK" : \
+  loadState == TextureManagerType::LoadState::MASK_APPLYING    ? "MASK_APPLYING"    : \
+  loadState == TextureManagerType::LoadState::MASK_APPLIED     ? "MASK_APPLIED"     : \
+  loadState == TextureManagerType::LoadState::UPLOADED         ? "UPLOADED"         : \
+  loadState == TextureManagerType::LoadState::CANCELLED        ? "CANCELLED"        : \
+  loadState == TextureManagerType::LoadState::LOAD_FAILED      ? "LOAD_FAILED"      : \
+                                                                 "Unknown"
+
+// clang-format on
+#endif
+
+namespace
+{
+const uint32_t DEFAULT_ATLAS_SIZE(1024u);               ///< This size can fit 8 by 8 images of average size 128 * 128
+const Vector4  FULL_ATLAS_RECT(0.0f, 0.0f, 1.0f, 1.0f); ///< UV Rectangle that covers the full Texture
+
+void PreMultiply(Devel::PixelBuffer pixelBuffer, TextureManager::MultiplyOnLoad& preMultiplyOnLoad)
+{
+  if(Pixel::HasAlpha(pixelBuffer.GetPixelFormat()))
+  {
+    if(preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD)
+    {
+      pixelBuffer.MultiplyColorByAlpha();
+    }
+  }
+  else
+  {
+    preMultiplyOnLoad = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
+  }
+}
+
+} // Anonymous namespace
+
+TextureManager::MaskingData::MaskingData()
+: mAlphaMaskUrl(),
+  mAlphaMaskId(INVALID_TEXTURE_ID),
+  mContentScaleFactor(1.0f),
+  mCropToMask(true)
+{
+}
+
+TextureManager::TextureManager()
+: mTextureCacheManager(),
+  mAsyncLocalLoaders(GetNumberOfLocalLoaderThreads(), [&]() { return TextureAsyncLoadingHelper(*this); }),
+  mAsyncRemoteLoaders(GetNumberOfRemoteLoaderThreads(), [&]() { return TextureAsyncLoadingHelper(*this); }),
+  mLifecycleObservers(),
+  mLoadQueue(),
+  mQueueLoadFlag(false)
+{
+  // Initialize the AddOn
+  RenderingAddOn::Get();
+}
+
+TextureManager::~TextureManager()
+{
+  for(auto iter = mLifecycleObservers.Begin(), endIter = mLifecycleObservers.End(); iter != endIter; ++iter)
+  {
+    (*iter)->TextureManagerDestroyed();
+  }
+}
+
+TextureSet TextureManager::LoadAnimatedImageTexture(
+  Dali::AnimatedImageLoading      animatedImageLoading,
+  const std::uint32_t&            frameIndex,
+  const Dali::SamplingMode::Type& samplingMode,
+  const bool&                     synchronousLoading,
+  TextureManager::TextureId&      textureId,
+  const Dali::WrapMode::Type&     wrapModeU,
+  const Dali::WrapMode::Type&     wrapModeV,
+  TextureUploadObserver*          textureObserver)
+{
+  TextureSet textureSet;
+
+  if(synchronousLoading)
+  {
+    Devel::PixelBuffer pixelBuffer;
+    if(animatedImageLoading)
+    {
+      pixelBuffer = animatedImageLoading.LoadFrame(frameIndex);
+    }
+    if(!pixelBuffer)
+    {
+      DALI_LOG_ERROR("TextureManager::LoadAnimatedImageTexture: Synchronous loading is failed\n");
+    }
+    else
+    {
+      PixelData pixelData = Devel::PixelBuffer::Convert(pixelBuffer); // takes ownership of buffer
+      if(!textureSet)
+      {
+        Texture texture = Texture::New(Dali::TextureType::TEXTURE_2D, pixelData.GetPixelFormat(), pixelData.GetWidth(), pixelData.GetHeight());
+        texture.Upload(pixelData);
+        textureSet = TextureSet::New();
+        textureSet.SetTexture(0u, texture);
+      }
+    }
+  }
+  else
+  {
+    auto preMultiply                    = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
+    textureId                           = RequestLoadInternal(animatedImageLoading.GetUrl(), INVALID_TEXTURE_ID, 1.0f, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::BOX_THEN_LINEAR, UseAtlas::NO_ATLAS, false, StorageType::UPLOAD_TO_TEXTURE, textureObserver, true, TextureManager::ReloadPolicy::CACHED, preMultiply, animatedImageLoading, frameIndex, false);
+    TextureManager::LoadState loadState = mTextureCacheManager.GetTextureStateInternal(textureId);
+    if(loadState == TextureManager::LoadState::UPLOADED)
+    {
+      // LoadComplete has already been called - keep the same texture set
+      textureSet = GetTextureSet(textureId);
+    }
+  }
+
+  if(textureSet)
+  {
+    Sampler sampler = Sampler::New();
+    sampler.SetWrapMode(wrapModeU, wrapModeV);
+    textureSet.SetSampler(0u, sampler);
+  }
+
+  return textureSet;
+}
+
+Devel::PixelBuffer TextureManager::LoadPixelBuffer(
+  const VisualUrl&                url,
+  const Dali::ImageDimensions&    desiredSize,
+  const Dali::FittingMode::Type&  fittingMode,
+  const Dali::SamplingMode::Type& samplingMode,
+  const bool&                     synchronousLoading,
+  TextureUploadObserver*          textureObserver,
+  const bool&                     orientationCorrection,
+  TextureManager::MultiplyOnLoad& preMultiplyOnLoad)
+{
+  Devel::PixelBuffer pixelBuffer;
+  if(synchronousLoading)
+  {
+    if(url.IsValid())
+    {
+      if(url.IsBufferResource())
+      {
+        const EncodedImageBuffer& encodedImageBuffer = mTextureCacheManager.GetEncodedImageBuffer(url.GetUrl());
+        if(encodedImageBuffer)
+        {
+          pixelBuffer = LoadImageFromBuffer(encodedImageBuffer.GetRawBuffer(), desiredSize, fittingMode, samplingMode, orientationCorrection);
+        }
+      }
+      else
+      {
+        pixelBuffer = LoadImageFromFile(url.GetUrl(), desiredSize, fittingMode, samplingMode, orientationCorrection);
+      }
+      if(pixelBuffer && preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD)
+      {
+        PreMultiply(pixelBuffer, preMultiplyOnLoad);
+      }
+    }
+  }
+  else
+  {
+    RequestLoadInternal(url, INVALID_TEXTURE_ID, 1.0f, desiredSize, fittingMode, samplingMode, UseAtlas::NO_ATLAS, false, StorageType::RETURN_PIXEL_BUFFER, textureObserver, orientationCorrection, TextureManager::ReloadPolicy::FORCED, preMultiplyOnLoad, Dali::AnimatedImageLoading(), 0u, false);
+  }
+
+  return pixelBuffer;
+}
+
+TextureSet TextureManager::LoadTexture(
+  const VisualUrl&                    url,
+  const Dali::ImageDimensions&        desiredSize,
+  const Dali::FittingMode::Type&      fittingMode,
+  const Dali::SamplingMode::Type&     samplingMode,
+  MaskingDataPointer&                 maskInfo,
+  const bool&                         synchronousLoading,
+  TextureManager::TextureId&          textureId,
+  Vector4&                            textureRect,
+  Dali::ImageDimensions&              textureRectSize,
+  bool&                               atlasingStatus,
+  bool&                               loadingStatus,
+  const Dali::WrapMode::Type&         wrapModeU,
+  const Dali::WrapMode::Type&         wrapModeV,
+  TextureUploadObserver*              textureObserver,
+  AtlasUploadObserver*                atlasObserver,
+  ImageAtlasManagerPtr                imageAtlasManager,
+  const bool&                         orientationCorrection,
+  const TextureManager::ReloadPolicy& reloadPolicy,
+  TextureManager::MultiplyOnLoad&     preMultiplyOnLoad)
+{
+  TextureSet textureSet;
+
+  loadingStatus = false;
+  textureRect   = FULL_ATLAS_RECT;
+
+  if(VisualUrl::TEXTURE == url.GetProtocolType())
+  {
+    std::string location = url.GetLocation();
+    if(location.size() > 0u)
+    {
+      TextureId id = std::stoi(location);
+      textureSet   = mTextureCacheManager.GetExternalTextureSet(id);
+      if(textureSet)
+      {
+        preMultiplyOnLoad = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
+        textureId         = id;
+        return textureSet;
+      }
+    }
+  }
+  else
+  {
+    // For Atlas
+    if(synchronousLoading && atlasingStatus && imageAtlasManager->CheckAtlasAvailable(url, desiredSize))
+    {
+      Devel::PixelBuffer pixelBuffer = LoadImageSynchronously(url, desiredSize, fittingMode, samplingMode, orientationCorrection);
+
+      if(maskInfo && maskInfo->mAlphaMaskUrl.IsValid())
+      {
+        Devel::PixelBuffer maskPixelBuffer = LoadImageSynchronously(maskInfo->mAlphaMaskUrl.GetUrl(), ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::NO_FILTER, true);
+        if(maskPixelBuffer)
+        {
+          pixelBuffer.ApplyMask(maskPixelBuffer, maskInfo->mContentScaleFactor, maskInfo->mCropToMask);
+        }
+      }
+
+      PixelData data;
+      if(pixelBuffer)
+      {
+        PreMultiply(pixelBuffer, preMultiplyOnLoad);
+        data = Devel::PixelBuffer::Convert(pixelBuffer); // takes ownership of buffer
+
+        if(data)
+        {
+          textureSet = imageAtlasManager->Add(textureRect, data);
+          if(textureSet)
+          {
+            textureRectSize.SetWidth(data.GetWidth());
+            textureRectSize.SetHeight(data.GetHeight());
+          }
+        }
+        else
+        {
+          DALI_LOG_ERROR("TextureManager::LoadTexture: Synchronous Texture loading with atlasing is failed.\n");
+        }
+      }
+      if(!textureSet)
+      {
+        atlasingStatus = false;
+      }
+    }
+
+    if(!textureSet)
+    {
+      loadingStatus = true;
+      // Atlas manager can chage desired size when it is set by 0,0.
+      // We should store into textureRectSize only if atlasing succes.
+      // So copy inpued desiredSize, and replace value into textureRectSize only if atlasing success.
+      Dali::ImageDimensions atlasDesiredSize = desiredSize;
+      if(atlasingStatus)
+      {
+        textureSet = imageAtlasManager->Add(textureRect, url.GetUrl(), atlasDesiredSize, fittingMode, true, atlasObserver);
+      }
+      if(!textureSet) // big image, no atlasing or atlasing failed
+      {
+        atlasingStatus = false;
+        if(!maskInfo || !maskInfo->mAlphaMaskUrl.IsValid())
+        {
+          textureId = RequestLoad(
+            url,
+            desiredSize,
+            fittingMode,
+            samplingMode,
+            UseAtlas::NO_ATLAS,
+            textureObserver,
+            orientationCorrection,
+            reloadPolicy,
+            preMultiplyOnLoad,
+            synchronousLoading);
+        }
+        else
+        {
+          maskInfo->mAlphaMaskId = RequestMaskLoad(maskInfo->mAlphaMaskUrl, synchronousLoading);
+          textureId              = RequestLoad(
+            url,
+            maskInfo->mAlphaMaskId,
+            maskInfo->mContentScaleFactor,
+            desiredSize,
+            fittingMode,
+            samplingMode,
+            UseAtlas::NO_ATLAS,
+            maskInfo->mCropToMask,
+            textureObserver,
+            orientationCorrection,
+            reloadPolicy,
+            preMultiplyOnLoad,
+            synchronousLoading);
+        }
+
+        TextureManager::LoadState loadState = mTextureCacheManager.GetTextureStateInternal(textureId);
+        if(loadState == TextureManager::LoadState::UPLOADED)
+        {
+          // LoadComplete has already been called - keep the same texture set
+          textureSet = mTextureCacheManager.GetTextureSet(textureId);
+        }
+
+        // If we are loading the texture, or waiting for the ready signal handler to complete, inform
+        // caller that they need to wait.
+        loadingStatus = (loadState == TextureManager::LoadState::LOADING ||
+                         loadState == TextureManager::LoadState::WAITING_FOR_MASK ||
+                         loadState == TextureManager::LoadState::MASK_APPLYING ||
+                         loadState == TextureManager::LoadState::MASK_APPLIED ||
+                         loadState == TextureManager::LoadState::NOT_STARTED ||
+                         mQueueLoadFlag);
+      }
+      else
+      {
+        textureRectSize = atlasDesiredSize;
+      }
+    }
+  }
+
+  if(!atlasingStatus && textureSet)
+  {
+    Sampler sampler = Sampler::New();
+    sampler.SetWrapMode(wrapModeU, wrapModeV);
+    textureSet.SetSampler(0u, sampler);
+  }
+
+  if(synchronousLoading)
+  {
+    loadingStatus = false;
+  }
+
+  return textureSet;
+}
+
+TextureManager::TextureId TextureManager::RequestLoad(
+  const VisualUrl&                    url,
+  const ImageDimensions&              desiredSize,
+  const Dali::FittingMode::Type&      fittingMode,
+  const Dali::SamplingMode::Type&     samplingMode,
+  const UseAtlas&                     useAtlas,
+  TextureUploadObserver*              observer,
+  const bool&                         orientationCorrection,
+  const TextureManager::ReloadPolicy& reloadPolicy,
+  TextureManager::MultiplyOnLoad&     preMultiplyOnLoad,
+  const bool&                         synchronousLoading)
+{
+  return RequestLoadInternal(url, INVALID_TEXTURE_ID, 1.0f, desiredSize, fittingMode, samplingMode, useAtlas, false, StorageType::UPLOAD_TO_TEXTURE, observer, orientationCorrection, reloadPolicy, preMultiplyOnLoad, Dali::AnimatedImageLoading(), 0u, synchronousLoading);
+}
+
+TextureManager::TextureId TextureManager::RequestLoad(
+  const VisualUrl&                    url,
+  const TextureManager::TextureId&    maskTextureId,
+  const float&                        contentScale,
+  const Dali::ImageDimensions&        desiredSize,
+  const Dali::FittingMode::Type&      fittingMode,
+  const Dali::SamplingMode::Type&     samplingMode,
+  const TextureManager::UseAtlas&     useAtlas,
+  const bool&                         cropToMask,
+  TextureUploadObserver*              observer,
+  const bool&                         orientationCorrection,
+  const TextureManager::ReloadPolicy& reloadPolicy,
+  TextureManager::MultiplyOnLoad&     preMultiplyOnLoad,
+  const bool&                         synchronousLoading)
+{
+  return RequestLoadInternal(url, maskTextureId, contentScale, desiredSize, fittingMode, samplingMode, useAtlas, cropToMask, StorageType::UPLOAD_TO_TEXTURE, observer, orientationCorrection, reloadPolicy, preMultiplyOnLoad, Dali::AnimatedImageLoading(), 0u, synchronousLoading);
+}
+
+TextureManager::TextureId TextureManager::RequestMaskLoad(
+  const VisualUrl& maskUrl,
+  const bool&      synchronousLoading)
+{
+  // Use the normal load procedure to get the alpha mask.
+  auto preMultiply = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
+  return RequestLoadInternal(maskUrl, INVALID_TEXTURE_ID, 1.0f, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::NO_FILTER, UseAtlas::NO_ATLAS, false, StorageType::KEEP_PIXEL_BUFFER, NULL, true, TextureManager::ReloadPolicy::CACHED, preMultiply, Dali::AnimatedImageLoading(), 0u, synchronousLoading);
+}
+
+TextureManager::TextureId TextureManager::RequestLoadInternal(
+  const VisualUrl&                    url,
+  const TextureManager::TextureId&    maskTextureId,
+  const float&                        contentScale,
+  const Dali::ImageDimensions&        desiredSize,
+  const Dali::FittingMode::Type&      fittingMode,
+  const Dali::SamplingMode::Type&     samplingMode,
+  const TextureManager::UseAtlas&     useAtlas,
+  const bool&                         cropToMask,
+  const TextureManager::StorageType&  storageType,
+  TextureUploadObserver*              observer,
+  const bool&                         orientationCorrection,
+  const TextureManager::ReloadPolicy& reloadPolicy,
+  TextureManager::MultiplyOnLoad&     preMultiplyOnLoad,
+  Dali::AnimatedImageLoading          animatedImageLoading,
+  const std::uint32_t&                frameIndex,
+  const bool&                         synchronousLoading)
+{
+  // First check if the requested Texture is cached.
+  bool isAnimatedImage = (animatedImageLoading) ? true : false;
+
+  TextureHash       textureHash = INITIAL_HASH_NUMBER;
+  TextureCacheIndex cacheIndex  = INVALID_CACHE_INDEX;
+  if(storageType != StorageType::RETURN_PIXEL_BUFFER && !isAnimatedImage)
+  {
+    textureHash = mTextureCacheManager.GenerateHash(url.GetUrl(), desiredSize, fittingMode, samplingMode, useAtlas, maskTextureId);
+
+    // Look up the texture by hash. Note: The extra parameters are used in case of a hash collision.
+    cacheIndex = mTextureCacheManager.FindCachedTexture(textureHash, url.GetUrl(), desiredSize, fittingMode, samplingMode, useAtlas, maskTextureId, preMultiplyOnLoad);
+  }
+
+  TextureManager::TextureId textureId = INVALID_TEXTURE_ID;
+  // Check if the requested Texture exists in the cache.
+  if(cacheIndex != INVALID_CACHE_INDEX)
+  {
+    if(TextureManager::ReloadPolicy::CACHED == reloadPolicy)
+    {
+      // Mark this texture being used by another client resource. Forced reload would replace the current texture
+      // without the need for incrementing the reference count.
+      ++(mTextureCacheManager[cacheIndex].referenceCount);
+    }
+    textureId = mTextureCacheManager[cacheIndex].textureId;
+
+    // Update preMultiplyOnLoad value. It should be changed according to preMultiplied value of the cached info.
+    preMultiplyOnLoad = mTextureCacheManager[cacheIndex].preMultiplied ? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD : TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
+
+    DALI_LOG_INFO(gTextureManagerLogFilter, Debug::General, "TextureManager::RequestLoad( url=%s observer=%p ) Using cached texture id@%d, textureId=%d\n", url.GetUrl().c_str(), observer, cacheIndex, textureId);
+  }
+
+  if(textureId == INVALID_TEXTURE_ID) // There was no caching, or caching not required
+  {
+    if(VisualUrl::BUFFER == url.GetProtocolType())
+    {
+      std::string location = url.GetLocation();
+      if(location.size() > 0u)
+      {
+        TextureId                 targetId           = std::stoi(location);
+        const EncodedImageBuffer& encodedImageBuffer = mTextureCacheManager.GetEncodedImageBuffer(targetId);
+        if(encodedImageBuffer)
+        {
+          textureId = targetId;
+
+          // Increase EncodedImageBuffer reference during it contains mTextureInfoContainer.
+          // TODO! We should change action when reload policy is FORCE.
+          // Eunki Hong will fix it after refactoring patch merged.
+          mTextureCacheManager.UseExternalResource(url.GetUrl());
+        }
+      }
+    }
+
+    if(textureId == INVALID_TEXTURE_ID)
+    {
+      textureId = mTextureCacheManager.GenerateUniqueTextureId();
+    }
+
+    bool preMultiply = (preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD);
+
+    // Cache new texutre, and get cacheIndex.
+    cacheIndex = mTextureCacheManager.AppendCache(TextureInfo(textureId, maskTextureId, url, desiredSize, contentScale, fittingMode, samplingMode, false, cropToMask, useAtlas, textureHash, orientationCorrection, preMultiply, animatedImageLoading, frameIndex));
+
+    DALI_LOG_INFO(gTextureManagerLogFilter, Debug::General, "TextureManager::RequestLoad( url=%s observer=%p ) New texture, cacheIndex:%d, textureId=%d\n", url.GetUrl().c_str(), observer, cacheIndex, textureId);
+  }
+
+  // The below code path is common whether we are using the cache or not.
+  // The textureInfoIndex now refers to either a pre-existing cached TextureInfo,
+  // or a new TextureInfo just created.
+  TextureInfo& textureInfo(mTextureCacheManager[cacheIndex]);
+  textureInfo.maskTextureId         = maskTextureId;
+  textureInfo.storageType           = storageType;
+  textureInfo.orientationCorrection = orientationCorrection;
+
+  DALI_LOG_INFO(gTextureManagerLogFilter, Debug::General, "TextureInfo loadState:%s\n", GET_LOAD_STATE_STRING(textureInfo.loadState));
+
+  // Force reloading of texture by setting loadState unless already loading or cancelled.
+  if(TextureManager::ReloadPolicy::FORCED == reloadPolicy &&
+     TextureManager::LoadState::LOADING != textureInfo.loadState &&
+     TextureManager::LoadState::WAITING_FOR_MASK != textureInfo.loadState &&
+     TextureManager::LoadState::MASK_APPLYING != textureInfo.loadState &&
+     TextureManager::LoadState::MASK_APPLIED != textureInfo.loadState &&
+     TextureManager::LoadState::CANCELLED != textureInfo.loadState)
+  {
+    DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Verbose, "TextureManager::RequestLoad( url=%s observer=%p ) ForcedReload cacheIndex:%d, textureId=%d\n", url.GetUrl().c_str(), observer, cacheIndex, textureId);
+
+    textureInfo.loadState = TextureManager::LoadState::NOT_STARTED;
+  }
+
+  if(!synchronousLoading)
+  {
+    // Check if we should add the observer.
+    // Only do this if we have not loaded yet and it will not have loaded by the end of this method.
+    switch(textureInfo.loadState)
+    {
+      case TextureManager::LoadState::LOAD_FAILED: // Failed notifies observer which then stops observing.
+      case TextureManager::LoadState::NOT_STARTED:
+      {
+        LoadOrQueueTexture(textureInfo, observer); // If called inside NotifyObservers, queues until afterwards
+        break;
+      }
+      case TextureManager::LoadState::LOADING:
+      case TextureManager::LoadState::WAITING_FOR_MASK:
+      case TextureManager::LoadState::MASK_APPLYING:
+      case TextureManager::LoadState::MASK_APPLIED:
+      {
+        ObserveTexture(textureInfo, observer);
+        break;
+      }
+      case TextureManager::LoadState::UPLOADED:
+      {
+        if(observer)
+        {
+          LoadOrQueueTexture(textureInfo, observer);
+        }
+        break;
+      }
+      case TextureManager::LoadState::CANCELLED:
+      {
+        // A cancelled texture hasn't finished loading yet. Treat as a loading texture
+        // (it's ref count has already been incremented, above)
+        textureInfo.loadState = TextureManager::LoadState::LOADING;
+        ObserveTexture(textureInfo, observer);
+        break;
+      }
+      case TextureManager::LoadState::LOAD_FINISHED:
+      {
+        // Loading has already completed.
+        if(observer && textureInfo.storageType == StorageType::RETURN_PIXEL_BUFFER)
+        {
+          LoadOrQueueTexture(textureInfo, observer);
+        }
+        break;
+      }
+    }
+  }
+  else
+  {
+    // If the image is already finished to load, use cached texture.
+    // We don't need to consider Observer becaouse this is synchronous loading.
+    if(textureInfo.loadState == TextureManager::LoadState::UPLOADED ||
+       textureInfo.loadState == TextureManager::LoadState::LOAD_FINISHED)
+    {
+      return textureId;
+    }
+    else
+    {
+      Devel::PixelBuffer pixelBuffer = LoadImageSynchronously(url, desiredSize, fittingMode, samplingMode, orientationCorrection);
+      ;
+
+      if(!pixelBuffer)
+      {
+        // If pixelBuffer loading is failed in synchronously, call Remove() method.
+        Remove(textureId, nullptr);
+        return INVALID_TEXTURE_ID;
+      }
+
+      if(storageType == StorageType::KEEP_PIXEL_BUFFER) // For the mask image loading.
+      {
+        textureInfo.pixelBuffer = pixelBuffer; // Store the pixel data
+        textureInfo.loadState   = LoadState::LOAD_FINISHED;
+      }
+      else // For the image loading.
+      {
+        if(maskTextureId != INVALID_TEXTURE_ID)
+        {
+          TextureCacheIndex maskCacheIndex = mTextureCacheManager.GetCacheIndexFromId(maskTextureId);
+          if(maskCacheIndex != INVALID_CACHE_INDEX)
+          {
+            Devel::PixelBuffer maskPixelBuffer = mTextureCacheManager[maskCacheIndex].pixelBuffer;
+            if(maskPixelBuffer)
+            {
+              pixelBuffer.ApplyMask(maskPixelBuffer, contentScale, cropToMask);
+            }
+          }
+          else
+          {
+            DALI_LOG_ERROR("Mask image is not stored in cache.\n");
+          }
+        }
+        PreMultiply(pixelBuffer, preMultiplyOnLoad);
+
+        // Upload texture
+        UploadTexture(pixelBuffer, textureInfo);
+      }
+    }
+  }
+
+  // Return the TextureId for which this Texture can now be referenced by externally.
+  return textureId;
+}
+
+void TextureManager::Remove(const TextureManager::TextureId& textureId, TextureUploadObserver* observer)
+{
+  // Remove textureId in CacheManager.
+  mTextureCacheManager.RemoveCache(textureId);
+
+  if(observer)
+  {
+    // Remove element from the LoadQueue
+    for(auto&& element : mLoadQueue)
+    {
+      if(element.mObserver == observer)
+      {
+        // Do not erase the item. We will clear it later in ProcessQueuedTextures().
+        element.mObserver = nullptr;
+        break;
+      }
+    }
+  }
+}
+
+Devel::PixelBuffer TextureManager::LoadImageSynchronously(
+  const VisualUrl&                url,
+  const Dali::ImageDimensions&    desiredSize,
+  const Dali::FittingMode::Type&  fittingMode,
+  const Dali::SamplingMode::Type& samplingMode,
+  const bool&                     orientationCorrection)
+{
+  Devel::PixelBuffer pixelBuffer;
+  if(url.IsBufferResource())
+  {
+    const EncodedImageBuffer& encodedImageBuffer = mTextureCacheManager.GetEncodedImageBuffer(url.GetUrl());
+    if(encodedImageBuffer)
+    {
+      pixelBuffer = LoadImageFromBuffer(encodedImageBuffer.GetRawBuffer(), desiredSize, fittingMode, samplingMode, orientationCorrection);
+    }
+  }
+  else
+  {
+    pixelBuffer = LoadImageFromFile(url.GetUrl(), desiredSize, fittingMode, samplingMode, orientationCorrection);
+  }
+  return pixelBuffer;
+}
+
+void TextureManager::AddObserver(TextureManager::LifecycleObserver& observer)
+{
+  // make sure an observer doesn't observe the same object twice
+  // otherwise it will get multiple calls to ObjectDestroyed()
+  DALI_ASSERT_DEBUG(mLifecycleObservers.End() == std::find(mLifecycleObservers.Begin(), mLifecycleObservers.End(), &observer));
+  mLifecycleObservers.PushBack(&observer);
+}
+
+void TextureManager::RemoveObserver(TextureManager::LifecycleObserver& observer)
+{
+  // Find the observer...
+  auto endIter = mLifecycleObservers.End();
+  for(auto iter = mLifecycleObservers.Begin(); iter != endIter; ++iter)
+  {
+    if((*iter) == &observer)
+    {
+      mLifecycleObservers.Erase(iter);
+      break;
+    }
+  }
+  DALI_ASSERT_DEBUG(endIter != mLifecycleObservers.End());
+}
+
+void TextureManager::LoadOrQueueTexture(TextureManager::TextureInfo& textureInfo, TextureUploadObserver* observer)
+{
+  switch(textureInfo.loadState)
+  {
+    case LoadState::NOT_STARTED:
+    case LoadState::LOAD_FAILED:
+    {
+      if(mQueueLoadFlag)
+      {
+        QueueLoadTexture(textureInfo, observer);
+      }
+      else
+      {
+        LoadTexture(textureInfo, observer);
+      }
+      break;
+    }
+    case LoadState::UPLOADED:
+    {
+      if(mQueueLoadFlag)
+      {
+        QueueLoadTexture(textureInfo, observer);
+      }
+      else
+      {
+        // The Texture has already loaded. The other observers have already been notified.
+        // We need to send a "late" loaded notification for this observer.
+        observer->LoadComplete(true, TextureUploadObserver::TextureInformation(TextureUploadObserver::ReturnType::TEXTURE, textureInfo.textureId, textureInfo.textureSet, (textureInfo.useAtlas == UseAtlas::USE_ATLAS) ? true : false, textureInfo.atlasRect, textureInfo.preMultiplied));
+      }
+      break;
+    }
+    case LoadState::LOADING:
+    case LoadState::CANCELLED:
+    case LoadState::LOAD_FINISHED:
+    case LoadState::WAITING_FOR_MASK:
+    case LoadState::MASK_APPLYING:
+    case LoadState::MASK_APPLIED:
+    {
+      break;
+    }
+  }
+}
+
+void TextureManager::QueueLoadTexture(const TextureManager::TextureInfo& textureInfo, TextureUploadObserver* observer)
+{
+  const auto& textureId = textureInfo.textureId;
+  mLoadQueue.PushBack(LoadQueueElement(textureId, observer));
+
+  observer->DestructionSignal().Connect(this, &TextureManager::ObserverDestroyed);
+}
+
+void TextureManager::LoadTexture(TextureManager::TextureInfo& textureInfo, TextureUploadObserver* observer)
+{
+  DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureManager::LoadTexture(): url:%s sync:%s\n", textureInfo.url.GetUrl().c_str(), textureInfo.loadSynchronously ? "T" : "F");
+
+  textureInfo.loadState = LoadState::LOADING;
+  if(!textureInfo.loadSynchronously)
+  {
+    auto& loadersContainer  = (textureInfo.url.IsLocalResource() || textureInfo.url.IsBufferResource()) ? mAsyncLocalLoaders : mAsyncRemoteLoaders;
+    auto  loadingHelperIt   = loadersContainer.GetNext();
+    auto  premultiplyOnLoad = (textureInfo.preMultiplyOnLoad && textureInfo.maskTextureId == INVALID_TEXTURE_ID) ? DevelAsyncImageLoader::PreMultiplyOnLoad::ON : DevelAsyncImageLoader::PreMultiplyOnLoad::OFF;
+    DALI_ASSERT_ALWAYS(loadingHelperIt != loadersContainer.End());
+    if(textureInfo.animatedImageLoading)
+    {
+      loadingHelperIt->LoadAnimatedImage(textureInfo.textureId, textureInfo.animatedImageLoading, textureInfo.frameIndex);
+    }
+    else
+    {
+      loadingHelperIt->Load(textureInfo.textureId, textureInfo.url, textureInfo.desiredSize, textureInfo.fittingMode, textureInfo.samplingMode, textureInfo.orientationCorrection, premultiplyOnLoad);
+    }
+  }
+  ObserveTexture(textureInfo, observer);
+}
+
+void TextureManager::ProcessQueuedTextures()
+{
+  for(auto&& element : mLoadQueue)
+  {
+    if(!element.mObserver)
+    {
+      continue;
+    }
+
+    TextureCacheIndex cacheIndex = mTextureCacheManager.GetCacheIndexFromId(element.mTextureId);
+    if(cacheIndex != INVALID_CACHE_INDEX)
+    {
+      TextureInfo& textureInfo(mTextureCacheManager[cacheIndex]);
+      if(textureInfo.loadState == LoadState::UPLOADED)
+      {
+        element.mObserver->LoadComplete(true, TextureUploadObserver::TextureInformation(TextureUploadObserver::ReturnType::TEXTURE, textureInfo.textureId, textureInfo.textureSet, (textureInfo.useAtlas == UseAtlas::USE_ATLAS) ? true : false, textureInfo.atlasRect, textureInfo.preMultiplied));
+      }
+      else if(textureInfo.loadState == LoadState::LOAD_FINISHED && textureInfo.storageType == StorageType::RETURN_PIXEL_BUFFER)
+      {
+        element.mObserver->LoadComplete(true, TextureUploadObserver::TextureInformation(TextureUploadObserver::ReturnType::PIXEL_BUFFER, textureInfo.pixelBuffer, textureInfo.url.GetUrl(), textureInfo.preMultiplied));
+      }
+      else
+      {
+        LoadTexture(textureInfo, element.mObserver);
+      }
+    }
+  }
+  mLoadQueue.Clear();
+}
+
+void TextureManager::ObserveTexture(TextureManager::TextureInfo& textureInfo,
+                                    TextureUploadObserver*       observer)
+{
+  DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureManager::ObserveTexture(): url:%s observer:%p\n", textureInfo.url.GetUrl().c_str(), observer);
+
+  if(observer)
+  {
+    textureInfo.observerList.PushBack(observer);
+    observer->DestructionSignal().Connect(this, &TextureManager::ObserverDestroyed);
+  }
+}
+
+void TextureManager::AsyncLoadComplete(const TextureManager::TextureId& textureId, Devel::PixelBuffer pixelBuffer)
+{
+  DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureManager::AsyncLoadComplete( textureId:%d )\n", textureId);
+  TextureCacheIndex cacheIndex = mTextureCacheManager.GetCacheIndexFromId(textureId);
+  if(cacheIndex != INVALID_CACHE_INDEX)
+  {
+    TextureInfo& textureInfo(mTextureCacheManager[cacheIndex]);
+
+    DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "  textureId:%d Url:%s CacheIndex:%d LoadState: %s\n", textureInfo.textureId, textureInfo.url.GetUrl().c_str(), cacheIndex, GET_LOAD_STATE_STRING(textureInfo.loadState));
+
+    if(textureInfo.loadState != LoadState::CANCELLED)
+    {
+      // textureInfo can be invalidated after this call (as the mTextureInfoContainer may be modified)
+      PostLoad(textureInfo, pixelBuffer);
+    }
+    else
+    {
+      Remove(textureInfo.textureId, nullptr);
+    }
+  }
+}
+
+void TextureManager::PostLoad(TextureManager::TextureInfo& textureInfo, Devel::PixelBuffer& pixelBuffer)
+{
+  // Was the load successful?
+  if(pixelBuffer && (pixelBuffer.GetWidth() != 0) && (pixelBuffer.GetHeight() != 0))
+  {
+    // No atlas support for now
+    textureInfo.useAtlas      = UseAtlas::NO_ATLAS;
+    textureInfo.preMultiplied = pixelBuffer.IsAlphaPreMultiplied();
+
+    if(textureInfo.storageType == StorageType::UPLOAD_TO_TEXTURE)
+    {
+      // If there is a mask texture ID associated with this texture, then apply the mask
+      // if it's already loaded. If it hasn't, and the mask is still loading,
+      // wait for the mask to finish loading.
+      // note, If the texture is already uploaded synchronously during loading,
+      // we don't need to apply mask.
+      if(textureInfo.loadState != LoadState::UPLOADED &&
+         textureInfo.maskTextureId != INVALID_TEXTURE_ID)
+      {
+        if(textureInfo.loadState == LoadState::MASK_APPLYING)
+        {
+          textureInfo.loadState = LoadState::MASK_APPLIED;
+          UploadTexture(pixelBuffer, textureInfo);
+          NotifyObservers(textureInfo, true);
+        }
+        else
+        {
+          LoadState maskLoadState = mTextureCacheManager.GetTextureStateInternal(textureInfo.maskTextureId);
+          textureInfo.pixelBuffer = pixelBuffer; // Store the pixel buffer temporarily
+          if(maskLoadState == LoadState::LOADING)
+          {
+            textureInfo.loadState = LoadState::WAITING_FOR_MASK;
+          }
+          else if(maskLoadState == LoadState::LOAD_FINISHED)
+          {
+            // Send New Task to Thread
+            ApplyMask(textureInfo, textureInfo.maskTextureId);
+          }
+        }
+      }
+      else
+      {
+        UploadTexture(pixelBuffer, textureInfo);
+        NotifyObservers(textureInfo, true);
+      }
+    }
+    else
+    {
+      textureInfo.pixelBuffer = pixelBuffer; // Store the pixel data
+      textureInfo.loadState   = LoadState::LOAD_FINISHED;
+
+      if(textureInfo.storageType == StorageType::RETURN_PIXEL_BUFFER)
+      {
+        NotifyObservers(textureInfo, true);
+      }
+      else
+      {
+        // Check if there was another texture waiting for this load to complete
+        // (e.g. if this was an image mask, and its load is on a different thread)
+        CheckForWaitingTexture(textureInfo);
+      }
+    }
+  }
+  else
+  {
+    textureInfo.loadState = LoadState::LOAD_FAILED;
+    CheckForWaitingTexture(textureInfo);
+    NotifyObservers(textureInfo, false);
+  }
+}
+
+void TextureManager::CheckForWaitingTexture(TextureManager::TextureInfo& maskTextureInfo)
+{
+  // Search the cache, checking if any texture has this texture id as a
+  // maskTextureId:
+  const TextureCacheIndex size = static_cast<TextureCacheIndex>(mTextureCacheManager.size());
+
+  for(TextureCacheIndex cacheIndex = 0; cacheIndex < size; ++cacheIndex)
+  {
+    if(mTextureCacheManager[cacheIndex].maskTextureId == maskTextureInfo.textureId &&
+       mTextureCacheManager[cacheIndex].loadState == LoadState::WAITING_FOR_MASK)
+    {
+      TextureInfo& textureInfo(mTextureCacheManager[cacheIndex]);
+
+      if(maskTextureInfo.loadState == LoadState::LOAD_FINISHED)
+      {
+        // Send New Task to Thread
+        ApplyMask(textureInfo, maskTextureInfo.textureId);
+      }
+      else
+      {
+        textureInfo.pixelBuffer.Reset();
+        textureInfo.loadState = LoadState::LOAD_FAILED;
+        NotifyObservers(textureInfo, false);
+      }
+    }
+  }
+}
+
+void TextureManager::ApplyMask(TextureManager::TextureInfo& textureInfo, const TextureManager::TextureId& maskTextureId)
+{
+  TextureCacheIndex maskCacheIndex = mTextureCacheManager.GetCacheIndexFromId(maskTextureId);
+  if(maskCacheIndex != INVALID_CACHE_INDEX)
+  {
+    Devel::PixelBuffer maskPixelBuffer = mTextureCacheManager[maskCacheIndex].pixelBuffer;
+    Devel::PixelBuffer pixelBuffer     = textureInfo.pixelBuffer;
+    textureInfo.pixelBuffer.Reset();
+
+    DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureManager::ApplyMask(): url:%s sync:%s\n", textureInfo.url.GetUrl().c_str(), textureInfo.loadSynchronously ? "T" : "F");
+
+    textureInfo.loadState   = LoadState::MASK_APPLYING;
+    auto& loadersContainer  = (textureInfo.url.IsLocalResource() || textureInfo.url.IsBufferResource()) ? mAsyncLocalLoaders : mAsyncRemoteLoaders;
+    auto  loadingHelperIt   = loadersContainer.GetNext();
+    auto  premultiplyOnLoad = textureInfo.preMultiplyOnLoad ? DevelAsyncImageLoader::PreMultiplyOnLoad::ON : DevelAsyncImageLoader::PreMultiplyOnLoad::OFF;
+    DALI_ASSERT_ALWAYS(loadingHelperIt != loadersContainer.End());
+    loadingHelperIt->ApplyMask(textureInfo.textureId, pixelBuffer, maskPixelBuffer, textureInfo.scaleFactor, textureInfo.cropToMask, premultiplyOnLoad);
+  }
+}
+
+void TextureManager::UploadTexture(Devel::PixelBuffer& pixelBuffer, TextureInfo& textureInfo)
+{
+  if(textureInfo.loadState != LoadState::UPLOADED && textureInfo.useAtlas != UseAtlas::USE_ATLAS)
+  {
+    DALI_LOG_INFO(gTextureManagerLogFilter, Debug::General, "  TextureManager::UploadTexture() New Texture for textureId:%d\n", textureInfo.textureId);
+
+    // Check if this pixelBuffer is premultiplied
+    textureInfo.preMultiplied = pixelBuffer.IsAlphaPreMultiplied();
+
+    auto& renderingAddOn = RenderingAddOn::Get();
+    if(renderingAddOn.IsValid())
+    {
+      renderingAddOn.CreateGeometry(textureInfo.textureId, pixelBuffer);
+    }
+
+    Texture texture = Texture::New(Dali::TextureType::TEXTURE_2D, pixelBuffer.GetPixelFormat(), pixelBuffer.GetWidth(), pixelBuffer.GetHeight());
+
+    PixelData pixelData = Devel::PixelBuffer::Convert(pixelBuffer);
+    texture.Upload(pixelData);
+    if(!textureInfo.textureSet)
+    {
+      textureInfo.textureSet = TextureSet::New();
+    }
+    textureInfo.textureSet.SetTexture(0u, texture);
+  }
+
+  // Update the load state.
+  // Note: This is regardless of success as we care about whether a
+  // load attempt is in progress or not.  If unsuccessful, a broken
+  // image is still loaded.
+  textureInfo.loadState = LoadState::UPLOADED;
+}
+
+void TextureManager::NotifyObservers(TextureManager::TextureInfo& textureInfo, const bool& success)
+{
+  TextureId textureId = textureInfo.textureId;
+
+  // If there is an observer: Notify the load is complete, whether successful or not,
+  // and erase it from the list
+  TextureInfo* info = &textureInfo;
+
+  mQueueLoadFlag = true;
+
+  while(info->observerList.Count())
+  {
+    TextureUploadObserver* observer = info->observerList[0];
+
+    // During LoadComplete() a Control ResourceReady() signal is emitted.
+    // During that signal the app may add remove /add Textures (e.g. via
+    // ImageViews).
+    // It is possible for observers to be removed from the observer list,
+    // and it is also possible for the mTextureInfoContainer to be modified,
+    // invalidating the reference to the textureInfo struct.
+    // Texture load requests for the same URL are deferred until the end of this
+    // method.
+    DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureManager::NotifyObservers() textureId:%d url:%s loadState:%s\n", textureId, textureInfo.url.GetUrl().c_str(), GET_LOAD_STATE_STRING(textureInfo.loadState));
+
+    // It is possible for the observer to be deleted.
+    // Disconnect and remove the observer first.
+    observer->DestructionSignal().Disconnect(this, &TextureManager::ObserverDestroyed);
+
+    info->observerList.Erase(info->observerList.Begin());
+
+    if(info->storageType == StorageType::RETURN_PIXEL_BUFFER)
+    {
+      observer->LoadComplete(success, TextureUploadObserver::TextureInformation(TextureUploadObserver::ReturnType::PIXEL_BUFFER, info->pixelBuffer, info->url.GetUrl(), info->preMultiplied));
+    }
+    else
+    {
+      observer->LoadComplete(success, TextureUploadObserver::TextureInformation(TextureUploadObserver::ReturnType::TEXTURE, info->textureId, info->textureSet, (info->useAtlas == UseAtlas::USE_ATLAS) ? true : false, info->atlasRect, info->preMultiplied));
+    }
+
+    // Get the textureInfo from the container again as it may have been invalidated.
+    TextureCacheIndex textureInfoIndex = mTextureCacheManager.GetCacheIndexFromId(textureId);
+    if(textureInfoIndex == INVALID_CACHE_INDEX)
+    {
+      break; // texture has been removed - can stop.
+    }
+    info = &mTextureCacheManager[textureInfoIndex];
+  }
+
+  mQueueLoadFlag = false;
+  ProcessQueuedTextures();
+
+  if(info->storageType == StorageType::RETURN_PIXEL_BUFFER && info->observerList.Count() == 0)
+  {
+    Remove(info->textureId, nullptr);
+  }
+}
+
+void TextureManager::ObserverDestroyed(TextureUploadObserver* observer)
+{
+  const TextureCacheIndex count = static_cast<TextureCacheIndex>(mTextureCacheManager.size());
+  for(TextureCacheIndex i = 0; i < count; ++i)
+  {
+    TextureInfo& textureInfo(mTextureCacheManager[i]);
+    for(TextureInfo::ObserverListType::Iterator j = textureInfo.observerList.Begin();
+        j != textureInfo.observerList.End();)
+    {
+      if(*j == observer)
+      {
+        j = textureInfo.observerList.Erase(j);
+      }
+      else
+      {
+        ++j;
+      }
+    }
+  }
+
+  // Remove element from the LoadQueue
+  for(auto&& element : mLoadQueue)
+  {
+    if(element.mObserver == observer)
+    {
+      element.mObserver = nullptr;
+    }
+  }
+}
+
+Dali::Geometry TextureManager::GetRenderGeometry(const TextureManager::TextureId& textureId, std::uint32_t& frontElements, std::uint32_t& backElements)
+{
+  return RenderingAddOn::Get().IsValid() ? RenderingAddOn::Get().GetGeometry(textureId, frontElements, backElements) : Geometry();
+}
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/visuals/texture-manager/texture-manager-impl.h b/dali-toolkit/internal/visuals/texture-manager/texture-manager-impl.h
new file mode 100644 (file)
index 0000000..71d7aa1
--- /dev/null
@@ -0,0 +1,627 @@
+#ifndef DALI_TOOLKIT_TEXTURE_MANAGER_IMPL_H
+#define DALI_TOOLKIT_TEXTURE_MANAGER_IMPL_H
+
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/animated-image-loading.h>
+#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
+#include <dali/public-api/adaptor-framework/encoded-image-buffer.h>
+#include <dali/public-api/common/dali-vector.h>
+#include <dali/public-api/rendering/geometry.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/image-loader/image-atlas.h>
+#include <dali-toolkit/internal/helpers/round-robin-container-view.h>
+#include <dali-toolkit/internal/visuals/texture-manager/texture-cache-manager.h>
+#include <dali-toolkit/internal/visuals/texture-manager/texture-manager-type.h>
+#include <dali-toolkit/internal/visuals/texture-manager/texture-upload-observer.h>
+#include <dali-toolkit/internal/visuals/visual-url.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+class ImageAtlasManager;
+typedef IntrusivePtr<ImageAtlasManager> ImageAtlasManagerPtr;
+class TextureAsyncLoadingHelper;
+
+/**
+ * The TextureManager provides a common Image loading API for Visuals.
+ *
+ * The TextureManager is responsible for providing sync, async, atlased and non-atlased
+ * CPU time alpha masking, animated image loads.
+ *
+ * Texture caching is provided and performed by TextureCacheManager.
+ * TextureUploadObserver.LoadComplete called when async load completed.
+ */
+class TextureManager : public ConnectionTracker
+{
+public:
+  // Copy enum and types and const values that TextureManager will use.
+  using TextureId         = TextureManagerType::TextureId;
+  using TextureCacheIndex = TextureManagerType::TextureCacheIndex;
+  using TextureHash       = TextureManagerType::TextureHash;
+
+  static constexpr TextureId         INVALID_TEXTURE_ID  = TextureManagerType::INVALID_TEXTURE_ID;
+  static constexpr TextureCacheIndex INVALID_CACHE_INDEX = TextureManagerType::INVALID_CACHE_INDEX;
+
+  using UseAtlas       = TextureManagerType::UseAtlas;
+  using StorageType    = TextureManagerType::StorageType;
+  using LoadType       = TextureManagerType::LoadType;
+  using LoadState      = TextureManagerType::LoadState;
+  using ReloadPolicy   = TextureManagerType::ReloadPolicy;
+  using MultiplyOnLoad = TextureManagerType::MultiplyOnLoad;
+  using TextureInfo    = TextureManagerType::TextureInfo;
+
+public:
+  struct MaskingData
+  {
+    MaskingData();
+    ~MaskingData() = default;
+
+    VisualUrl                 mAlphaMaskUrl;
+    TextureManager::TextureId mAlphaMaskId;
+    float                     mContentScaleFactor;
+    bool                      mCropToMask;
+  };
+  using MaskingDataPointer = std::unique_ptr<MaskingData>;
+
+  /**
+   * Class to provide lifecycle event on destruction of texture manager.
+   */
+  struct LifecycleObserver
+  {
+    /**
+     * Called shortly before the texture manager is destroyed.
+     */
+    virtual void TextureManagerDestroyed() = 0;
+  };
+
+  /**
+   * Constructor.
+   */
+  TextureManager();
+
+  /**
+   * Destructor.
+   */
+  ~TextureManager() override;
+
+  // TextureManager Main API:
+
+  /**
+   * @brief Requests an frame of animated image load.
+   *
+   * The parameters are used to specify how the animated image is loaded.
+   * The observer has the LoadComplete method called when the load is ready.
+   *
+   * @param[in] animatedImageLoading  The AnimatedImageLoading that contain the animated image information
+   * @param[in] frameIndex            The frame index to load.
+   * @param[in] samplingMode          The SamplingMode to use
+   * @param[in] synchronousLoading    true if the frame should be loaded synchronously
+   * @param[out] textureId            The textureId of the frame
+   * @param[in] wrapModeU             Horizontal Wrap mode
+   * @param[in] wrapModeV             Vertical Wrap mode
+   * @param[in] textureObserver       The client object should inherit from this and provide the "UploadCompleted" virtual.
+   *                                  This is called when an image load completes (or fails).
+   *
+   * @return                          The texture set containing the frame of animated image, or empty if still loading.
+   */
+  TextureSet LoadAnimatedImageTexture(
+    Dali::AnimatedImageLoading      animatedImageLoading,
+    const std::uint32_t&            frameIndex,
+    const Dali::SamplingMode::Type& samplingMode,
+    const bool&                     synchronousLoading,
+    TextureManager::TextureId&      textureId,
+    const Dali::WrapMode::Type&     wrapModeU,
+    const Dali::WrapMode::Type&     wrapModeV,
+    TextureUploadObserver*          textureObserver);
+
+  /**
+   * @brief Requests an image load of the given URL to get PixelBuffer.
+   *
+   * The parameters are used to specify how the image is loaded.
+   * The observer has the LoadComplete method called when the load is ready.
+   *
+   * @param[in] url                   The URL of the image to load
+   * @param[in] desiredSize           The size the image is likely to appear at. This can be set to 0,0 for automatic
+   * @param[in] fittingMode           The FittingMode to use
+   * @param[in] samplingMode          The SamplingMode to use
+   * @param[in] synchronousLoading    true if the URL should be loaded synchronously
+   * @param[in] textureObserver       The client object should inherit from this and provide the "UploadCompleted" virtual.
+   *                                  This is called when an image load completes (or fails).
+   * @param[in] orientationCorrection Whether to rotate image to match embedded orientation data
+   * @param[in,out] preMultiplyOnLoad True if the image color should be multiplied by it's alpha. Set to false if the
+   *                                  image has no alpha channel
+   *
+   * @return                          The pixel buffer containing the image, or empty if still loading.
+   */
+  Devel::PixelBuffer LoadPixelBuffer(
+    const VisualUrl&                url,
+    const Dali::ImageDimensions&    desiredSize,
+    const Dali::FittingMode::Type&  fittingMode,
+    const Dali::SamplingMode::Type& samplingMode,
+    const bool&                     synchronousLoading,
+    TextureUploadObserver*          textureObserver,
+    const bool&                     orientationCorrection,
+    TextureManager::MultiplyOnLoad& preMultiplyOnLoad);
+
+  /**
+   * @brief Requests an image load of the given URL.
+   *
+   * The parameters are used to specify how the image is loaded.
+   * The observer has the LoadComplete method called when the load is ready.
+   *
+   * When the client has finished with the Texture, Remove() should be called.
+   *
+   * @param[in] url                   The URL of the image to load
+   * @param[in] desiredSize           The size the image is likely to appear at. This can be set to 0,0 for automatic
+   * @param[in] fittingMode           The FittingMode to use
+   * @param[in] samplingMode          The SamplingMode to use
+   * @param[in, out] maskInfo         Mask info structure
+   * @param[in] synchronousLoading    true if the URL should be loaded synchronously
+   * @param[out] textureId,           The textureId of the URL
+   * @param[out] textureRect          The rectangle within the texture atlas that this URL occupies,
+   *                                  this is the rectangle in normalized coordinates.
+   * @param[out] textureRectSize      The rectangle within the texture atlas that this URL occupies,
+   *                                  this is the same rectangle in pixels.
+   * @param[in,out] atlasingStatus    Set to USE_ATLAS to attempt atlasing. If atlasing fails, the image will still
+   *                                  be loaded, and marked successful, but this will be set to false.
+   *                                  If atlasing succeeds, this will be set to true.
+   * @param[out] loadingStatus        The loading status of the texture
+   * @param[in] wrapModeU             Horizontal Wrap mode
+   * @param[in] wrapModeV             Vertical Wrap mode
+   * @param[in] textureObserver       The client object should inherit from this and provide the "UploadCompleted" virtual.
+   *                                  This is called when an image load completes (or fails).
+   * @param[in] atlasObserver         This is used if the texture is atlased, and will be called instead of
+   *                                  textureObserver.UploadCompleted
+   * @param[in] imageAtlasManager     The atlas manager to use for atlasing textures
+   * @param[in] orientationCorrection Whether to rotate image to match embedded orientation data
+   * @param[in] reloadPolicy          Forces a reload of the texture even if already cached
+   * @param[in,out] preMultiplyOnLoad True if the image color should be multiplied by it's alpha. Set to false if the
+   *                                  image has no alpha channel
+   *
+   * @return                          The texture set containing the image, or empty if still loading.
+   */
+  TextureSet LoadTexture(
+    const VisualUrl&                    url,
+    const Dali::ImageDimensions&        desiredSize,
+    const Dali::FittingMode::Type&      fittingMode,
+    const Dali::SamplingMode::Type&     samplingMode,
+    MaskingDataPointer&                 maskInfo,
+    const bool&                         synchronousLoading,
+    TextureManager::TextureId&          textureId,
+    Dali::Vector4&                      textureRect,
+    Dali::ImageDimensions&              textureRectSize,
+    bool&                               atlasingStatus,
+    bool&                               loadingStatus,
+    const Dali::WrapMode::Type&         wrapModeU,
+    const Dali::WrapMode::Type&         wrapModeV,
+    TextureUploadObserver*              textureObserver,
+    AtlasUploadObserver*                atlasObserver,
+    ImageAtlasManagerPtr                imageAtlasManager,
+    const bool&                         orientationCorrection,
+    const TextureManager::ReloadPolicy& reloadPolicy,
+    TextureManager::MultiplyOnLoad&     preMultiplyOnLoad);
+
+  /**
+   * @brief Remove a Texture from the TextureManager.
+   *
+   * Textures are cached and therefore only the removal of the last
+   * occurrence of a Texture will cause its removal internally.
+   *
+   * @param[in] textureId The ID of the Texture to remove.
+   * @param[in] textureObserver The texture observer.
+   */
+  void Remove(const TextureManager::TextureId& textureId, TextureUploadObserver* textureObserver);
+
+  /**
+   * Add an observer to the object.
+   * @param[in] observer The observer to add.
+   */
+  void AddObserver(TextureManager::LifecycleObserver& observer);
+
+  /**
+   * Remove an observer from the object
+   * @pre The observer has already been added.
+   * @param[in] observer The observer to remove.
+   */
+  void RemoveObserver(TextureManager::LifecycleObserver& observer);
+
+  /**
+   * @brief Returns the geometry associated with texture.
+   * @param[in] textureId Id of the texture
+   * @param[out] frontElements number of front elements
+   * @param[out] backElements number of back elements
+   * @return Returns valid geometry object
+   */
+  Geometry GetRenderGeometry(const TextureManager::TextureId& textureId, std::uint32_t& frontElements, std::uint32_t& backElements);
+
+public:
+  // API list that need to access TextureCacheManager.
+
+  /**
+   * @copydoc TextureCacheManager::GetVisualUrl
+   */
+  inline VisualUrl GetVisualUrl(const TextureManager::TextureId& textureId)
+  {
+    return mTextureCacheManager.GetVisualUrl(textureId);
+  }
+
+  /**
+   * @copydoc TextureCacheManager::GetTextureSet
+   */
+  inline TextureSet GetTextureSet(const TextureManager::TextureId& textureId)
+  {
+    return mTextureCacheManager.GetTextureSet(textureId);
+  }
+
+  /**
+   * @copydoc TextureCacheManager::RemoveExternalTexture
+   */
+  inline TextureSet RemoveExternalTexture(const std::string& url)
+  {
+    return mTextureCacheManager.RemoveExternalTexture(url);
+  }
+
+  /**
+   * @copydoc TextureCacheManager::RemoveExternalEncodedImageBuffer
+   */
+  inline EncodedImageBuffer RemoveExternalEncodedImageBuffer(const std::string& url)
+  {
+    return mTextureCacheManager.RemoveExternalEncodedImageBuffer(url);
+  }
+
+  /**
+   * @copydoc TextureCacheManager::UseExternalResource
+   */
+  inline void UseExternalResource(const VisualUrl& url)
+  {
+    mTextureCacheManager.UseExternalResource(url);
+  }
+
+  /**
+   * @copydoc TextureCacheManager::GetEncodedImageBuffer
+   */
+  inline EncodedImageBuffer GetEncodedImageBuffer(const std::string& url)
+  {
+    return mTextureCacheManager.GetEncodedImageBuffer(url);
+  }
+
+  /**
+   * @copydoc TextureCacheManager::AddExternalTexture
+   */
+  inline std::string AddExternalTexture(const TextureSet& texture)
+  {
+    return mTextureCacheManager.AddExternalTexture(texture);
+  }
+
+  /**
+   * @copydoc TextureCacheManager::AddExternalEncodedImageBuffer
+   */
+  inline std::string AddExternalEncodedImageBuffer(const EncodedImageBuffer& encodedImageBuffer)
+  {
+    return mTextureCacheManager.AddExternalEncodedImageBuffer(encodedImageBuffer);
+  }
+
+public: // Load Request API
+  /**
+   * @brief Requests an image load of the given URL.
+   *
+   * The parameters are used to specify how the image is loaded.
+   * The observer has the LoadComplete method called when the load is ready.
+   *
+   * When the client has finished with the Texture, Remove() should be called.
+   *
+   * @param[in] url                   The URL of the image to load
+   * @param[in] desiredSize           The size the image is likely to appear at. This can be set to 0,0 for automatic
+   * @param[in] fittingMode           The FittingMode to use
+   * @param[in] samplingMode          The SamplingMode to use
+   * @param[in] useAtlasing           Set to USE_ATLAS to attempt atlasing. If atlasing fails, the image will still be loaded, and marked successful,
+   *                                  but "useAtlasing" will be set to false in the "UploadCompleted" callback from the TextureManagerUploadObserver.
+   * @param[in] observer              The client object should inherit from this and provide the "UploadCompleted" virtual.
+   *                                  This is called when an image load completes (or fails).
+   * @param[in] orientationCorrection Whether to rotate image to match embedded orientation data
+   * @param[in] reloadPolicy          Forces a reload of the texture even if already cached
+   * @param[in,out] preMultiplyOnLoad True if the image color should be multiplied by it's alpha. Set to false if the image has no alpha channel
+   * @param[in] synchronousLoading    True if the frame should be loaded synchronously. If you skip this parameter,
+   *                                  default is false.
+   * @return                          A TextureId to use as a handle to reference this Texture
+   */
+  TextureManager::TextureId RequestLoad(
+    const VisualUrl&                    url,
+    const ImageDimensions&              desiredSize,
+    const Dali::FittingMode::Type&      fittingMode,
+    const Dali::SamplingMode::Type&     samplingMode,
+    const TextureManager::UseAtlas&     useAtlasing,
+    TextureUploadObserver*              observer,
+    const bool&                         orientationCorrection,
+    const TextureManager::ReloadPolicy& reloadPolicy,
+    TextureManager::MultiplyOnLoad&     preMultiplyOnLoad,
+    const bool&                         synchronousLoading = false);
+
+  /**
+   * @brief Requests an image load of the given URL, when the texture has
+   * have loaded, it will perform a blend with the image mask, and upload
+   * the blended texture.
+   *
+   * The parameters are used to specify how the image is loaded.
+   * The observer has the LoadComplete method called when the load is ready.
+   *
+   * When the client has finished with the Texture, Remove() should be called.
+   *
+   * @param[in] url                   The URL of the image to load
+   * @param[in] maskTextureId         The texture id of an image to mask this with
+   *                                  (can be INVALID if no masking required)
+   * @param[in] contentScale          The scale factor to apply to the image before masking
+   * @param[in] desiredSize           The size the image is likely to appear at. This can be set to 0,0 for automatic
+   * @param[in] fittingMode           The FittingMode to use
+   * @param[in] samplingMode          The SamplingMode to use
+   * @param[in] useAtlasing           Set to USE_ATLAS to attempt atlasing. If atlasing fails, the image will still
+   *                                  be loaded, and marked successful,
+   *                                  but "useAtlasing" will be set to false in the "UploadCompleted" callback from
+   *                                  the TextureManagerUploadObserver.
+   * @param[in] cropToMask            Only used with masking, this will crop the scaled image to the mask size.
+   *                                  If false, then the mask will be scaled to fit the image before being applied.
+   * @param[in] observer              The client object should inherit from this and provide the "UploadCompleted"
+   *                                  virtual.
+   *                                  This is called when an image load completes (or fails).
+   * @param[in] orientationCorrection Whether to rotate image to match embedded orientation data
+   * @param[in] reloadPolicy          Forces a reload of the texture even if already cached
+   * @param[in,out] preMultiplyOnLoad True if the image color should be multiplied by it's alpha. Set to false if the
+   *                                  image has no alpha channel
+   * @param[in] synchronousLoading    True if the frame should be loaded synchronously. If you skip this parameter,
+   *                                  default is false.
+   * @return                          A TextureId to use as a handle to reference this Texture
+   */
+  TextureManager::TextureId RequestLoad(
+    const VisualUrl&                    url,
+    const TextureManager::TextureId&    maskTextureId,
+    const float&                        contentScale,
+    const ImageDimensions&              desiredSize,
+    const Dali::FittingMode::Type&      fittingMode,
+    const Dali::SamplingMode::Type&     samplingMode,
+    const TextureManager::UseAtlas&     useAtlasing,
+    const bool&                         cropToMask,
+    TextureUploadObserver*              observer,
+    const bool&                         orientationCorrection,
+    const TextureManager::ReloadPolicy& reloadPolicy,
+    TextureManager::MultiplyOnLoad&     preMultiplyOnLoad,
+    const bool&                         synchronousLoading = false);
+
+  /**
+   * @brief Requests a masking image to be loaded. This mask is not uploaded to GL,
+   * instead, it is stored in CPU memory, and can be used for CPU blending.
+   * @param[in] maskUrl            The URL of the mask image to load
+   * @param[in] synchronousLoading True if the frame should be loaded synchronously. If you skip this parameter,
+   *                               default is false.
+   * @return                       A TextureId to use as a handle to reference this mask Texture
+   */
+  TextureManager::TextureId RequestMaskLoad(
+    const VisualUrl& maskUrl,
+    const bool&      synchronousLoading = false);
+
+private:
+  /**
+   * @brief Requests an image load of the given URL, when the texture has
+   * have loaded, if there is a valid maskTextureId, it will perform a
+   * CPU blend with the mask, and upload the blend texture.
+   *
+   * The parameters are used to specify how the image is loaded.
+   * The observer has the LoadComplete method called when the load is ready.
+   *
+   * When the client has finished with the Texture, Remove() should be called.
+   *
+   * @param[in] url                   The URL of the image to load
+   * @param[in] maskTextureId         The texture id of an image to use as a mask. If no mask is required, then set
+   *                                  to INVALID_TEXTURE_ID
+   * @param[in] contentScale          The scaling factor to apply to the content when masking
+   * @param[in] desiredSize           The size the image is likely to appear at. This can be set to 0,0 for automatic
+   * @param[in] fittingMode           The FittingMode to use
+   * @param[in] samplingMode          The SamplingMode to use
+   * @param[in] useAtlasing           Set to USE_ATLAS to attempt atlasing. If atlasing fails, the image will still be
+   *                                  loaded, and marked successful, but "useAtlasing" will be set to false in the
+   *                                  "UploadCompleted" callback from the TextureManagerUploadObserver.
+   * @param[in] cropToMask            Whether to crop the target after masking, or scale the mask to the image before
+   *                                  masking.
+   * @param[in] storageType,          Whether the pixel data is stored in the cache or uploaded to the GPU
+   * @param[in] observer              The client object should inherit from this and provide the "UploadCompleted"
+   *                                  virtual.
+   *                                  This is called when an image load completes (or fails).
+   * @param[in] orientationCorrection Whether to rotate image to match embedded orientation data
+   * @param[in] reloadPolicy          Forces a reload of the texture even if already cached
+   * @param[in,out] preMultiplyOnLoad True if the image color should be multiplied by it's alpha. Set to false if
+   *                                  there is no alpha
+   * @param[in] animatedImageLoading  The AnimatedImageLoading to load animated image
+   * @param[in] frameIndex            The frame index of a frame to be loaded frame
+   * @param[in] synchronousLoading    True if the frame should be loaded synchronously. If you skip this parameter,
+   *                                  default is false.
+   * @return                          A TextureId to use as a handle to reference this Texture
+   */
+  TextureManager::TextureId RequestLoadInternal(
+    const VisualUrl&                    url,
+    const TextureManager::TextureId&    maskTextureId,
+    const float&                        contentScale,
+    const Dali::ImageDimensions&        desiredSize,
+    const Dali::FittingMode::Type&      fittingMode,
+    const Dali::SamplingMode::Type&     samplingMode,
+    const TextureManager::UseAtlas&     useAtlas,
+    const bool&                         cropToMask,
+    const TextureManager::StorageType&  storageType,
+    TextureUploadObserver*              observer,
+    const bool&                         orientationCorrection,
+    const TextureManager::ReloadPolicy& reloadPolicy,
+    TextureManager::MultiplyOnLoad&     preMultiplyOnLoad,
+    Dali::AnimatedImageLoading          animatedImageLoading,
+    const std::uint32_t&                frameIndex,
+    const bool&                         synchronousLoading);
+
+  /**
+   * @brief Load a new image synchronously.
+   * @param[in] url                   The URL of the image to load
+   * @param[in] desiredSize           The size the image is likely to appear at.
+   *                                  This can be set to 0,0 for automatic
+   * @param[in] fittingMode           The FittingMode to use
+   * @param[in] samplingMode          The SamplingMode to use
+   * @param[in] orientationCorrection Whether to use image metadata to rotate or flip the image,
+   *                                  e.g., from portrait to landscape
+   * @return PixelBuffer of loaded image.
+   */
+  Devel::PixelBuffer LoadImageSynchronously(
+    const VisualUrl&                url,
+    const Dali::ImageDimensions&    desiredSize,
+    const Dali::FittingMode::Type&  fittingMode,
+    const Dali::SamplingMode::Type& samplingMode,
+    const bool&                     orientationCorrection);
+
+private:
+  // Load and queue
+
+  /**
+   * Structure to hold info about a texture load queued during NotifyObservers
+   */
+  struct LoadQueueElement
+  {
+    LoadQueueElement(TextureManager::TextureId textureId, TextureUploadObserver* observer)
+    : mTextureId(textureId),
+      mObserver(observer)
+    {
+    }
+
+    TextureManager::TextureId mTextureId; ///< The texture id of the requested load.
+    TextureUploadObserver*    mObserver;  ///< Observer of texture load.
+  };
+
+  /**
+   * @brief Initiate a load or queue load if NotifyObservers is invoking callbacks
+   * @param[in] textureInfo The TextureInfo struct associated with the Texture
+   * @param[in] observer The observer wishing to observe the texture upload
+   */
+  void LoadOrQueueTexture(TextureManager::TextureInfo& textureInfo, TextureUploadObserver* observer);
+
+  /**
+   * @brief Queue a texture load to be subsequently handled by ProcessQueuedTextures.
+   * @param[in] textureInfo The TextureInfo struct associated with the Texture
+   * @param[in] observer The observer wishing to observe the texture upload
+   */
+  void QueueLoadTexture(const TextureManager::TextureInfo& textureInfo, TextureUploadObserver* observer);
+
+  /**
+   * @brief Used internally to initiate a load.
+   * @param[in] textureInfo The TextureInfo struct associated with the Texture
+   * @param[in] observer The observer wishing to observe the texture upload
+   */
+  void LoadTexture(TextureManager::TextureInfo& textureInfo, TextureUploadObserver* observer);
+
+  /**
+   * @brief Initiate load of textures queued whilst NotifyObservers invoking callbacks.
+   */
+  void ProcessQueuedTextures();
+
+  /**
+   * Add the observer to the observer list
+   * @param[in] textureInfo The TextureInfo struct associated with the texture
+   * @param[in] observer The observer wishing to observe the texture upload
+   */
+  void ObserveTexture(TextureManager::TextureInfo& textureInfo, TextureUploadObserver* observer);
+
+  /**
+   * @brief Performs Post-Load steps including atlasing.
+   * @param[in] textureInfo The struct associated with this Texture
+   * @param[in] pixelBuffer The image pixelBuffer
+   * @return    True if successful
+   */
+  void PostLoad(TextureManager::TextureInfo& textureInfo, Devel::PixelBuffer& pixelBuffer);
+
+  /**
+   * Check if there is a texture waiting to be masked. If there
+   * is then apply this mask and upload it.
+   * @param[in] maskTextureInfo The texture info of the mask that has just loaded.
+   */
+  void CheckForWaitingTexture(TextureManager::TextureInfo& maskTextureInfo);
+
+  /**
+   * Apply the mask to the pixelBuffer.
+   * @param[in] textureInfo The information of texture to apply the mask to
+   * @param[in] maskTextureId The texture id of the mask.
+   */
+  void ApplyMask(TextureManager::TextureInfo& textureInfo, const TextureManager::TextureId& maskTextureId);
+
+  /**
+   * Upload the texture specified in pixelBuffer to the appropriate location
+   * @param[in] pixelBuffer The image data to upload
+   * @param[in] textureInfo The texture info containing the location to
+   * store the data to.
+   */
+  void UploadTexture(Devel::PixelBuffer& pixelBuffer, TextureManager::TextureInfo& textureInfo);
+
+  /**
+   * Notify the current observers that the texture upload is complete,
+   * then remove the observers from the list.
+   * @param[in] textureInfo The struct associated with this Texture
+   * @param[in] success If the pixel data was retrieved successfully and uploaded to GPU
+   */
+  void NotifyObservers(TextureManager::TextureInfo& textureInfo, const bool& success);
+
+public:
+  /**
+   * @brief Common method to handle loading completion.
+   * TextureAsyncLoadingHelper will call this API After async loading finished.
+   * @param[in] textureId   The ID of the texture load complete.
+   * @param[in] pixelBuffer The loaded image data
+   */
+  void AsyncLoadComplete(const TextureManager::TextureId& textureId, Devel::PixelBuffer pixelBuffer);
+
+private:
+  /**
+   * Deleted copy constructor.
+   */
+  TextureManager(const TextureManager&) = delete;
+
+  /**
+   * Deleted assignment operator.
+   */
+  TextureManager& operator=(const TextureManager& rhs) = delete;
+
+  /**
+   * This is called by the TextureManagerUploadObserver when an observer is destroyed.
+   * We use the callback to know when to remove an observer from our notify list.
+   * @param[in] observer The observer that generated the callback
+   */
+  void ObserverDestroyed(TextureUploadObserver* observer);
+
+private:                                    // Member Variables:
+  TextureCacheManager mTextureCacheManager; ///< Manager the life-cycle and caching of Textures
+
+  RoundRobinContainerView<TextureAsyncLoadingHelper> mAsyncLocalLoaders;  ///< The Asynchronous image loaders used to provide all local async loads
+  RoundRobinContainerView<TextureAsyncLoadingHelper> mAsyncRemoteLoaders; ///< The Asynchronous image loaders used to provide all remote async loads
+
+  Dali::Vector<LifecycleObserver*> mLifecycleObservers; ///< Lifecycle observers of texture manager
+  Dali::Vector<LoadQueueElement>   mLoadQueue;          ///< Queue of textures to load after NotifyObservers
+  bool                             mQueueLoadFlag;      ///< Flag that causes Load Textures to be queued.
+};
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXTURE_MANAGER_IMPL_H
diff --git a/dali-toolkit/internal/visuals/texture-manager/texture-manager-type.h b/dali-toolkit/internal/visuals/texture-manager/texture-manager-type.h
new file mode 100644 (file)
index 0000000..a8349e2
--- /dev/null
@@ -0,0 +1,204 @@
+#ifndef DALI_TOOLKIT_TEXTURE_MANAGER_TYPE_H
+#define DALI_TOOLKIT_TEXTURE_MANAGER_TYPE_H
+
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/animated-image-loading.h>
+#include <dali/public-api/common/dali-vector.h>
+#include <dali/public-api/math/vector4.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/image-loader/image-atlas.h>
+#include <dali-toolkit/internal/visuals/texture-manager/texture-upload-observer.h>
+#include <dali-toolkit/internal/visuals/visual-url.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+/**
+ * @brief Define common type, enum, and struct that texture-manager-impl and texture-cache-manager will use.
+ */
+namespace TextureManagerType
+{
+// Typedef:
+
+typedef std::int32_t TextureId;         ///< The TextureId type. This is used as a handle to refer to a particular Texture.
+typedef std::int32_t TextureCacheIndex; ///< The TextureCacheIndex type. This is used as a handles to refer to a particular Texture in TextureCacheManager.
+typedef std::size_t  TextureHash;       ///< The type used to store the hash used for Texture caching.
+
+// Constant values:
+
+static constexpr TextureId         INVALID_TEXTURE_ID  = -1; ///< Used to represent a null TextureId or error
+static constexpr TextureCacheIndex INVALID_CACHE_INDEX = -1; ///< Used to represent a null TextureCacheIndex or error
+
+// Enum classes:
+
+/**
+ * Whether the texture should be atlased or uploaded into it's own GPU texture
+ */
+enum class UseAtlas
+{
+  NO_ATLAS,
+  USE_ATLAS
+};
+
+/**
+ * Whether the pixel data should be kept in TextureManager, returned with pixelBuffer or uploaded for rendering
+ */
+enum class StorageType
+{
+  KEEP_PIXEL_BUFFER,   ///< Keep loaded pixel buffer inside of texture manager without making texture. This could be used for inside pixel process like mask image.
+  RETURN_PIXEL_BUFFER, ///< Return loaded pixel buffer without making texture.
+                       ///  Because a pixel buffer cannot be used multiple texture, this pixel buffer only cached during loading, and is removed after loading is finished.
+  UPLOAD_TO_TEXTURE    ///< Loaded image will be uploaded to texture and the texture will be returned.
+};
+
+/**
+ * Whether the texture should be loaded synchronously or asynchronously.
+ */
+enum class LoadType
+{
+  LOAD_ASYNCHRONOUSLY,
+  LOAD_SYNCHRONOUSLY
+};
+
+/**
+ * @brief The LoadState Enumeration represents the current state of a particular Texture's life-cycle.
+ */
+enum class LoadState
+{
+  NOT_STARTED,      ///< Default
+  LOADING,          ///< Loading has been started, but not finished.
+  LOAD_FINISHED,    ///< Loading has finished. (for CPU storage only)
+  WAITING_FOR_MASK, ///< Loading has finished, but waiting for mask image
+  MASK_APPLYING,    ///< Loading has finished, Mask is applying
+  MASK_APPLIED,     ///< Loading has finished, Mask is applyied by GPU
+  UPLOADED,         ///< Uploaded and ready. (For GPU upload only)
+  CANCELLED,        ///< Removed before loading completed
+  LOAD_FAILED       ///< Async loading failed, e.g. connection problem
+};
+
+/**
+ * @brief Types of reloading policies
+ */
+enum class ReloadPolicy
+{
+  CACHED = 0, ///< Loads cached texture if it exists.
+  FORCED      ///< Forces reloading of texture.
+};
+
+/**
+ * @brief Whether to multiply alpha into color channels on load
+ */
+enum class MultiplyOnLoad
+{
+  LOAD_WITHOUT_MULTIPLY = 0, ///< Don't modify the image
+  MULTIPLY_ON_LOAD           ///< Multiply alpha into color channels on load
+};
+
+// Structs:
+
+/**
+ * @brief This struct is used to manage the life-cycle of Texture loading and caching.
+ */
+struct TextureInfo
+{
+  TextureInfo(const TextureId&                  textureId,
+              const TextureId&                  maskTextureId,
+              const VisualUrl&                  url,
+              const Dali::ImageDimensions&      desiredSize,
+              const float&                      scaleFactor,
+              const Dali::FittingMode::Type&    fittingMode,
+              const Dali::SamplingMode::Type&   samplingMode,
+              const bool&                       loadSynchronously,
+              const bool&                       cropToMask,
+              const UseAtlas&                   useAtlas,
+              const TextureHash&                hash,
+              const bool&                       orientationCorrection,
+              const bool&                       preMultiplyOnLoad,
+              const Dali::AnimatedImageLoading& animatedImageLoading,
+              const std::uint32_t&              frameIndex)
+  : url(url),
+    desiredSize(desiredSize),
+    useSize(desiredSize),
+    atlasRect(0.0f, 0.0f, 1.0f, 1.0f), // Full atlas rectangle
+    textureId(textureId),
+    maskTextureId(maskTextureId),
+    hash(hash),
+    scaleFactor(scaleFactor),
+    referenceCount(1u),
+    loadState(LoadState::NOT_STARTED),
+    fittingMode(fittingMode),
+    samplingMode(samplingMode),
+    storageType(StorageType::UPLOAD_TO_TEXTURE),
+    animatedImageLoading(animatedImageLoading),
+    frameIndex(frameIndex),
+    loadSynchronously(loadSynchronously),
+    useAtlas(useAtlas),
+    cropToMask(cropToMask),
+    orientationCorrection(true),
+    preMultiplyOnLoad(preMultiplyOnLoad),
+    preMultiplied(false)
+  {
+  }
+
+  /**
+   * Container type used to store all observer clients of this Texture
+   */
+  typedef Dali::Vector<TextureUploadObserver*> ObserverListType;
+
+  ObserverListType           observerList;          ///< Container used to store all observer clients of this Texture
+  Dali::Toolkit::ImageAtlas  atlas;                 ///< The atlas this Texture lays within (if any)
+  Dali::Devel::PixelBuffer   pixelBuffer;           ///< The PixelBuffer holding the image data (May be empty after upload)
+  Dali::TextureSet           textureSet;            ///< The TextureSet holding the Texture
+  VisualUrl                  url;                   ///< The URL of the image
+  Dali::ImageDimensions      desiredSize;           ///< The size requested
+  Dali::ImageDimensions      useSize;               ///< The size used
+  Dali::Vector4              atlasRect;             ///< The atlas rect used if atlased
+  TextureId                  textureId;             ///< The TextureId associated with this Texture
+  TextureId                  maskTextureId;         ///< The mask TextureId to be applied on load
+  TextureHash                hash;                  ///< The hash used to cache this Texture
+  float                      scaleFactor;           ///< The scale factor to apply to the Texture when masking
+  std::int16_t               referenceCount;        ///< The reference count of clients using this Texture
+  LoadState                  loadState;             ///< The load state showing the load progress of the Texture
+  Dali::FittingMode::Type    fittingMode : 3;       ///< The requested FittingMode
+  Dali::SamplingMode::Type   samplingMode : 3;      ///< The requested SamplingMode
+  StorageType                storageType;           ///< CPU storage / GPU upload;
+  Dali::AnimatedImageLoading animatedImageLoading;  ///< AnimatedImageLoading that contains animated image information.
+  std::uint32_t              frameIndex;            ///< frame index that be loaded, in case of animated image
+  bool                       loadSynchronously : 1; ///< True if synchronous loading was requested
+  UseAtlas                   useAtlas;              ///< USE_ATLAS if an atlas was requested.
+                                                    ///< This is updated to false if atlas is not used
+  bool cropToMask : 1;                              ///< true if the image should be cropped to the mask size.
+  bool orientationCorrection : 1;                   ///< true if the image should be rotated to match exif orientation data
+  bool preMultiplyOnLoad : 1;                       ///< true if the image's color should be multiplied by it's alpha
+  bool preMultiplied : 1;                           ///< true if the image's color was multiplied by it's alpha
+};
+
+} // namespace TextureManagerType
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_TEXTURE_MANAGER_TYPE_H
@@ -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.
@@ -19,7 +19,7 @@
 #include "texture-upload-observer.h"
 
 // INTERNAL INCLUDES
-#include <dali-toolkit/internal/visuals/texture-manager-impl.h>
+#include <dali-toolkit/internal/visuals/texture-manager/texture-manager-type.h> // for INVALUD_TEXTURE_ID
 
 namespace Dali
 {
@@ -39,7 +39,7 @@ TextureUploadObserver::TextureInformation::TextureInformation(ReturnType returnT
 
 TextureUploadObserver::TextureInformation::TextureInformation(ReturnType returnType, Devel::PixelBuffer pixelBuffer, const std::string& url, bool preMultiplied)
 : returnType(returnType),
-  textureId(Internal::TextureManager::INVALID_TEXTURE_ID),
+  textureId(Internal::TextureManagerType::INVALID_TEXTURE_ID),
   textureSet(),
   useAtlasing(false),
   atlasRect(Vector4::ZERO),
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_INTERNAL_TEXTURE_UPLOAD_OBSERVER_H
 
 /*
- * 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.
index b19bad4..c02dca4 100644 (file)
@@ -27,7 +27,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/visuals/npatch-loader.h>
 #include <dali-toolkit/internal/visuals/svg/svg-rasterize-thread.h>
-#include <dali-toolkit/internal/visuals/texture-manager-impl.h>
+#include <dali-toolkit/internal/visuals/texture-manager/texture-manager-impl.h>
 #include <dali/devel-api/rendering/renderer-devel.h>
 
 namespace Dali