Removed Texture Atlas for the GIF image.
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / texture-manager-impl.cpp
index e795863..6b31322 100644 (file)
@@ -47,8 +47,10 @@ size_t GetNumberOfThreads(const char* environmentVariable, size_t defaultValue)
 {
   using Dali::EnvironmentVariable::GetEnvironmentVariable;
   auto numberString = GetEnvironmentVariable(environmentVariable);
-  auto numberOfThreads = numberString ? std::strtol(numberString, nullptr, 10) : 0;
-  return (numberOfThreads > 0) ? numberOfThreads : defaultValue;
+  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()
@@ -103,12 +105,13 @@ TextureManager::TextureManager()
 }
 
 TextureSet TextureManager::LoadTexture(
-    VisualUrl& url, Dali::ImageDimensions desiredSize, Dali::FittingMode::Type fittingMode,
+    const VisualUrl& url, Dali::ImageDimensions desiredSize, Dali::FittingMode::Type fittingMode,
     Dali::SamplingMode::Type samplingMode, const MaskingDataPointer& maskInfo,
     bool synchronousLoading, TextureManager::TextureId& textureId, Vector4& textureRect,
     bool& atlasingStatus, bool& loadingStatus, Dali::WrapMode::Type wrapModeU,
     Dali::WrapMode::Type wrapModeV, TextureUploadObserver* textureObserver,
-    AtlasUploadObserver* atlasObserver, ImageAtlasManagerPtr imageAtlasManager)
+    AtlasUploadObserver* atlasObserver, ImageAtlasManagerPtr imageAtlasManager, bool orientationCorrection,
+    TextureManager::ReloadPolicy reloadPolicy )
 {
   TextureSet textureSet;
 
@@ -125,6 +128,7 @@ TextureSet TextureManager::LoadTexture(
       {
         if( elem.textureId == id )
         {
+          textureId = elem.textureId;
           return elem.textureSet;
         }
       }
@@ -135,7 +139,8 @@ TextureSet TextureManager::LoadTexture(
     PixelData data;
     if( url.IsValid() )
     {
-      Devel::PixelBuffer pixelBuffer = LoadImageFromFile( url.GetUrl(), desiredSize, fittingMode, samplingMode );
+      Devel::PixelBuffer pixelBuffer = LoadImageFromFile( url.GetUrl(), desiredSize, fittingMode, samplingMode,
+                                       orientationCorrection  );
       if( pixelBuffer )
       {
         data = Devel::PixelBuffer::Convert(pixelBuffer); // takes ownership of buffer
@@ -185,7 +190,8 @@ TextureSet TextureManager::LoadTexture(
       atlasingStatus = false;
       if( !maskInfo )
       {
-        textureId = RequestLoad( url, desiredSize, fittingMode, samplingMode, TextureManager::NO_ATLAS, textureObserver );
+        textureId = RequestLoad( url, desiredSize, fittingMode, samplingMode, TextureManager::NO_ATLAS,
+                                 textureObserver, orientationCorrection, reloadPolicy );
       }
       else
       {
@@ -196,10 +202,12 @@ TextureSet TextureManager::LoadTexture(
                                  fittingMode, samplingMode,
                                  TextureManager::NO_ATLAS,
                                  maskInfo->mCropToMask,
-                                 textureObserver );
+                                 textureObserver,
+                                 orientationCorrection,
+                                 reloadPolicy );
       }
 
-      TextureManager::LoadState loadState = GetTextureState( textureId );
+      TextureManager::LoadState loadState = GetTextureStateInternal( textureId );
       loadingStatus = ( loadState == TextureManager::LOADING );
 
       if( loadState == TextureManager::UPLOADED )
@@ -221,64 +229,80 @@ TextureSet TextureManager::LoadTexture(
 }
 
 TextureManager::TextureId TextureManager::RequestLoad(
-  const VisualUrl&         url,
-  const ImageDimensions    desiredSize,
-  FittingMode::Type        fittingMode,
-  Dali::SamplingMode::Type samplingMode,
-  const UseAtlas           useAtlas,
-  TextureUploadObserver*   observer )
+  const VisualUrl&            url,
+  const ImageDimensions       desiredSize,
+  FittingMode::Type           fittingMode,
+  Dali::SamplingMode::Type    samplingMode,
+  const UseAtlas              useAtlas,
+  TextureUploadObserver*      observer,
+  bool                        orientationCorrection,
+  TextureManager::ReloadPolicy reloadPolicy )
 {
-  return RequestLoadInternal( url, INVALID_TEXTURE_ID, 1.0f, desiredSize, fittingMode, samplingMode, useAtlas, false, UPLOAD_TO_TEXTURE, observer );
+  return RequestLoadInternal( url, INVALID_TEXTURE_ID, 1.0f, desiredSize, fittingMode, samplingMode, useAtlas,
+                              false, UPLOAD_TO_TEXTURE, observer, orientationCorrection, reloadPolicy );
 }
 
 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 )
-{
-  return RequestLoadInternal( url, maskTextureId, contentScale, desiredSize, fittingMode, samplingMode, useAtlas, cropToMask, UPLOAD_TO_TEXTURE, observer );
+  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 )
+{
+  return RequestLoadInternal( url, maskTextureId, contentScale, desiredSize, fittingMode, samplingMode, useAtlas,
+                              cropToMask, UPLOAD_TO_TEXTURE, observer, orientationCorrection, reloadPolicy );
 }
 
 TextureManager::TextureId TextureManager::RequestMaskLoad( const VisualUrl& maskUrl )
 {
   // Use the normal load procedure to get the alpha mask.
-  return RequestLoadInternal( maskUrl, INVALID_TEXTURE_ID, 1.0f, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::NO_FILTER, NO_ATLAS, false, KEEP_PIXEL_BUFFER, NULL );
+  return RequestLoadInternal( maskUrl, INVALID_TEXTURE_ID, 1.0f, ImageDimensions(), FittingMode::SCALE_TO_FILL,
+                              SamplingMode::NO_FILTER, NO_ATLAS, false, KEEP_PIXEL_BUFFER, NULL, true,
+                              TextureManager::ReloadPolicy::CACHED );
 }
 
 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 )
+  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 )
 {
   // First check if the requested Texture is cached.
-  const TextureHash textureHash = GenerateHash( url.GetUrl(), desiredSize, fittingMode, samplingMode, useAtlas, maskTextureId );
+  const TextureHash textureHash = GenerateHash( url.GetUrl(), desiredSize, fittingMode, samplingMode, useAtlas,
+                                                maskTextureId );
 
   TextureManager::TextureId textureId = INVALID_TEXTURE_ID;
 
   // Look up the texture by hash. Note: The extra parameters are used in case of a hash collision.
-  int cacheIndex = FindCachedTexture( textureHash, url.GetUrl(), desiredSize, fittingMode, samplingMode, useAtlas, maskTextureId );
+  int cacheIndex = FindCachedTexture( textureHash, url.GetUrl(), desiredSize, fittingMode, samplingMode, useAtlas,
+                                      maskTextureId );
 
   // Check if the requested Texture exists in the cache.
   if( cacheIndex != INVALID_CACHE_INDEX )
   {
-    // Mark this texture being used by another client resource.
-    ++( mTextureInfoContainer[ cacheIndex ].referenceCount );
+    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;
-
-    DALI_LOG_INFO( gTextureManagerLogFilter, Debug::Concise, "TextureManager::RequestLoad( url=%s observer=%p ) Using cached texture @%d, textureId=%d\n", url.GetUrl().c_str(), observer, cacheIndex, textureId );
+    DALI_LOG_INFO( gTextureManagerLogFilter, Debug::Concise, "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
@@ -287,10 +311,11 @@ TextureManager::TextureId TextureManager::RequestLoadInternal(
     textureId = GenerateUniqueTextureId();
     mTextureInfoContainer.push_back( TextureInfo( textureId, maskTextureId, url.GetUrl(),
                                                   desiredSize, contentScale, fittingMode, samplingMode,
-                                                  false, cropToMask, useAtlas, textureHash ) );
+                                                  false, cropToMask, useAtlas, textureHash, orientationCorrection ) );
     cacheIndex = mTextureInfoContainer.size() - 1u;
 
-    DALI_LOG_INFO( gTextureManagerLogFilter, Debug::Concise, "TextureManager::RequestLoad( url=%s observer=%p ) New texture, cacheIndex:%d, textureId=%d\n", url.GetUrl().c_str(), observer, cacheIndex, textureId );
+    DALI_LOG_INFO( gTextureManagerLogFilter, Debug::Concise, "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.
@@ -299,6 +324,7 @@ TextureManager::TextureId TextureManager::RequestLoadInternal(
   TextureInfo& textureInfo( mTextureInfoContainer[ cacheIndex ] );
   textureInfo.maskTextureId = maskTextureId;
   textureInfo.storageType = storageType;
+  textureInfo.orientationCorrection = orientationCorrection;
 
   DALI_LOG_INFO( gTextureManagerLogFilter, Debug::Concise, "TextureInfo loadState:%s\n",
                  textureInfo.loadState == TextureManager::NOT_STARTED ? "NOT_STARTED" :
@@ -306,9 +332,20 @@ TextureManager::TextureId TextureManager::RequestLoadInternal(
                  textureInfo.loadState == TextureManager::UPLOADED ? "UPLOADED" :
                  textureInfo.loadState == TextureManager::CANCELLED ? "CANCELLED" : "Unknown" );
 
-  // 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.
+  // Force reloading of texture by setting loadState unless already loading or cancelled.
+  if ( TextureManager::ReloadPolicy::FORCED == reloadPolicy && TextureManager::LOADING != textureInfo.loadState &&
+       TextureManager::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::NOT_STARTED;
+  }
+
+  // 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::LOAD_FAILED: // Failed notifies observer which then stops observing.
     case TextureManager::NOT_STARTED:
     {
       LoadTexture( textureInfo );
@@ -341,7 +378,6 @@ TextureManager::TextureId TextureManager::RequestLoadInternal(
     }
     case TextureManager::LOAD_FINISHED:
     case TextureManager::WAITING_FOR_MASK:
-    case TextureManager::LOAD_FAILED:
       // Loading has already completed. Do nothing.
       break;
   }
@@ -421,6 +457,31 @@ TextureManager::LoadState TextureManager::GetTextureState( TextureId textureId )
     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::NOT_STARTED;
+
+  int cacheIndex = GetCacheIndexFromId( textureId );
+  if( cacheIndex != INVALID_CACHE_INDEX )
+  {
+    TextureInfo& cachedTextureInfo( mTextureInfoContainer[ cacheIndex ] );
+    loadState = cachedTextureInfo.loadState;
+  }
+
   return loadState;
 }
 
@@ -434,6 +495,17 @@ TextureSet TextureManager::GetTextureSet( TextureId textureId )
     TextureInfo& cachedTextureInfo( mTextureInfoContainer[ cacheIndex ] );
     textureSet = cachedTextureInfo.textureSet;
   }
+  else
+  {
+    for( auto&& elem : mExternalTextures )
+    {
+      if( elem.textureId == textureId )
+      {
+        textureSet = elem.textureSet;
+        break;
+      }
+    }
+  }
   return textureSet;
 }
 
@@ -489,7 +561,7 @@ bool TextureManager::LoadTexture( TextureInfo& textureInfo )
       DALI_ASSERT_ALWAYS(loadingHelperIt != loadersContainer.End());
       loadingHelperIt->Load(textureInfo.textureId, textureInfo.url,
                             textureInfo.desiredSize, textureInfo.fittingMode,
-                            textureInfo.samplingMode, true);
+                            textureInfo.samplingMode, textureInfo.orientationCorrection );
     }
   }
 
