Merge "Remove mask internally in texture manager" into devel/master
authorsunghyun kim <scholb.kim@samsung.com>
Thu, 8 Sep 2022 04:45:58 +0000 (04:45 +0000)
committerGerrit Code Review <gerrit@review>
Thu, 8 Sep 2022 04:45:58 +0000 (04:45 +0000)
1  2 
automated-tests/src/dali-toolkit-internal/utc-Dali-TextureManager.cpp
dali-toolkit/internal/texture-manager/texture-cache-manager.cpp
dali-toolkit/internal/texture-manager/texture-cache-manager.h
dali-toolkit/internal/texture-manager/texture-manager-impl.cpp
dali-toolkit/internal/texture-manager/texture-manager-impl.h
dali-toolkit/internal/visuals/animated-image/fixed-image-cache.cpp
dali-toolkit/internal/visuals/animated-image/rolling-animated-image-cache.cpp
dali-toolkit/internal/visuals/animated-image/rolling-image-cache.cpp
dali-toolkit/internal/visuals/image/image-visual.cpp

@@@ -599,6 -599,8 +599,6 @@@ int UtcTextureManagerUseInvalidMask(voi
      atlasRectSize,
      atlasingStatus,
      loadingStatus,
 -    WrapMode::DEFAULT,
 -    WrapMode::DEFAULT,
      &observer,
      atlasUploadObserver,
      atlasManager,
@@@ -664,6 -666,8 +664,6 @@@ int UtcTextureManagerUseInvalidMaskAndM
      atlasRectSize,
      atlasingStatus,
      loadingStatus,
 -    WrapMode::DEFAULT,
 -    WrapMode::DEFAULT,
      &observer,
      atlasUploadObserver,
      atlasManager,
@@@ -729,6 -733,8 +729,6 @@@ int UtcTextureManagerUseInvalidMaskAndM
      atlasRectSize,
      atlasingStatus,
      loadingStatus,
 -    WrapMode::DEFAULT,
 -    WrapMode::DEFAULT,
      &observer,
      atlasUploadObserver,
      atlasManager,
@@@ -814,6 -820,8 +814,6 @@@ int UtcTextureManagerSynchronousLoading
      atlasRectSize,
      atlasingStatus,
      loadingStatus,
 -    WrapMode::DEFAULT,
 -    WrapMode::DEFAULT,
      &observer,
      atlasUploadObserver,
      atlasManager,
@@@ -868,6 -876,8 +868,6 @@@ int UtcTextureManagerCachingSynchronous
      atlasRectSize,
      atlasingStatus,
      loadingStatus,
 -    WrapMode::DEFAULT,
 -    WrapMode::DEFAULT,
      &observer,
      atlasUploadObserver,
      atlasManager,
      atlasRectSize,
      atlasingStatus,
      loadingStatus,
 -    WrapMode::DEFAULT,
 -    WrapMode::DEFAULT,
      &asyncObserver,
      atlasUploadObserver,
      atlasManager,
@@@ -956,6 -968,8 +956,6 @@@ int UtcTextureManagerAsyncSyncAsync(voi
      atlasRectSize,
      atlasingStatus,
      asyncLoadingStatus1,
 -    WrapMode::DEFAULT,
 -    WrapMode::DEFAULT,
      &asyncObserver1,
      atlasUploadObserver,
      atlasManager,
      atlasRectSize,
      atlasingStatus,
      syncLoadingStatus,
 -    WrapMode::DEFAULT,
 -    WrapMode::DEFAULT,
      &syncObserver,
      atlasUploadObserver,
      atlasManager,
      atlasRectSize,
      atlasingStatus,
      asyncLoadingStatus2,
 -    WrapMode::DEFAULT,
 -    WrapMode::DEFAULT,
      &asyncObserver2,
      atlasUploadObserver,
      atlasManager,
  
    DALI_TEST_EQUALS(asyncLoadingStatus2, false, TEST_LOCATION); // texture is loaded by previous sync request
    DALI_TEST_CHECK(asyncTextureSet2);                           // texture is loaded
 -  DALI_TEST_CHECK(asyncTextureSet2 == syncTextureSet);         // check loaded two texture is same.
 +  Texture syncTexture   = syncTextureSet.GetTexture(0u);
 +  Texture asyncTexture2 = asyncTextureSet2.GetTexture(0u);
 +  DALI_TEST_CHECK(syncTexture);
 +  DALI_TEST_CHECK(asyncTexture2);
 +  DALI_TEST_CHECK(asyncTexture2 == syncTexture);               // check loaded two texture is same.
  
    // observer is called synchronously because the texture is cached.
    DALI_TEST_EQUALS(asyncObserver2.mLoaded, true, TEST_LOCATION);
    DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
    DALI_TEST_EQUALS(asyncObserver1.mLoaded, true, TEST_LOCATION);
    DALI_TEST_EQUALS(asyncObserver1.mObserverCalled, true, TEST_LOCATION);
 -  DALI_TEST_CHECK(asyncObserver1.mTextureSet == asyncTextureSet2); // check loaded two texture is same.
 +  DALI_TEST_CHECK(asyncObserver1.mTextureSet);
 +
 +  Texture observerTexture = asyncObserver1.mTextureSet.GetTexture(0u);
 +  DALI_TEST_CHECK(observerTexture == asyncTexture2); // check loaded two texture is same.
  
    // asyncObserver2 was already called so it isn't called here.
    DALI_TEST_EQUALS(asyncObserver2.mLoaded, false, TEST_LOCATION);
@@@ -1154,6 -1165,8 +1154,6 @@@ int UtcTextureManagerRemoveDuringApplyM
      atlasRectSize,
      atlasingStatus,
      loadingStatus,
 -    WrapMode::DEFAULT,
 -    WrapMode::DEFAULT,
      &observer1,
      atlasUploadObserver,
      atlasManager,
  
    tet_printf("textureId1:%d removed and textureId2:%d requested\n", static_cast<int>(textureId1), static_cast<int>(textureId2));
  
-   // ApplyMask event come back, and do nothing.
-   // CAPTION : HARD-CODING.
-   {
-     std::vector<Devel::PixelBuffer> pixelBuffers;
-     textureManager.AsyncLoadComplete(textureId1, pixelBuffers);
-     textureManager.Remove(maskInfo->mAlphaMaskId, nullptr);
-   }
-   application.SendNotification();
-   application.Render();
-   DALI_TEST_EQUALS(observer1.mLoaded, false, TEST_LOCATION);
-   DALI_TEST_EQUALS(observer1.mObserverCalled, false, TEST_LOCATION);
-   DALI_TEST_EQUALS(observer2.mLoaded, false, TEST_LOCATION);
-   DALI_TEST_EQUALS(observer2.mObserverCalled, false, TEST_LOCATION);
    // CAPTION : HARD-CODING.
    {
      std::vector<Devel::PixelBuffer> pixelBuffers;
@@@ -167,20 -167,22 +167,20 @@@ TextureCacheManager::LoadState TextureC
    return loadState;
  }
  
 -TextureSet TextureCacheManager::GetTextureSet(const TextureCacheManager::TextureId& textureId)
 +Texture TextureCacheManager::GetTexture(const TextureCacheManager::TextureId& textureId, uint32_t textureIndex)
  {
 -  TextureSet        textureSet; // empty handle
 -  TextureCacheIndex cacheIndex = static_cast<TextureCacheIndex>(mTextureIdConverter[static_cast<std::uint32_t>(textureId)]);
 +  Texture        texture; // empty handle
 +  TextureCacheIndex cacheIndex = GetCacheIndexFromId(textureId);
  
    switch(static_cast<TextureCacheIndexType>(cacheIndex.detailValue.type))
    {
      case TextureCacheIndexType::TEXTURE_CACHE_INDEX_TYPE_LOCAL:
      {
        TextureInfo& cachedTextureInfo(mTextureInfoContainer[cacheIndex.GetIndex()]);
 -      textureSet = cachedTextureInfo.textureSet;
 -      break;
 -    }
 -    case TextureCacheIndexType::TEXTURE_CACHE_INDEX_TYPE_TEXTURE:
 -    {
 -      textureSet = mExternalTextures[cacheIndex.GetIndex()].textureSet;
 +      if(textureIndex < static_cast<uint32_t>(cachedTextureInfo.textures.size()))
 +      {
 +        texture = cachedTextureInfo.textures[textureIndex];
 +      }
        break;
      }
      default:
      }
    }
  
 -  return textureSet;
 +  return texture;
  }
  
  TextureSet TextureCacheManager::GetExternalTextureSet(const TextureCacheManager::TextureId& textureId)
@@@ -643,61 -645,55 +643,55 @@@ TextureCacheManager::TextureCacheIndex 
    return cacheIndex;
  }
  
