Use original PixelBufferLoadedSignalType signal parameter.
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / texture-manager-impl.cpp
index 7847924..9a06862 100644 (file)
@@ -85,6 +85,8 @@ Debug::Filter* gTextureManagerLogFilter = Debug::Filter::New( Debug::NoLogging,
     loadState == TextureManager::LOADING ? "LOADING" :                   \
     loadState == TextureManager::LOAD_FINISHED ? "LOAD_FINISHED" :       \
     loadState == TextureManager::WAITING_FOR_MASK ? "WAITING_FOR_MASK" : \
+    loadState == TextureManager::MASK_APPLYING ? "MASK_APPLYING" :         \
+    loadState == TextureManager::MASK_APPLIED ? "MASK_APPLIED" :         \
     loadState == TextureManager::UPLOADED ? "UPLOADED" :                 \
     loadState == TextureManager::CANCELLED ? "CANCELLED" :               \
     loadState == TextureManager::LOAD_FAILED ? "LOAD_FAILED" : "Unknown"
@@ -263,6 +265,9 @@ TextureSet TextureManager::LoadTexture(
       // 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::LOADING ||
+                        loadState == TextureManager::WAITING_FOR_MASK ||
+                        loadState == TextureManager::MASK_APPLYING ||
+                        loadState == TextureManager::MASK_APPLIED ||
                         loadState == TextureManager::NOT_STARTED ||
                         mQueueLoadFlag );
 
@@ -344,7 +349,7 @@ TextureManager::TextureId TextureManager::RequestLoadInternal(
 {
   // First check if the requested Texture is cached.
   const TextureHash textureHash = GenerateHash( url.GetUrl(), desiredSize, fittingMode, samplingMode, useAtlas,
-                                                maskTextureId, preMultiplyOnLoad );
+                                                maskTextureId );
 
   TextureManager::TextureId textureId = INVALID_TEXTURE_ID;
 
@@ -393,7 +398,11 @@ TextureManager::TextureId TextureManager::RequestLoadInternal(
                  GET_LOAD_STATE_STRING(textureInfo.loadState ) );
 
   // Force reloading of texture by setting loadState unless already loading or cancelled.
-  if ( TextureManager::ReloadPolicy::FORCED == reloadPolicy && TextureManager::LOADING != textureInfo.loadState &&
+  if ( TextureManager::ReloadPolicy::FORCED == reloadPolicy &&
+       TextureManager::LOADING != textureInfo.loadState &&
+       TextureManager::WAITING_FOR_MASK != textureInfo.loadState &&
+       TextureManager::MASK_APPLYING != textureInfo.loadState &&
+       TextureManager::MASK_APPLIED != textureInfo.loadState &&
        TextureManager::CANCELLED != textureInfo.loadState )
   {
     DALI_LOG_INFO( gTextureManagerLogFilter, Debug::Verbose, "TextureManager::RequestLoad( url=%s observer=%p ) ForcedReload cacheIndex:%d, textureId=%d\n",
@@ -412,6 +421,9 @@ TextureManager::TextureId TextureManager::RequestLoadInternal(
       break;
     }
     case TextureManager::LOADING:
+    case TextureManager::WAITING_FOR_MASK:
+    case TextureManager::MASK_APPLYING:
+    case TextureManager::MASK_APPLIED:
     {
       ObserveTexture( textureInfo, observer );
       break;
@@ -433,7 +445,6 @@ TextureManager::TextureId TextureManager::RequestLoadInternal(
       break;
     }
     case TextureManager::LOAD_FINISHED:
-    case TextureManager::WAITING_FOR_MASK:
       // Loading has already completed. Do nothing.
       break;
   }
@@ -648,7 +659,6 @@ void TextureManager::LoadOrQueueTexture( TextureInfo& textureInfo, TextureUpload
       }
       break;
     }
-    case LOADING:
     case UPLOADED:
     {
       if( mQueueLoadFlag )
@@ -663,10 +673,14 @@ void TextureManager::LoadOrQueueTexture( TextureInfo& textureInfo, TextureUpload
                                   textureInfo.useAtlas, textureInfo.atlasRect,
                                   textureInfo.preMultiplied );
       }
+      break;
     }
+    case LOADING:
     case CANCELLED:
     case LOAD_FINISHED:
     case WAITING_FOR_MASK:
+    case MASK_APPLYING:
+    case MASK_APPLIED:
     {
       break;
     }
@@ -689,10 +703,12 @@ void TextureManager::LoadTexture( TextureInfo& textureInfo, TextureUploadObserve
   {
     auto& loadersContainer = textureInfo.url.IsLocalResource() ? mAsyncLocalLoaders : mAsyncRemoteLoaders;
     auto loadingHelperIt = loadersContainer.GetNext();
+    auto premultiplyOnLoad = textureInfo.preMultiplyOnLoad? DevelAsyncImageLoader::PreMultiplyOnLoad::ON : DevelAsyncImageLoader::PreMultiplyOnLoad::OFF;
     DALI_ASSERT_ALWAYS(loadingHelperIt != loadersContainer.End());
     loadingHelperIt->Load(textureInfo.textureId, textureInfo.url,
                           textureInfo.desiredSize, textureInfo.fittingMode,
-                          textureInfo.samplingMode, textureInfo.orientationCorrection );
+                          textureInfo.samplingMode, textureInfo.orientationCorrection,
+                          premultiplyOnLoad );
   }
   ObserveTexture( textureInfo, observer );
 }
@@ -784,18 +800,26 @@ void TextureManager::PostLoad( TextureInfo& textureInfo, Devel::PixelBuffer& pix
       // wait for the mask to finish loading.
       if( textureInfo.maskTextureId != INVALID_TEXTURE_ID )
       {
-        LoadState maskLoadState = GetTextureStateInternal( textureInfo.maskTextureId );
-        if( maskLoadState == LOADING )
+        if( textureInfo.loadState == MASK_APPLYING )
         {
-          textureInfo.pixelBuffer = pixelBuffer; // Store the pixel buffer temporarily
-          textureInfo.loadState = WAITING_FOR_MASK;
-        }
-        else if( maskLoadState == LOAD_FINISHED )
-        {
-          ApplyMask( pixelBuffer, textureInfo.maskTextureId, textureInfo.scaleFactor, textureInfo.cropToMask );
+          textureInfo.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 == LOADING )
+          {
+            textureInfo.loadState = WAITING_FOR_MASK;
+          }
+          else if( maskLoadState == LOAD_FINISHED )
+          {
+            // Send New Task to Thread
+            ApplyMask( textureInfo, textureInfo.maskTextureId );
+          }
+        }
       }
       else
       {
@@ -815,7 +839,6 @@ void TextureManager::PostLoad( TextureInfo& textureInfo, Devel::PixelBuffer& pix
   }
   else
   {
-    DALI_LOG_ERROR( "TextureManager::AsyncImageLoad(%s) failed\n", textureInfo.url.GetUrl().c_str() );
     // @todo If the load was unsuccessful, upload the broken image.
     textureInfo.loadState = LOAD_FAILED;
     CheckForWaitingTexture( textureInfo );
@@ -835,18 +858,15 @@ void TextureManager::CheckForWaitingTexture( TextureInfo& maskTextureInfo )
         mTextureInfoContainer[cacheIndex].loadState == WAITING_FOR_MASK )
     {
       TextureInfo& textureInfo( mTextureInfoContainer[cacheIndex] );
-      Devel::PixelBuffer pixelBuffer = textureInfo.pixelBuffer;
-      textureInfo.pixelBuffer.Reset();
 
       if( maskTextureInfo.loadState == LOAD_FINISHED )
       {
-        ApplyMask( pixelBuffer, maskTextureInfo.textureId, textureInfo.scaleFactor, textureInfo.cropToMask );
-        UploadTexture( pixelBuffer, textureInfo );
-        NotifyObservers( textureInfo, true );
+        // Send New Task to Thread
+        ApplyMask( textureInfo, maskTextureInfo.textureId );
       }
       else
       {
-        DALI_LOG_ERROR( "TextureManager::ApplyMask to %s failed\n", textureInfo.url.GetUrl().c_str() );
+        textureInfo.pixelBuffer.Reset();
         textureInfo.loadState = LOAD_FAILED;
         NotifyObservers( textureInfo, false );
       }
@@ -854,15 +874,23 @@ void TextureManager::CheckForWaitingTexture( TextureInfo& maskTextureInfo )
   }
 }
 
-void TextureManager::ApplyMask(
-  Devel::PixelBuffer& pixelBuffer, TextureId maskTextureId,
-  float contentScale, bool cropToMask )
+void TextureManager::ApplyMask( TextureInfo& textureInfo, TextureId maskTextureId )
 {
   int maskCacheIndex = GetCacheIndexFromId( maskTextureId );
   if( maskCacheIndex != INVALID_CACHE_INDEX )
   {
     Devel::PixelBuffer maskPixelBuffer = mTextureInfoContainer[maskCacheIndex].pixelBuffer;
-    pixelBuffer.ApplyMask( maskPixelBuffer, contentScale, cropToMask );
+    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 = MASK_APPLYING;
+    auto& loadersContainer = textureInfo.url.IsLocalResource() ? mAsyncLocalLoaders : mAsyncRemoteLoaders;
+    auto loadingHelperIt = loadersContainer.GetNext();
+    DALI_ASSERT_ALWAYS(loadingHelperIt != loadersContainer.End());
+    loadingHelperIt->ApplyMask( textureInfo.textureId, pixelBuffer, maskPixelBuffer, textureInfo.scaleFactor, textureInfo.cropToMask );
   }
 }
 
@@ -872,13 +900,8 @@ void TextureManager::UploadTexture( Devel::PixelBuffer& pixelBuffer, TextureInfo
   {
     DALI_LOG_INFO( gTextureManagerLogFilter, Debug::General, "  TextureManager::UploadTexture() New Texture for textureId:%d\n", textureInfo.textureId );
 
-    // If the texture doesn't have an alpha channel, can't pre-multiply it.
-    // Ensure that we don't change the load parameter (it's used for hashing), and instead set
-    // the status for use in the observer.
-    auto preMultiply = textureInfo.preMultiplyOnLoad ? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD :
-      TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
-    PreMultiply( pixelBuffer, preMultiply );
-    textureInfo.preMultiplied = (preMultiply == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD );
+    // Check if this pixelBuffer is premultiplied
+    textureInfo.preMultiplied = pixelBuffer.IsAlphaPreMultiplied();
 
     Texture texture = Texture::New( Dali::TextureType::TEXTURE_2D, pixelBuffer.GetPixelFormat(),
                                     pixelBuffer.GetWidth(), pixelBuffer.GetHeight() );
@@ -977,8 +1000,7 @@ TextureManager::TextureHash TextureManager::GenerateHash(
   const FittingMode::Type        fittingMode,
   const Dali::SamplingMode::Type samplingMode,
   const UseAtlas                 useAtlas,
-  TextureId                      maskTextureId,
-  TextureManager::MultiplyOnLoad preMultiplyOnLoad)
+  TextureId                      maskTextureId )
 {
   std::string hashTarget( url );
   const size_t urlLength = hashTarget.length();
@@ -1038,22 +1060,6 @@ TextureManager::TextureHash TextureManager::GenerateHash(
     }
   }
 
-  auto premultipliedIndex = hashTarget.length();
-  hashTarget.resize( premultipliedIndex + 1 );
-  switch( preMultiplyOnLoad )
-  {
-    case TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD:
-    {
-      hashTarget[ premultipliedIndex ] = 't';
-      break;
-    }
-    case TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY:
-    {
-      hashTarget[ premultipliedIndex ] = 'f';
-      break;
-    }
-  }
-
   return Dali::CalculateHash( hashTarget );
 }
 
@@ -1078,21 +1084,24 @@ int TextureManager::FindCachedTexture(
     {
       // We have a match, now we check all the original parameters in case of a hash collision.
       TextureInfo& textureInfo( mTextureInfoContainer[i] );
-      auto multiplyOnLoad = textureInfo.preMultiplyOnLoad ? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD :
-        TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
 
       if( ( url == textureInfo.url.GetUrl() ) &&
           ( useAtlas == textureInfo.useAtlas ) &&
           ( maskTextureId == textureInfo.maskTextureId ) &&
           ( size == textureInfo.desiredSize ) &&
-          ( preMultiplyOnLoad ==  multiplyOnLoad ) &&
           ( ( size.GetWidth() == 0 && size.GetHeight() == 0 ) ||
             ( fittingMode == textureInfo.fittingMode &&
               samplingMode == textureInfo.samplingMode ) ) )
       {
-        // The found Texture is a match.
-        cacheIndex = i;
-        break;
+        // 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;
+        }
       }
     }
   }
@@ -1133,10 +1142,22 @@ void TextureManager::AsyncLoadingHelper::Load(TextureId          textureId,
                                               ImageDimensions    desiredSize,
                                               FittingMode::Type  fittingMode,
                                               SamplingMode::Type samplingMode,
-                                              bool               orientationCorrection)
+                                              bool               orientationCorrection,
+                                              DevelAsyncImageLoader::PreMultiplyOnLoad  preMultiplyOnLoad)
+{
+  mLoadingInfoContainer.push_back(AsyncLoadingInfo(textureId));
+  auto id = DevelAsyncImageLoader::Load( mLoader, url.GetUrl(), 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 )
 {
   mLoadingInfoContainer.push_back(AsyncLoadingInfo(textureId));
-  auto id = mLoader.Load(url.GetUrl(), desiredSize, fittingMode, samplingMode, orientationCorrection);
+  auto id = DevelAsyncImageLoader::ApplyMask( mLoader, pixelBuffer, maskPixelBuffer, contentScale, cropToMask );
   mLoadingInfoContainer.back().loadId = id;
 }
 
@@ -1158,9 +1179,9 @@ TextureManager::AsyncLoadingHelper::AsyncLoadingHelper(
 }
 
 void TextureManager::AsyncLoadingHelper::AsyncLoadComplete(uint32_t           id,
-                                                           Devel::PixelBuffer pixelBuffer)
+                                                           Devel::PixelBuffer pixelBuffer )
 {
-  mTextureManager.AsyncLoadComplete(mLoadingInfoContainer, id, pixelBuffer);
+  mTextureManager.AsyncLoadComplete( mLoadingInfoContainer, id, pixelBuffer );
 }
 
 void TextureManager::SetBrokenImageUrl(const std::string& brokenImageUrl)