@@ -506,7 +578,8 @@ void TextureManager::ObserveTexture( TextureInfo& textureInfo,
   }
 }
 
-void TextureManager::AsyncLoadComplete( AsyncLoadingInfoContainerType& loadingContainer, uint32_t id, Devel::PixelBuffer pixelBuffer )
+void TextureManager::AsyncLoadComplete( AsyncLoadingInfoContainerType& loadingContainer, uint32_t id,
+                                        Devel::PixelBuffer pixelBuffer )
 {
   DALI_LOG_INFO( gTextureManagerLogFilter, Debug::Concise, "TextureManager::AsyncLoadComplete( id:%d )\n", id );
 
@@ -554,7 +627,7 @@ void TextureManager::PostLoad( TextureInfo& textureInfo, Devel::PixelBuffer& pix
       // wait for the mask to finish loading.
       if( textureInfo.maskTextureId != INVALID_TEXTURE_ID )
       {
-        LoadState maskLoadState = GetTextureState( textureInfo.maskTextureId );
+        LoadState maskLoadState = GetTextureStateInternal( textureInfo.maskTextureId );
         if( maskLoadState == LOADING )
         {
           textureInfo.pixelBuffer = pixelBuffer; // Store the pixel buffer temporarily
@@ -639,10 +712,14 @@ void TextureManager::UploadTexture( Devel::PixelBuffer& pixelBuffer, TextureInfo
   {
     DALI_LOG_INFO( gTextureManagerLogFilter, Debug::Concise, "  TextureManager::UploadTexture() New Texture for textureId:%d\n", textureInfo.textureId );
 
-    Texture texture = Texture::New( Dali::TextureType::TEXTURE_2D, pixelBuffer.GetPixelFormat(), pixelBuffer.GetWidth(), pixelBuffer.GetHeight() );
+    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 = TextureSet::New();
+    if ( ! textureInfo.textureSet )
+    {
+      textureInfo.textureSet = TextureSet::New();
+    }
     textureInfo.textureSet.SetTexture( 0u, texture );
   }
 
@@ -724,7 +801,6 @@ int TextureManager::GetCacheIndexFromId( const TextureId textureId )
     }
   }
 
-  DALI_LOG_WARNING( "Cannot locate TextureId: %d\n", textureId );
   return INVALID_CACHE_INDEX;
 }
 
@@ -828,7 +904,8 @@ void TextureManager::ObserverDestroyed( TextureUploadObserver* observer )
   for( unsigned int i = 0; i < count; ++i )
   {
     TextureInfo& textureInfo( mTextureInfoContainer[i] );
-    for( TextureInfo::ObserverListType::Iterator j = textureInfo.observerList.Begin(); j != textureInfo.observerList.End(); )
+    for( TextureInfo::ObserverListType::Iterator j = textureInfo.observerList.Begin();
+         j != textureInfo.observerList.End(); )
     {
       if( *j == observer )
       {