- void TextureCacheManager::RemoveCache(const TextureCacheManager::TextureId& textureId)
+ void TextureCacheManager::RemoveCache(TextureCacheManager::TextureInfo& textureInfo)
  {
-   TextureCacheIndex textureInfoIndex = GetCacheIndexFromId(textureId);
+   TextureCacheIndex textureInfoIndex = GetCacheIndexFromId(textureInfo.textureId);
    bool removeTextureInfo = false;
  
-   if(textureInfoIndex != INVALID_CACHE_INDEX)
-   {
-     TextureInfo& textureInfo(mTextureInfoContainer[textureInfoIndex.GetIndex()]);
+   DALI_LOG_INFO(gTextureManagerLogFilter, Debug::Concise, "TextureCacheManager::Remove(textureId:%d) url:%s\n  cacheIdx:%d loadState:%s reference count = %d\n", textureInfo.textureId, textureInfo.url.GetUrl().c_str(), textureInfoIndex.GetIndex(), GET_LOAD_STATE_STRING(textureInfo.loadState), textureInfo.referenceCount);
  
-     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.GetIndex(), 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;
  
-     // Decrement the reference count and check if this is the last user of this Texture.
-     if(--textureInfo.referenceCount <= 0)
+     // If loaded, we can remove the TextureInfo and the Atlas (if atlased).
+     if(textureInfo.loadState == LoadState::UPLOADED)
      {
-       // This is the last remove for this Texture.
-       textureInfo.referenceCount = 0;
-       // 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 || textureInfo.loadState == LoadState::MASK_APPLYING)
-       {
-         // We mark the textureInfo for removal.
-         // Once the load has completed, this method will be called again.
-         textureInfo.loadState = LoadState::CANCELLED;
-       }
-       else
+       if(textureInfo.atlas)
        {
-         // In other states, we are not waiting for a load so we are safe to remove the TextureInfo data.
-         removeTextureInfo = true;
+         textureInfo.atlas.Remove(textureInfo.atlasRect);
        }
+       removeTextureInfo = true;
+     }
+     else if(textureInfo.loadState == LoadState::LOADING || textureInfo.loadState == LoadState::MASK_APPLYING)
+     {
+       // 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 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())
        {
-         // If url location is BUFFER, decrease reference count of EncodedImageBuffer.
-         if(textureInfo.url.IsBufferResource())
-         {
-           RemoveEncodedImageBuffer(textureInfo.url.GetUrl());
-         }
+         RemoveEncodedImageBuffer(textureInfo.url.GetUrl());
+       }
  
-         // Permanently remove the textureInfo struct.
+       // Permanently remove the textureInfo struct.
  
-         // Step 1. remove current textureId information in mTextureHashContainer.
-         RemoveHashId(textureInfo.hash, textureId);
-         // Step 2. make textureId is not using anymore. After this job, we can reuse textureId.
-         mTextureIdConverter.Remove(textureId);
-       }
+       // Step 1. remove current textureId information in mTextureHashContainer.
+       RemoveHashId(textureInfo.hash, textureInfo.textureId);
+       // Step 2. make textureId is not using anymore. After this job, we can reuse textureId.
+       mTextureIdConverter.Remove(textureInfo.textureId);
      }
    }
  
