Remove VisualFactory::Get() code at AsyncImageLoader
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / texture-manager-impl.cpp
index 0d34d55..c6fc0c2 100644 (file)
@@ -30,6 +30,7 @@
 #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>
@@ -199,7 +200,18 @@ Devel::PixelBuffer TextureManager::LoadPixelBuffer(
   {
     if(url.IsValid())
     {
-      pixelBuffer = LoadImageFromFile(url.GetUrl(), desiredSize, fittingMode, samplingMode, orientationCorrection);
+      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);
@@ -244,7 +256,19 @@ TextureSet TextureManager::LoadTexture(
     PixelData data;
     if(url.IsValid())
     {
-      Devel::PixelBuffer pixelBuffer = LoadImageFromFile(url.GetUrl(), desiredSize, fittingMode, samplingMode, 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);
+      }
       if(maskInfo && maskInfo->mAlphaMaskUrl.IsValid())
       {
         Devel::PixelBuffer maskPixelBuffer = LoadImageFromFile(maskInfo->mAlphaMaskUrl.GetUrl(), ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::NO_FILTER, true);
@@ -433,12 +457,35 @@ TextureManager::TextureId TextureManager::RequestLoadInternal(
     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);
   }
 
+  // Check if the requested Texture exist in Encoded Buffer
+  // This mean, that buffer is not cached, and need to be decoded.
+  if(textureId == INVALID_TEXTURE_ID && 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;
+        // Insert this buffer at mTextureInfoContainer.
+        // This buffer will decode at ImageLoaderThread.
+        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 buffered texture, cacheIndex:%d, textureId=%d\n", url.GetUrl().c_str(), observer, cacheIndex, textureId);
+      }
+    }
+  }
+
   if(textureId == INVALID_TEXTURE_ID) // There was no caching, or caching not required
   {
     // We need a new Texture.
     textureId        = GenerateUniqueTextureId();
     bool preMultiply = (preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD);
-    mTextureInfoContainer.push_back(TextureInfo(textureId, maskTextureId, url.GetUrl(), desiredSize, contentScale, fittingMode, samplingMode, false, cropToMask, useAtlas, textureHash, orientationCorrection, preMultiply, animatedImageLoading, frameIndex));
+    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);
@@ -519,6 +566,7 @@ TextureManager::TextureId TextureManager::RequestLoadInternal(
 void TextureManager::Remove(const TextureManager::TextureId textureId, TextureUploadObserver* observer)
 {
   int textureInfoIndex = GetCacheIndexFromId(textureId);
+
   if(textureInfoIndex != INVALID_INDEX)
   {
     TextureInfo& textureInfo(mTextureInfoContainer[textureInfoIndex]);
@@ -568,7 +616,8 @@ void TextureManager::Remove(const TextureManager::TextureId textureId, TextureUp
       {
         if(element.mObserver == observer)
         {
-          mLoadQueue.Erase(&element);
+          // Do not erase the item. We will clear it later in ProcessQueuedTextures().
+          element.mObserver = nullptr;
           break;
         }
       }
@@ -653,24 +702,70 @@ TextureSet TextureManager::GetTextureSet(TextureId textureId)
   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)
   {
-    // get the location from the Url
-    VisualUrl parseUrl(url);
-    if(VisualUrl::TEXTURE == parseUrl.GetProtocolType())
+    if(VisualUrl::TEXTURE == VisualUrl::GetProtocolType(url))
     {
-      std::string location = parseUrl.GetLocation();
+      // get the location from the Url
+      std::string location = VisualUrl::GetLocation(url);
       if(location.size() > 0u)
       {
         TextureId  id  = std::stoi(location);
@@ -680,7 +775,10 @@ TextureSet TextureManager::RemoveExternalTexture(const std::string& url)
           if(iter->textureId == id)
           {
             auto textureSet = iter->textureSet;
-            mExternalTextures.erase(iter);
+            if(--(iter->referenceCount) <= 0)
+            {
+              mExternalTextures.erase(iter);
+            }
             return textureSet;
           }
         }
@@ -690,6 +788,72 @@ TextureSet TextureManager::RemoveExternalTexture(const std::string& url)
   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
@@ -771,7 +935,7 @@ void TextureManager::LoadTexture(TextureInfo& textureInfo, TextureUploadObserver
   textureInfo.loadState = LoadState::LOADING;
   if(!textureInfo.loadSynchronously)
   {
-    auto& loadersContainer  = textureInfo.url.IsLocalResource() ? mAsyncLocalLoaders : mAsyncRemoteLoaders;
+    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());
@@ -970,7 +1134,7 @@ void TextureManager::ApplyMask(TextureInfo& textureInfo, TextureId maskTextureId
     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() ? mAsyncLocalLoaders : mAsyncRemoteLoaders;
+    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());
@@ -1242,7 +1406,7 @@ void TextureManager::AsyncLoadingHelper::LoadAnimatedImage(TextureId
                                                            uint32_t                   frameIndex)
 {
   mLoadingInfoContainer.push_back(AsyncLoadingInfo(textureId));
-  auto id                             = DevelAsyncImageLoader::LoadAnimatedImage(mLoader, animatedImageLoading, frameIndex);
+  auto id                             = GetImplementation(mLoader).LoadAnimatedImage(animatedImageLoading, frameIndex);
   mLoadingInfoContainer.back().loadId = id;
 }
 
@@ -1255,8 +1419,16 @@ void TextureManager::AsyncLoadingHelper::Load(TextureId
                                               DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
 {
   mLoadingInfoContainer.push_back(AsyncLoadingInfo(textureId));
-  auto id                             = DevelAsyncImageLoader::Load(mLoader, url.GetUrl(), desiredSize, fittingMode, samplingMode, orientationCorrection, preMultiplyOnLoad);
-  mLoadingInfoContainer.back().loadId = id;
+  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,
@@ -1267,7 +1439,7 @@ void TextureManager::AsyncLoadingHelper::ApplyMask(TextureId
                                                    DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
 {
   mLoadingInfoContainer.push_back(AsyncLoadingInfo(textureId));
-  auto id                             = DevelAsyncImageLoader::ApplyMask(mLoader, pixelBuffer, maskPixelBuffer, contentScale, cropToMask, preMultiplyOnLoad);
+  auto id                             = GetImplementation(mLoader).ApplyMask(pixelBuffer, maskPixelBuffer, contentScale, cropToMask, preMultiplyOnLoad);
   mLoadingInfoContainer.back().loadId = id;
 }