@@@ -102,7 -102,7 +102,7 @@@ public
    /**
     * @brief Get the current state of a texture
     * @note This API doesn't consider encodedimagebuffer.
 -   * @param[in] textureId The texture id to query
 +   * @param[in] textureId The texture id to query.defaul value is 0.
     * @return The loading state if the texture is valid, or NOT_STARTED if the textureId
     * is not valid.
     */
    /**
     * @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
 +   * @param[in] textureIndex The texture index to query
 +   * @return the associated texture, or an empty handle if textureId is not valid
     */
 -  TextureSet GetTextureSet(const TextureCacheManager::TextureId& textureId);
 +  Texture GetTexture(const TextureCacheManager::TextureId& textureId, uint32_t textureIndex = 0);
  
    /**
     * @brief Get the external texture set if the texture id is valid
@@@ -270,9 -269,9 +270,9 @@@ public
     * 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.
+    * @param[in] textureInfo TextureInfo that want to cache in container.
     */
-   void RemoveCache(const TextureCacheManager::TextureId& textureId);
+   void RemoveCache(TextureCacheManager::TextureInfo& textureInfo);
  
  public:
    /**
@@@ -37,9 -37,6 +37,9 @@@ constexpr auto INITIAL_HASH_NUMBE
  constexpr auto DEFAULT_NUMBER_OF_LOCAL_LOADER_THREADS  = size_t{4u};
  constexpr auto DEFAULT_NUMBER_OF_REMOTE_LOADER_THREADS = size_t{8u};
  
 +constexpr auto TEXTURE_INDEX       = 0u; ///< The Index for texture
 +constexpr auto MASK_TEXTURE_INDEX  = 1u; ///< The Index for mask texture
 +
  constexpr auto NUMBER_OF_LOCAL_LOADER_THREADS_ENV  = "DALI_TEXTURE_LOCAL_THREADS";
  constexpr auto NUMBER_OF_REMOTE_LOADER_THREADS_ENV = "DALI_TEXTURE_REMOTE_THREADS";
  constexpr auto LOAD_IMAGE_YUV_PLANES_ENV           = "DALI_LOAD_IMAGE_YUV_PLANES";
@@@ -136,7 -133,7 +136,7 @@@ TextureManager::TextureManager(
    mLifecycleObservers(),
    mLoadQueue(),
    mRemoveQueue(),
-   mQueueLoadFlag(false),
+   mLoadingQueueTextureId(INVALID_TEXTURE_ID),
    mLoadYuvPlanes(NeedToLoadYuvPlanes())
  {
    // Initialize the AddOn
@@@ -158,6 -155,8 +158,6 @@@ TextureSet TextureManager::LoadAnimated
    TextureManager::TextureId&      textureId,
    MaskingDataPointer&             maskInfo,
    const Dali::SamplingMode::Type& samplingMode,
 -  const Dali::WrapMode::Type&     wrapModeU,
 -  const Dali::WrapMode::Type&     wrapModeV,
    const bool&                     synchronousLoading,
    TextureUploadObserver*          textureObserver,
    TextureManager::MultiplyOnLoad& preMultiplyOnLoad)
          Texture texture = Texture::New(Dali::TextureType::TEXTURE_2D, pixelData.GetPixelFormat(), pixelData.GetWidth(), pixelData.GetHeight());
          texture.Upload(pixelData);
          textureSet = TextureSet::New();
 -        textureSet.SetTexture(0u, texture);
 +        textureSet.SetTexture(TEXTURE_INDEX, texture);
          if(maskTexture)
          {
 -          textureSet.SetTexture(1u, maskTexture);
 +          textureSet.SetTexture(MASK_TEXTURE_INDEX, maskTexture);
          }
        }
      }
      }
    }
  
 -  if(textureSet)
 -  {
 -    Sampler sampler = Sampler::New();
 -    sampler.SetWrapMode(wrapModeU, wrapModeV);
 -    textureSet.SetSampler(0u, sampler);
 -  }
 -
    return textureSet;
  }
  
@@@ -301,6 -307,8 +301,6 @@@ TextureSet TextureManager::LoadTexture
    Dali::ImageDimensions&              textureRectSize,
    bool&                               atlasingStatus,
    bool&                               loadingStatus,
 -  const Dali::WrapMode::Type&         wrapModeU,
 -  const Dali::WrapMode::Type&         wrapModeV,
    TextureUploadObserver*              textureObserver,
    AtlasUploadObserver*                atlasObserver,
    ImageAtlasManagerPtr                imageAtlasManager,
          if(loadState == TextureManager::LoadState::UPLOADED)
          {
            // LoadComplete has already been called - keep the same texture set
 -          textureSet = mTextureCacheManager.GetTextureSet(textureId);
 +          textureSet = GetTextureSet(textureId);
          }
  
          // If we are loading the texture, or waiting for the ready signal handler to complete, inform
                           loadState == TextureManager::LoadState::MASK_APPLYING ||
                           loadState == TextureManager::LoadState::MASK_APPLIED ||
                           loadState == TextureManager::LoadState::NOT_STARTED ||
-                          mQueueLoadFlag);
+                          mLoadingQueueTextureId != INVALID_TEXTURE_ID);
        }
        else
        {
      }
    }
  
 -  if(!atlasingStatus && textureSet)
 -  {
 -    Sampler sampler = Sampler::New();
 -    sampler.SetWrapMode(wrapModeU, wrapModeV);
 -    textureSet.SetSampler(0u, sampler);
 -  }
 -
    if(synchronousLoading)
    {
      loadingStatus = false;
@@@ -668,9 -683,10 +668,9 @@@ TextureManager::TextureId TextureManage
            {
              if(mTextureCacheManager[maskCacheIndex].storageType == StorageType::KEEP_TEXTURE)
              {
 -              TextureSet maskTextures = mTextureCacheManager[maskCacheIndex].textureSet;
 -              if(maskTextures && maskTextures.GetTextureCount())
 +              if(!mTextureCacheManager[maskCacheIndex].textures.empty())
                {
 -                maskTexture = maskTextures.GetTexture(0u);
 +                maskTexture = mTextureCacheManager[maskCacheIndex].textures[0];
                }
              }
              else if(mTextureCacheManager[maskCacheIndex].storageType == StorageType::KEEP_PIXEL_BUFFER)
  
          // Upload texture
          UploadTextures(pixelBuffers, textureInfo);
 -        if(maskTexture && textureInfo.textureSet)
 -        {
 -          textureInfo.textureSet.SetTexture(1u, maskTexture);
 -        }
        }
      }
    }
 +
    return textureId;
  }
  
@@@ -706,15 -725,60 +706,60 @@@ void TextureManager::Remove(const Textu
  {
    if(textureId != INVALID_TEXTURE_ID)
    {
-     if(mQueueLoadFlag)
-     {
-       // Remove textureId after NotifyObserver finished
-       mRemoveQueue.PushBack(textureId);
-     }
-     else
+     TextureCacheIndex textureCacheIndex = mTextureCacheManager.GetCacheIndexFromId(textureId);
+     if(textureCacheIndex != INVALID_CACHE_INDEX)
      {
-       // Remove textureId in CacheManager.
-       mTextureCacheManager.RemoveCache(textureId);
+       TextureManager::TextureId maskTextureId = INVALID_TEXTURE_ID;
+       TextureInfo& textureInfo(mTextureCacheManager[textureCacheIndex]);
+       if(textureInfo.maskTextureId != INVALID_TEXTURE_ID)
+       {
+         maskTextureId = textureInfo.maskTextureId;
+       }
+       // the case that LoadingQueue is working.
+       if(mLoadingQueueTextureId != INVALID_TEXTURE_ID)
+       {
+         // If textureId is not same, this observer need to delete when ProcessRemoveQueue() is called.
+         TextureUploadObserver* queueObserver = nullptr;
+         if(mLoadingQueueTextureId != textureId)
+         {
+           queueObserver = observer;
+         }
+         // Remove textureId after NotifyObserver finished
+         if(maskTextureId != INVALID_TEXTURE_ID)
+         {
+           if(textureInfo.loadState != LoadState::CANCELLED)
+           {
+             mRemoveQueue.PushBack(QueueElement(maskTextureId, nullptr));
+           }
+         }
+         mRemoveQueue.PushBack(QueueElement(textureId, queueObserver));
+       }
+       else
+       {
+         // Remove its observer
+         RemoveTextureObserver(textureInfo, observer);
+         // Remove maskTextureId in CacheManager
+         if(maskTextureId != INVALID_TEXTURE_ID)
+         {
+           TextureCacheIndex maskCacheIndex = mTextureCacheManager.GetCacheIndexFromId(maskTextureId);
+           if(maskCacheIndex != INVALID_CACHE_INDEX)
+           {
+             TextureInfo& maskTextureInfo(mTextureCacheManager[maskCacheIndex]);
+             // Only Remove maskTexture when texture's loadState is not CANCELLED. because it is already deleted.
+             if(textureInfo.loadState != LoadState::CANCELLED)
+             {
+               mTextureCacheManager.RemoveCache(maskTextureInfo);
+             }
+           }
+         }
+         // Remove textureId in CacheManager
+         mTextureCacheManager.RemoveCache(textureInfo);
+       }
      }
  
      if(observer)
@@@ -799,7 -863,7 +844,7 @@@ void TextureManager::LoadOrQueueTexture
      case LoadState::NOT_STARTED:
      case LoadState::LOAD_FAILED:
      {
-       if(mQueueLoadFlag)
+       if(mLoadingQueueTextureId != INVALID_TEXTURE_ID)
        {
          QueueLoadTexture(textureInfo, observer);
        }
      }
      case LoadState::UPLOADED:
      {
-       if(mQueueLoadFlag)
+       if(mLoadingQueueTextureId != INVALID_TEXTURE_ID)
        {
          QueueLoadTexture(textureInfo, observer);
        }
  void TextureManager::QueueLoadTexture(const TextureManager::TextureInfo& textureInfo, TextureUploadObserver* observer)
  {
    const auto& textureId = textureInfo.textureId;
-   mLoadQueue.PushBack(LoadQueueElement(textureId, observer));
+   mLoadQueue.PushBack(QueueElement(textureId, observer));
  
    observer->DestructionSignal().Connect(this, &TextureManager::ObserverDestroyed);
  }
@@@ -900,9 -964,16 +945,16 @@@ void TextureManager::ProcessLoadQueue(
  
  void TextureManager::ProcessRemoveQueue()
  {
-   for(const auto& textureId : mRemoveQueue)
+   TextureCacheIndex textureCacheIndex = INVALID_CACHE_INDEX;
+   for(auto&& element : mRemoveQueue)
    {
-     mTextureCacheManager.RemoveCache(textureId);
+     textureCacheIndex = mTextureCacheManager.GetCacheIndexFromId(element.mTextureId);
+     if(textureCacheIndex != INVALID_CACHE_INDEX)
+     {
+       TextureInfo& textureInfo(mTextureCacheManager[textureCacheIndex]);
+       RemoveTextureObserver(textureInfo, element.mObserver);
+       mTextureCacheManager.RemoveCache(textureInfo);
+     }
    }
    mRemoveQueue.Clear();
  }
@@@ -995,7 -1066,11 +1047,7 @@@ void TextureManager::PostLoad(TextureMa
                    {
                      // Upload image texture. textureInfo.loadState will be UPLOADED.
                      UploadTextures(pixelBuffers, textureInfo);
 -                    if(maskTextureInfo.textureSet.GetTextureCount() > 0u)
 -                    {
 -                      Texture maskTexture = maskTextureInfo.textureSet.GetTexture(0u);
 -                      textureInfo.textureSet.SetTexture(1u, maskTexture);
 -                    }
 +
                      // notify mask texture set.
                      NotifyObservers(textureInfo, true);
                    }
@@@ -1100,7 -1175,11 +1152,7 @@@ void TextureManager::CheckForWaitingTex
            std::vector<Devel::PixelBuffer> pixelBuffers;
            pixelBuffers.push_back(textureInfo.pixelBuffer);
            UploadTextures(pixelBuffers, textureInfo);
 -          if(maskTextureInfo.textureSet.GetTextureCount() > 0u)
 -          {
 -            Texture maskTexture = maskTextureInfo.textureSet.GetTexture(0u);
 -            textureInfo.textureSet.SetTexture(1u, maskTexture);
 -          }
 +
            // notify mask texture set.
            NotifyObservers(textureInfo, true);
          }
@@@ -1153,15 -1232,19 +1205,15 @@@ void TextureManager::UploadTextures(std
        renderingAddOn.CreateGeometry(textureInfo.textureId, pixelBuffers[0]);
      }
  
 -    if(!textureInfo.textureSet)
 -    {
 -      textureInfo.textureSet = TextureSet::New();
 -    }
 +    // Remove previous textures and insert new textures
 +    textureInfo.textures.clear();
  
 -    uint32_t index = 0;
      for(auto&& pixelBuffer : pixelBuffers)
      {
        Texture texture = Texture::New(Dali::TextureType::TEXTURE_2D, pixelBuffer.GetPixelFormat(), pixelBuffer.GetWidth(), pixelBuffer.GetHeight());
 -
        PixelData pixelData = Devel::PixelBuffer::Convert(pixelBuffer);
        texture.Upload(pixelData);
 -      textureInfo.textureSet.SetTexture(index++, texture);
 +      textureInfo.textures.push_back(texture);
      }
    }
  
@@@ -1191,7 -1274,7 +1243,7 @@@ void TextureManager::NotifyObservers(Te
      info->animatedImageLoading.Reset();
    }
  
-   mQueueLoadFlag = true;
+   mLoadingQueueTextureId = textureId;
  
    // Reverse observer list that we can pop_back the observer.
    std::reverse(info->observerList.Begin(), info->observerList.End());
      info = &mTextureCacheManager[textureInfoIndex];
    }
  
-   mQueueLoadFlag = false;
+   mLoadingQueueTextureId = INVALID_TEXTURE_ID;
    ProcessLoadQueue();
    ProcessRemoveQueue();
  
@@@ -1278,77 -1361,32 +1330,93 @@@ void TextureManager::EmitLoadComplete(T
    {
      observer->LoadComplete(success, TextureUploadObserver::TextureInformation(TextureUploadObserver::ReturnType::PIXEL_BUFFER, textureInfo.pixelBuffer, textureInfo.url.GetUrl(), textureInfo.preMultiplied));
    }
 -  else if(textureInfo.isAnimatedImageFormat)
 +  else
 +  {
 +    TextureSet textureSet = GetTextureSet(textureInfo);
 +    if(textureInfo.isAnimatedImageFormat)
 +    {
 +      observer->LoadComplete(success, TextureUploadObserver::TextureInformation(TextureUploadObserver::ReturnType::ANIMATED_IMAGE_TEXTURE, textureInfo.textureId, textureSet, textureInfo.frameCount, textureInfo.frameInterval));
 +    }
 +    else
 +    {
 +      observer->LoadComplete(success, TextureUploadObserver::TextureInformation(TextureUploadObserver::ReturnType::TEXTURE, textureInfo.textureId, textureSet, (textureInfo.useAtlas == UseAtlas::USE_ATLAS) ? true : false, textureInfo.atlasRect, textureInfo.preMultiplied));
 +    }
 +  }
 +}
 +
 +TextureSet TextureManager::GetTextureSet(const TextureManager::TextureId& textureId)
 +{
 +  TextureSet textureSet;
 +  TextureManager::LoadState loadState = mTextureCacheManager.GetTextureStateInternal(textureId);
 +  if(loadState == TextureManager::LoadState::UPLOADED)
    {
 -    observer->LoadComplete(success, TextureUploadObserver::TextureInformation(TextureUploadObserver::ReturnType::ANIMATED_IMAGE_TEXTURE, textureInfo.textureId, textureInfo.frameCount, textureInfo.frameInterval));
 +    // LoadComplete has already been called - keep the same texture set
 +    TextureCacheIndex textureCacheIndex = mTextureCacheManager.GetCacheIndexFromId(textureId);
 +    if(textureCacheIndex != INVALID_CACHE_INDEX)
 +    {
 +      TextureInfo& textureInfo(mTextureCacheManager[textureCacheIndex]);
 +      textureSet = GetTextureSet(textureInfo);
 +    }
    }
    else
    {
 -    observer->LoadComplete(success, TextureUploadObserver::TextureInformation(TextureUploadObserver::ReturnType::TEXTURE, textureInfo.textureId, textureInfo.textureSet, (textureInfo.useAtlas == UseAtlas::USE_ATLAS) ? true : false, textureInfo.atlasRect, textureInfo.preMultiplied));
 +    DALI_LOG_ERROR("GetTextureSet is failed. texture is not uploaded \n");
 +  }
 +  return textureSet;
 +}
 +
 +TextureSet TextureManager::GetTextureSet(const TextureManager::TextureInfo& textureInfo)
 +{
 +  TextureSet textureSet;
 +
 +  // LoadComplete has already been called - keep the same texture set
 +  textureSet = TextureSet::New();
 +  if(!textureInfo.textures.empty())
 +  {
 +    if(textureInfo.textures.size() > 1) // For YUV case
 +    {
 +      uint32_t index = 0u;
 +      for(auto&& texture : textureInfo.textures)
 +      {
 +        textureSet.SetTexture(index++, texture);
 +      }
 +    }
 +    else
 +    {
 +      textureSet.SetTexture(TEXTURE_INDEX, textureInfo.textures[0]);
 +      TextureCacheIndex maskCacheIndex = mTextureCacheManager.GetCacheIndexFromId(textureInfo.maskTextureId);
 +      if(maskCacheIndex != INVALID_CACHE_INDEX)
 +      {
 +        TextureInfo& maskTextureInfo(mTextureCacheManager[maskCacheIndex]);
 +        if(maskTextureInfo.storageType == StorageType::UPLOAD_TO_TEXTURE || maskTextureInfo.storageType == StorageType::KEEP_TEXTURE)
 +        {
 +          if(!maskTextureInfo.textures.empty())
 +          {
 +            textureSet.SetTexture(MASK_TEXTURE_INDEX, maskTextureInfo.textures[0]);
 +          }
 +        }
 +      }
 +    }
    }
 +  return textureSet;
  }
  
+ void TextureManager::RemoveTextureObserver(TextureManager::TextureInfo& textureInfo, TextureUploadObserver* observer)
+ {
+   // Remove its observer
+   if(observer)
+   {
+     const auto   iterEnd = textureInfo.observerList.End();
+     const auto   iter    = std::find(textureInfo.observerList.Begin(), iterEnd, observer);
+     if(iter != iterEnd)
+     {
+       // Disconnect and remove the observer.
+       observer->DestructionSignal().Disconnect(this, &TextureManager::ObserverDestroyed);
+       textureInfo.observerList.Erase(iter);
+     }
+   }
+ }
  } // namespace Internal
  
  } // namespace Toolkit
@@@ -120,6 -120,8 +120,6 @@@ public
     * @param[out] textureId             The textureId of the frame
     * @param[in, out] maskInfo          Mask info structure
     * @param[in]  samplingMode          The SamplingMode to use
 -   * @param[in]  wrapModeU             Horizontal Wrap mode
 -   * @param[in]  wrapModeV             Vertical Wrap mode
     * @param[in]  synchronousLoading    true if the frame should be loaded synchronously
     * @param[in]  textureObserver       The client object should inherit from this and provide the "LoadCompleted" virtual.
     *                                   This is called when an image load completes (or fails).
                                        TextureManager::TextureId&      textureId,
                                        MaskingDataPointer&             maskInfo,
                                        const Dali::SamplingMode::Type& samplingMode,
 -                                      const Dali::WrapMode::Type&     wrapModeU,
 -                                      const Dali::WrapMode::Type&     wrapModeV,
                                        const bool&                     synchronousLoading,
                                        TextureUploadObserver*          textureObserver,
                                        TextureManager::MultiplyOnLoad& preMultiplyOnLoad);
     *                                  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 "LoadCompleted" 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
      Dali::ImageDimensions&              textureRectSize,
      bool&                               atlasingStatus,
      bool&                               loadingStatus,
 -    const Dali::WrapMode::Type&         wrapModeU,
 -    const Dali::WrapMode::Type&         wrapModeV,
      TextureUploadObserver*              textureObserver,
      AtlasUploadObserver*                atlasObserver,
      ImageAtlasManagerPtr                imageAtlasManager,
     */
    Geometry GetRenderGeometry(const TextureManager::TextureId& textureId, std::uint32_t& frontElements, std::uint32_t& backElements);
  
 +  /**
 +   * @brief Returns the textureSet in texture manager.
 +   * @param[in] textureId Id of the texture
 +   * @return The textureSet in texture manager. These textures include YUV textures or images and masks.
 +   */
 +  TextureSet GetTextureSet(const TextureManager::TextureId& textureId);
 +
 +  /**
 +   * @brief Returns the textureSet in texture manager.
 +   * @param[in] textureInfo the information of the texture
 +   * @return The textureSet in texture manager. These textures include YUV textures or images and masks.
 +   */
 +  TextureSet GetTextureSet(const TextureManager::TextureInfo& textureInfo);
 +
  public:
    // API list that need to access TextureCacheManager.
  
    }
  
    /**
 -   * @copydoc TextureCacheManager::GetTextureSet
 +   * @copydoc TextureCacheManager::GetTexture
     */
 -  inline TextureSet GetTextureSet(const TextureManager::TextureId& textureId)
 +  inline Texture GetTexture(const TextureManager::TextureId& textureId)
    {
 -    return mTextureCacheManager.GetTextureSet(textureId);
 +    return mTextureCacheManager.GetTexture(textureId);
    }
  
    /**
@@@ -517,9 -511,9 +517,9 @@@ private
    /**
     * Structure to hold info about a texture load queued during NotifyObservers
     */
-   struct LoadQueueElement
+   struct QueueElement
    {
-     LoadQueueElement(TextureManager::TextureId textureId, TextureUploadObserver* observer)
+     QueueElement(TextureManager::TextureId textureId, TextureUploadObserver* observer)
      : mTextureId(textureId),
        mObserver(observer)
      {
     */
    void EmitLoadComplete(TextureUploadObserver* observer, TextureManager::TextureInfo& textureInfo, const bool& success);
  
+   /**
+    * @brief Remove observer in textureInfo
+    *
+    * @param textureInfo The struct associated with this Texture.
+    * @param observer The observer wishing to remove.
+    */
+   void RemoveTextureObserver(TextureManager::TextureInfo& textureInfo, TextureUploadObserver* observer);
  public:
    /**
     * @brief Common method to handle loading completion.
@@@ -645,11 -648,11 +654,11 @@@ private
    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
-   Dali::Vector<TextureManager::TextureId> mRemoveQueue;        ///< Queue of textures to remove after NotifyObservers
-   bool                                    mQueueLoadFlag;      ///< Flag that causes Load Textures to be queued.
-   bool                                    mLoadYuvPlanes;      ///< A global flag to specify if the image should be loaded as yuv planes
+   Dali::Vector<LifecycleObserver*>        mLifecycleObservers;      ///< Lifecycle observers of texture manager
+   Dali::Vector<QueueElement>              mLoadQueue;               ///< Queue of textures to load after NotifyObservers
+   Dali::Vector<QueueElement>              mRemoveQueue;             ///< Queue of textures to remove after NotifyObservers
+   TextureManager::TextureId               mLoadingQueueTextureId;   ///< TextureId when it is loading. it causes Load Textures to be queued.
+   bool                                    mLoadYuvPlanes;           ///< A global flag to specify if the image should be loaded as yuv planes
  };
  
  } // namespace Internal
@@@ -132,21 -132,16 +132,21 @@@ void FixedImageCache::LoadBatch(
      Dali::ImageDimensions textureRectSize;
      auto                  preMultiply = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
  
 -    mTextureManager.LoadTexture(
 -      url, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::BOX_THEN_LINEAR, mMaskingData, synchronousLoading, mImageUrls[frameIndex].mTextureId, textureRect, textureRectSize, atlasingStatus, loadingStatus, Dali::WrapMode::Type::DEFAULT, Dali::WrapMode::Type::DEFAULT, this, atlasObserver, imageAtlasManager, ENABLE_ORIENTATION_CORRECTION, TextureManager::ReloadPolicy::CACHED, preMultiply);
 -
 +    mTextureManager.LoadTexture(url, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::BOX_THEN_LINEAR, mMaskingData, synchronousLoading, mImageUrls[frameIndex].mTextureId, textureRect, textureRectSize, atlasingStatus, loadingStatus, this, atlasObserver, imageAtlasManager, ENABLE_ORIENTATION_CORRECTION, TextureManager::ReloadPolicy::CACHED, preMultiply);
      mRequestingLoad = false;
    }
  }
  
  TextureSet FixedImageCache::GetFrontTextureSet() const
  {
 -  return mTextureManager.GetTextureSet(mImageUrls[mFront].mTextureId);
 +  TextureSet textureSet = mTextureManager.GetTextureSet(mImageUrls[mFront].mTextureId);
 +  if(textureSet)
 +  {
 +    Sampler sampler = Sampler::New();
 +    sampler.SetWrapMode(Dali::WrapMode::Type::DEFAULT, Dali::WrapMode::Type::DEFAULT);
 +    textureSet.SetSampler(0u, sampler);
 +  }
 +  return textureSet;
  }
  
  void FixedImageCache::CheckFrontFrame(bool wasReady)
@@@ -165,13 -160,6 +165,6 @@@ void FixedImageCache::ClearCache(
      {
        mTextureManager.Remove(mImageUrls[i].mTextureId, this);
        mImageUrls[i].mTextureId = TextureManager::INVALID_TEXTURE_ID;
-       if(mMaskingData && mMaskingData->mAlphaMaskId != TextureManager::INVALID_TEXTURE_ID)
-       {
-         // In the CPU alpha masking, each frame increases reference count of masking texture.
-         // We should call TextureManager::Remove to decrease reference count when each frame is removed.
-         mTextureManager.Remove(mMaskingData->mAlphaMaskId, this);
-       }
      }
    }
    mReadyFlags.clear();
@@@ -208,15 -208,11 +208,15 @@@ TextureSet RollingAnimatedImageCache::R
                                                                     loadTextureId,
                                                                     mMaskingData,
                                                                     SamplingMode::BOX_THEN_LINEAR,
 -                                                                   mWrapModeU,
 -                                                                   mWrapModeV,
                                                                     synchronousLoading,
                                                                     this,
                                                                     preMultiplyOnLoading);
 +  if(textureSet)
 +  {
 +    Sampler sampler = Sampler::New();
 +    sampler.SetWrapMode(mWrapModeU, mWrapModeV);
 +    textureSet.SetSampler(0u, sampler);
 +  }
  
    mTextureIds[frameIndex] = loadTextureId;
  
@@@ -264,14 -260,7 +264,14 @@@ TextureSet RollingAnimatedImageCache::G
    DALI_LOG_INFO(gAnimImgLogFilter, Debug::Concise, "RollingAnimatedImageCache::GetFrontTextureSet() FrameNumber:%d\n", mQueue[0].mFrameNumber);
  
    TextureManager::TextureId textureId = GetCachedTextureId(0);
 -  return mTextureManager.GetTextureSet(textureId);
 +  TextureSet textureSet = mTextureManager.GetTextureSet(textureId);
 +  if(textureSet)
 +  {
 +    Sampler sampler = Sampler::New();
 +    sampler.SetWrapMode(mWrapModeU, mWrapModeV);
 +    textureSet.SetSampler(0u, sampler);
 +  }
 +  return textureSet;
  }
  
  TextureManager::TextureId RollingAnimatedImageCache::GetCachedTextureId(int index) const
@@@ -287,7 -276,6 +287,6 @@@ void RollingAnimatedImageCache::PopFron
  
    if(mMaskingData && mMaskingData->mAlphaMaskId != TextureManager::INVALID_TEXTURE_ID)
    {
-     mTextureManager.Remove(mMaskingData->mAlphaMaskId, this);
      if(mQueue.IsEmpty())
      {
        mMaskingData->mAlphaMaskId = TextureManager::INVALID_TEXTURE_ID;
@@@ -343,14 -331,15 +342,14 @@@ void RollingAnimatedImageCache::LoadCom
    DALI_LOG_INFO(gAnimImgLogFilter, Debug::Concise, "AnimatedImageVisual::LoadComplete(textureId:%d) start\n", textureInformation.textureId);
    LOG_CACHE;
  
 -  TextureSet textureSet = mTextureManager.GetTextureSet(textureInformation.textureId);
 -  if(textureSet)
 +  if(textureInformation.textureSet)
    {
      Sampler sampler = Sampler::New();
      sampler.SetWrapMode(mWrapModeU, mWrapModeV);
 -    textureSet.SetSampler(0u, sampler);
 +    textureInformation.textureSet.SetSampler(0u, sampler);
    }
  
 -  MakeFrameReady(loadSuccess, textureSet, textureInformation.interval);
 +  MakeFrameReady(loadSuccess, textureInformation.textureSet, textureInformation.interval);
  
    if(loadSuccess)
    {
@@@ -168,7 -168,7 +168,7 @@@ void RollingImageCache::LoadBatch(uint3
  
      TextureManager::TextureId loadTextureId = TextureManager::INVALID_TEXTURE_ID;
      TextureSet                textureSet    = mTextureManager.LoadTexture(
 -      url, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::BOX_THEN_LINEAR, mMaskingData, synchronousLoading, loadTextureId, textureRect, textureRectSize, atlasingStatus, loadingStatus, Dali::WrapMode::Type::DEFAULT, Dali::WrapMode::Type::DEFAULT, this, atlasObserver, imageAtlasManager, ENABLE_ORIENTATION_CORRECTION, TextureManager::ReloadPolicy::CACHED, preMultiply);
 +      url, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::BOX_THEN_LINEAR, mMaskingData, synchronousLoading, loadTextureId, textureRect, textureRectSize, atlasingStatus, loadingStatus, this, atlasObserver, imageAtlasManager, ENABLE_ORIENTATION_CORRECTION, TextureManager::ReloadPolicy::CACHED, preMultiply);
      mImageUrls[imageFrame.mUrlIndex].mTextureId = loadTextureId;
  
      mRequestingLoad = false;
  TextureSet RollingImageCache::GetFrontTextureSet() const
  {
    TextureManager::TextureId textureId = GetCachedTextureId(0);
 -  return mTextureManager.GetTextureSet(textureId);
 +  TextureSet textureSet = mTextureManager.GetTextureSet(textureId);
 +  if(textureSet)
 +  {
 +    Sampler sampler = Sampler::New();
 +    sampler.SetWrapMode(Dali::WrapMode::Type::DEFAULT, Dali::WrapMode::Type::DEFAULT);
 +    textureSet.SetSampler(0u, sampler);
 +  }
 +  return textureSet;
  }
  
  TextureManager::TextureId RollingImageCache::GetCachedTextureId(int index) const
@@@ -204,7 -197,6 +204,6 @@@ void RollingImageCache::PopFrontCache(
  
    if(mMaskingData && mMaskingData->mAlphaMaskId != TextureManager::INVALID_TEXTURE_ID)
    {
-     mTextureManager.Remove(mMaskingData->mAlphaMaskId, this);
      if(mQueue.IsEmpty())
      {
        mMaskingData->mAlphaMaskId = TextureManager::INVALID_TEXTURE_ID;
@@@ -251,13 -243,7 +250,13 @@@ void RollingImageCache::LoadComplete(bo
  
      if(!frontFrameReady && IsFrontReady())
      {
 -      mObserver.FrameReady(mTextureManager.GetTextureSet(textureInformation.textureId), mInterval);
 +      if(textureInformation.textureSet)
 +      {
 +        Sampler sampler = Sampler::New();
 +        sampler.SetWrapMode(Dali::WrapMode::Type::DEFAULT, Dali::WrapMode::Type::DEFAULT);
 +        textureInformation.textureSet.SetSampler(0u, sampler);
 +      }
 +      mObserver.FrameReady(textureInformation.textureSet, mInterval);
      }
    }
    else
@@@ -180,18 -180,6 +180,6 @@@ ImageVisual::~ImageVisual(
  {
    if(Stage::IsInstalled())
    {
-     if(mMaskingData)
-     {
-       // TextureManager could have been deleted before the actor that contains this
-       // ImageVisual is destroyed (e.g. due to stage shutdown). Ensure the stage
-       // is still valid before accessing texture manager.
-       if(mMaskingData->mAlphaMaskId != TextureManager::INVALID_TEXTURE_ID)
-       {
-         TextureManager& textureManager = mFactoryCache.GetTextureManager();
-         textureManager.Remove(mMaskingData->mAlphaMaskId, this);
-       }
-     }
      if(mImageUrl.IsValid())
      {
        // Decrease reference count of External Resources :
@@@ -618,7 -606,7 +606,7 @@@ void ImageVisual::LoadTexture(bool& atl
    bool synchronousLoading = IsSynchronousLoadingRequired();
    bool loadingStatus;
  
 -  textures = textureManager.LoadTexture(mImageUrl, mDesiredSize, mFittingMode, mSamplingMode, mMaskingData, synchronousLoading, mTextureId, atlasRect, mAtlasRectSize, atlasing, loadingStatus, mWrapModeU, mWrapModeV, textureObserver, atlasUploadObserver, atlasManager, mOrientationCorrection, forceReload, preMultiplyOnLoad);
 +  textures = textureManager.LoadTexture(mImageUrl, mDesiredSize, mFittingMode, mSamplingMode, mMaskingData, synchronousLoading, mTextureId, atlasRect, mAtlasRectSize, atlasing, loadingStatus, textureObserver, atlasUploadObserver, atlasManager, mOrientationCorrection, forceReload, preMultiplyOnLoad);
  
    if(textures)
    {
      }
  
      EnablePreMultipliedAlpha(preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD);
 +    if(!atlasing)
 +    {
 +      Sampler sampler = Sampler::New();
 +      sampler.SetWrapMode(mWrapModeU, mWrapModeV);
 +      textures.SetSampler(0u, sampler);
 +    }
    }
    else if(synchronousLoading)
    {
@@@ -682,12 -664,6 +670,12 @@@ void ImageVisual::InitializeRenderer(
      else
      {
        mTextures = mFactoryCache.GetTextureManager().GetTextureSet(mTextureId);
 +      if(!(mImpl->mFlags & Visual::Base::Impl::IS_ATLASING_APPLIED) && mTextures)
 +      {
 +        Sampler sampler = Sampler::New();
 +        sampler.SetWrapMode(mWrapModeU, mWrapModeV);
 +        mTextures.SetSampler(0u, sampler);
 +      }
      }
    }
  
@@@ -924,13 -900,9 +912,13 @@@ void ImageVisual::LoadComplete(bool loa
      }
      else
      {
 -      Sampler sampler = Sampler::New();
 -      sampler.SetWrapMode(mWrapModeU, mWrapModeV);
 -      textureInformation.textureSet.SetSampler(0u, sampler);
 +      if(!textureInformation.useAtlasing)
 +      {
 +        Sampler sampler = Sampler::New();
 +        sampler.SetWrapMode(mWrapModeU, mWrapModeV);
 +        textureInformation.textureSet.SetSampler(0u, sampler);
 +      }
 +
        mImpl->mRenderer.SetTextures(textureInformation.textureSet);
        ComputeTextureSize();
        CheckMaskTexture();