NPatch rendering optimization
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / image / image-visual.cpp
index f656e2d..b8abd9b 100644 (file)
 // EXTERNAL HEADERS
 #include <cstring> // for strlen()
 #include <dali/public-api/actors/layer.h>
-#include <dali/public-api/common/stage.h>
-#include <dali/public-api/images/resource-image.h>
-#include <dali/public-api/images/native-image.h>
-#include <dali/devel-api/images/texture-set-image.h>
+#include <dali/devel-api/common/stage.h>
 #include <dali/devel-api/adaptor-framework/image-loading.h>
 #include <dali/devel-api/scripting/enum-helper.h>
 #include <dali/devel-api/scripting/scripting.h>
@@ -43,6 +40,7 @@
 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
 #include <dali-toolkit/internal/visuals/visual-url.h>
 #include <dali-toolkit/internal/visuals/image-visual-shader-factory.h>
+#include <dali/devel-api/rendering/renderer-devel.h>
 
 namespace Dali
 {
@@ -56,15 +54,6 @@ namespace Internal
 namespace
 {
 
-// property names
-const char * const IMAGE_FITTING_MODE( "fittingMode" );
-const char * const IMAGE_SAMPLING_MODE( "samplingMode" );
-const char * const IMAGE_DESIRED_WIDTH( "desiredWidth" );
-const char * const IMAGE_DESIRED_HEIGHT( "desiredHeight" );
-const char * const SYNCHRONOUS_LOADING( "synchronousLoading" );
-const char * const IMAGE_ATLASING("atlasing");
-const char * const ALPHA_MASK_URL("alphaMaskUrl");
-
 // fitting modes
 DALI_ENUM_TO_STRING_TABLE_BEGIN( FITTING_MODE )
 DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::FittingMode, SHRINK_TO_FIT )
@@ -108,8 +97,6 @@ DALI_ENUM_TO_STRING_TABLE_END( RELEASE_POLICY )
 
 const Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f);
 
-const char* DEFAULT_SAMPLER_TYPENAME = "sampler2D";
-
 const float PIXEL_ALIGN_ON = 1.0f;
 const float PIXEL_ALIGN_OFF = 0.0f;
 
@@ -131,6 +118,7 @@ Geometry CreateGeometry( VisualFactoryCache& factoryCache, ImageDimensions gridS
 
 } // unnamed namespace
 
+
 ImageVisualPtr ImageVisual::New( VisualFactoryCache& factoryCache,
                                  ImageVisualShaderFactory& shaderFactory,
                                  const VisualUrl& imageUrl,
@@ -154,19 +142,13 @@ ImageVisualPtr ImageVisual::New( VisualFactoryCache& factoryCache,
   return new ImageVisual( factoryCache, shaderFactory, imageUrl, size, fittingMode, samplingMode );
 }
 
-ImageVisualPtr ImageVisual::New( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const Image& image )
-{
-  return new ImageVisual( factoryCache, shaderFactory, image );
-}
-
 ImageVisual::ImageVisual( VisualFactoryCache& factoryCache,
                           ImageVisualShaderFactory& shaderFactory,
                           const VisualUrl& imageUrl,
                           ImageDimensions size,
                           FittingMode::Type fittingMode,
                           Dali::SamplingMode::Type samplingMode )
-: Visual::Base( factoryCache, Visual::FittingMode::FILL ),
-  mImage(),
+: Visual::Base( factoryCache, Visual::FittingMode::FILL, Toolkit::Visual::IMAGE ),
   mPixelArea( FULL_TEXTURE_RECT ),
   mPlacementActor(),
   mImageUrl( imageUrl ),
@@ -190,31 +172,6 @@ ImageVisual::ImageVisual( VisualFactoryCache& factoryCache,
   EnablePreMultipliedAlpha( mFactoryCache.GetPreMultiplyOnLoad() );
 }
 
-ImageVisual::ImageVisual( VisualFactoryCache& factoryCache, ImageVisualShaderFactory& shaderFactory, const Image& image )
-: Visual::Base( factoryCache, Visual::FittingMode::FIT_KEEP_ASPECT_RATIO ),
-  mImage( image ),
-  mPixelArea( FULL_TEXTURE_RECT ),
-  mPlacementActor(),
-  mImageUrl(),
-  mMaskingData( ),
-  mDesiredSize(),
-  mTextureId( TextureManager::INVALID_TEXTURE_ID ),
-  mTextures(),
-  mImageVisualShaderFactory( shaderFactory ),
-  mFittingMode( FittingMode::DEFAULT ),
-  mSamplingMode( SamplingMode::DEFAULT ),
-  mWrapModeU( WrapMode::DEFAULT ),
-  mWrapModeV( WrapMode::DEFAULT ),
-  mLoadPolicy( Toolkit::ImageVisual::LoadPolicy::ATTACHED ),
-  mReleasePolicy( Toolkit::ImageVisual::ReleasePolicy::DESTROYED ),
-  mAtlasRect( 0.0f, 0.0f, 0.0f, 0.0f ),
-  mAttemptAtlasing( false ),
-  mLoading( false ),
-  mOrientationCorrection( true )
-{
-  EnablePreMultipliedAlpha( mFactoryCache.GetPreMultiplyOnLoad() );
-}
-
 ImageVisual::~ImageVisual()
 {
   if( Stage::IsInstalled() )
@@ -227,7 +184,7 @@ ImageVisual::~ImageVisual()
       if( mMaskingData->mAlphaMaskId != TextureManager::INVALID_TEXTURE_ID )
       {
         TextureManager& textureManager = mFactoryCache.GetTextureManager();
-        textureManager.Remove( mMaskingData->mAlphaMaskId );
+        textureManager.Remove( mMaskingData->mAlphaMaskId, this );
       }
     }
 
@@ -489,13 +446,7 @@ void ImageVisual::AllocateMaskData()
 
 void ImageVisual::GetNaturalSize( Vector2& naturalSize )
 {
-  if(mImage)
-  {
-    naturalSize.x = mImage.GetWidth();
-    naturalSize.y = mImage.GetHeight();
-    return;
-  }
-  else if( mDesiredSize.GetWidth()>0 && mDesiredSize.GetHeight()>0)
+  if( mDesiredSize.GetWidth()>0 && mDesiredSize.GetHeight()>0)
   {
     naturalSize.x = mDesiredSize.GetWidth();
     naturalSize.y = mDesiredSize.GetHeight();
@@ -514,9 +465,12 @@ void ImageVisual::GetNaturalSize( Vector2& naturalSize )
     if( textureSet )
     {
       auto texture = textureSet.GetTexture(0);
-      naturalSize.x = texture.GetWidth();
-      naturalSize.y = texture.GetHeight();
-      return;
+      if( texture )
+      {
+        naturalSize.x = texture.GetWidth();
+        naturalSize.y = texture.GetHeight();
+        return;
+      }
     }
   }
 
@@ -544,7 +498,7 @@ void ImageVisual::GetNaturalSize( Vector2& naturalSize )
       }
       else
       {
-        Image brokenImage = mFactoryCache.GetBrokenVisualImage();
+        Texture brokenImage = mFactoryCache.GetBrokenVisualImage();
 
         naturalSize.x = brokenImage.GetWidth();
         naturalSize.y = brokenImage.GetWidth();
@@ -552,7 +506,6 @@ void ImageVisual::GetNaturalSize( Vector2& naturalSize )
       return;
     }
   }
-
   naturalSize = Vector2::ZERO;
 }
 
@@ -563,11 +516,20 @@ void ImageVisual::CreateRenderer( TextureSet& textureSet )
 
   if( !mImpl->mCustomShader )
   {
-    geometry = CreateGeometry( mFactoryCache, ImageDimensions( 1, 1 ) );
+    TextureManager& textureManager = mFactoryCache.GetTextureManager();
+
+    uint32_t firstElementCount {0u};
+    uint32_t secondElementCount {0u};
+    geometry = textureManager.GetRenderGeometry(mTextureId, firstElementCount, secondElementCount);
+    if(!firstElementCount && !secondElementCount)
+    {
+      geometry = CreateGeometry( mFactoryCache, ImageDimensions( 1, 1 ) );
+    }
 
     shader = mImageVisualShaderFactory.GetShader( mFactoryCache,
                              mImpl->mFlags & Impl::IS_ATLASING_APPLIED,
-                             mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE );
+                             mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE,
+                             IsRoundedCornerRequired() );
   }
   else
   {
@@ -608,65 +570,6 @@ void ImageVisual::CreateRenderer( TextureSet& textureSet )
   EnablePreMultipliedAlpha( IsPreMultipliedAlphaEnabled() );
 }
 
-void ImageVisual::CreateNativeImageRenderer( NativeImage& nativeImage )
-{
-  Geometry geometry;
-  Shader shader;
-
-  std::string fragmentShader;
-  const char* fragmentPreFix = nativeImage.GetCustomFragmentPreFix();
-  const char* customSamplerTypename = nativeImage.GetCustomSamplerTypename();
-
-  if( fragmentPreFix )
-  {
-    fragmentShader = fragmentPreFix;
-    fragmentShader += "\n";
-  }
-
-  if( mImpl->mCustomShader && !mImpl->mCustomShader->mFragmentShader.empty() )
-  {
-    fragmentShader += mImpl->mCustomShader->mFragmentShader;
-  }
-  else
-  {
-    fragmentShader += mImageVisualShaderFactory.GetFragmentShaderSource();
-  }
-
-  if( customSamplerTypename )
-  {
-    fragmentShader.replace( fragmentShader.find( DEFAULT_SAMPLER_TYPENAME ), strlen( DEFAULT_SAMPLER_TYPENAME ), customSamplerTypename );
-  }
-
-  if( !mImpl->mCustomShader )
-  {
-    geometry = CreateGeometry( mFactoryCache, ImageDimensions( 1, 1 ) );
-
-    shader  = Shader::New( mImageVisualShaderFactory.GetVertexShaderSource(), fragmentShader );
-    shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
-  }
-  else
-  {
-    geometry = CreateGeometry( mFactoryCache, mImpl->mCustomShader->mGridSize );
-    shader  = Shader::New( mImpl->mCustomShader->mVertexShader.empty() ? mImageVisualShaderFactory.GetVertexShaderSource() : mImpl->mCustomShader->mVertexShader,
-                           fragmentShader,
-                           mImpl->mCustomShader->mHints );
-    if( mImpl->mCustomShader->mVertexShader.empty() )
-    {
-      shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
-    }
-  }
-
-  mImpl->mRenderer = Renderer::New( geometry, shader );
-
-  //Register transform properties
-  mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT );
-}
-
-bool ImageVisual::IsSynchronousResourceLoading() const
-{
-  return mImpl->mFlags & Impl::IS_SYNCHRONOUS_RESOURCE_LOADING;
-}
-
 void ImageVisual::LoadTexture( bool& atlasing, Vector4& atlasRect, TextureSet& textures, bool orientationCorrection,
                                TextureManager::ReloadPolicy forceReload )
 {
@@ -687,7 +590,7 @@ void ImageVisual::LoadTexture( bool& atlasing, Vector4& atlasRect, TextureSet& t
     : TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
 
   textures = textureManager.LoadTexture( mImageUrl, mDesiredSize, mFittingMode, mSamplingMode,
-                                         mMaskingData, IsSynchronousResourceLoading(), mTextureId,
+                                         mMaskingData, IsSynchronousLoadingRequired(), mTextureId,
                                          atlasRect, mAtlasRectSize, atlasing, mLoading, mWrapModeU,
                                          mWrapModeV, textureObserver, atlasUploadObserver, atlasManager,
                                          mOrientationCorrection, forceReload, preMultiplyOnLoad);
@@ -715,13 +618,27 @@ bool ImageVisual::AttemptAtlasing()
 void ImageVisual::InitializeRenderer()
 {
   auto attemptAtlasing = AttemptAtlasing();
-  // texture set has to be created first as we need to know if atlasing succeeded or not
-  // when selecting the shader
 
-  if( mTextureId == TextureManager::INVALID_TEXTURE_ID && ! mTextures ) // Only load the texture once
+  // Load Texture if mTextures is empty.
+  // mTextures is already set, the mTexture can be used to create Renderer.
+  // There are two cases mTextures is empty.
+  // 1. mTextureId == TextureManager::INVALID_TEXTURE_ID
+  //  - Visual is on stage with LoadPolicy::ATTACHED
+  // 2. mTextureId != TextureManager::INVALID_TEXTURE_ID
+  //  - If ReleasePolicy is DESTROYED, InitializeRenderer called every on stage called.
+  //  - Then every resources those contained in Visual are Reset but mTextureId is remained when the Off stage time,
+  //  - So, mTextures needed to be get from texture manager to created resources like mImpl->mRenderer.
+  if( ! mTextures )
   {
-    LoadTexture( attemptAtlasing, mAtlasRect, mTextures, mOrientationCorrection,
-                 TextureManager::ReloadPolicy::CACHED );
+    if( mTextureId == TextureManager::INVALID_TEXTURE_ID )
+    {
+      LoadTexture( attemptAtlasing, mAtlasRect, mTextures, mOrientationCorrection,
+                   TextureManager::ReloadPolicy::CACHED );
+    }
+    else
+    {
+      mTextures = mFactoryCache.GetTextureManager().GetTextureSet( mTextureId );
+    }
   }
 
   CreateRenderer( mTextures );
@@ -742,35 +659,12 @@ void ImageVisual::InitializeRenderer()
   }
 }
 
-void ImageVisual::InitializeRenderer( const Image& image )
-{
-  TextureSet textures = TextureSet::New();
-
-  NativeImage nativeImage = NativeImage::DownCast( image );
-  if( nativeImage )
-  {
-    CreateNativeImageRenderer( nativeImage );
-    DALI_ASSERT_DEBUG( textures );
-    mImpl->mRenderer.SetTextures( textures );
-  }
-  else
-  {
-    // reuse existing code for regular images
-    CreateRenderer( textures ); // Textures will be retreived from Image
-  }
-  ApplyImageToSampler( image );
-}
-
-void ImageVisual::DoSetOnStage( Actor& actor )
+void ImageVisual::DoSetOnScene( Actor& actor )
 {
   if( mImageUrl.IsValid() )
   {
     InitializeRenderer();
   }
-  else if( mImage )
-  {
-    InitializeRenderer( mImage );
-  }
 
   if( !mImpl->mRenderer )
   {
@@ -780,7 +674,7 @@ void ImageVisual::DoSetOnStage( Actor& actor )
   mPlacementActor = actor;
   // Search the Actor tree to find if Layer UI behaviour set.
   Layer layer = actor.GetLayer();
-  if( layer && layer.GetBehavior() == Layer::LAYER_3D )
+  if( layer && layer.GetProperty<Layer::Behavior>( Layer::Property::BEHAVIOR ) == Layer::LAYER_3D )
   {
      // Layer 3D set, do not align pixels
      mImpl->mRenderer.RegisterProperty( PIXEL_ALIGNED_UNIFORM_NAME, PIXEL_ALIGN_OFF );
@@ -801,9 +695,9 @@ void ImageVisual::DoSetOnStage( Actor& actor )
   }
 }
 
-void ImageVisual::DoSetOffStage( Actor& actor )
+void ImageVisual::DoSetOffScene( Actor& actor )
 {
-  // Visual::Base::SetOffStage only calls DoSetOffStage if mRenderer exists (is on onstage)
+  // Visual::Base::SetOffScene only calls DoSetOffScene if mRenderer exists (is on onstage)
 
   // Image release is dependent on the ReleasePolicy, renderer is destroyed.
   actor.RemoveRenderer( mImpl->mRenderer);
@@ -813,11 +707,6 @@ void ImageVisual::DoSetOffStage( Actor& actor )
     mImpl->mResourceStatus = Toolkit::Visual::ResourceStatus::PREPARING;
   }
 
-  if( mImageUrl.IsValid() )
-  {
-    // Legacy support for deprecated Dali::Image
-    mImage.Reset();
-  }
   mLoading = false;
   mImpl->mRenderer.Reset();
   mPlacementActor.Reset();
@@ -828,7 +717,7 @@ void ImageVisual::DoCreatePropertyMap( Property::Map& map ) const
   map.Clear();
   map.Insert( Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE );
 
-  bool sync = IsSynchronousResourceLoading();
+  bool sync = IsSynchronousLoadingRequired();
   map.Insert( SYNCHRONOUS_LOADING, sync );
   if( mImageUrl.IsValid() )
   {
@@ -836,17 +725,6 @@ void ImageVisual::DoCreatePropertyMap( Property::Map& map ) const
     map.Insert( Toolkit::ImageVisual::Property::DESIRED_WIDTH, mDesiredSize.GetWidth() );
     map.Insert( Toolkit::ImageVisual::Property::DESIRED_HEIGHT, mDesiredSize.GetHeight() );
   }
-  else if( mImage )
-  {
-    map.Insert( Toolkit::ImageVisual::Property::DESIRED_WIDTH, static_cast<int>(mImage.GetWidth()) );
-    map.Insert( Toolkit::ImageVisual::Property::DESIRED_HEIGHT, static_cast<int>(mImage.GetHeight()) );
-
-    ResourceImage resourceImage = ResourceImage::DownCast(mImage);
-    if( resourceImage )
-    {
-      map.Insert( Toolkit::ImageVisual::Property::URL, resourceImage.GetUrl() );
-    }
-  }
 
   map.Insert( Toolkit::ImageVisual::Property::FITTING_MODE, mFittingMode );
   map.Insert( Toolkit::ImageVisual::Property::SAMPLING_MODE, mSamplingMode );
@@ -878,11 +756,6 @@ void ImageVisual::DoCreateInstancePropertyMap( Property::Map& map ) const
     map.Insert( Toolkit::ImageVisual::Property::DESIRED_WIDTH, mDesiredSize.GetWidth() );
     map.Insert( Toolkit::ImageVisual::Property::DESIRED_HEIGHT, mDesiredSize.GetHeight() );
   }
-  else if( mImage )
-  {
-    map.Insert( Toolkit::ImageVisual::Property::DESIRED_WIDTH, static_cast<int>(mImage.GetWidth()) );
-    map.Insert( Toolkit::ImageVisual::Property::DESIRED_HEIGHT, static_cast<int>(mImage.GetHeight()) );
-  }
 }
 
 void ImageVisual::OnDoAction( const Dali::Property::Index actionName, const Dali::Property::Value& attributes )
@@ -915,20 +788,6 @@ bool ImageVisual::IsResourceReady() const
            mImpl->mResourceStatus == Toolkit::Visual::ResourceStatus::FAILED );
 }
 
-void ImageVisual::ApplyImageToSampler( const Image& image )
-{
-  if( image )
-  {
-    TextureSet textureSet = mImpl->mRenderer.GetTextures();
-    DALI_ASSERT_DEBUG( textureSet ); // texture set should always exist by this time
-
-    TextureSetImage( textureSet, 0u, image );
-    Sampler sampler = Sampler::New();
-    sampler.SetWrapMode(  mWrapModeU, mWrapModeV  );
-    textureSet.SetSampler( 0u, sampler );
-  }
-}
-
 // From existing atlas manager
 void ImageVisual::UploadCompleted()
 {
@@ -969,22 +828,20 @@ void ImageVisual::UploadComplete( bool loadingSuccess, int32_t textureId, Textur
       mPlacementActor.Reset();
     }
 
-    if( loadingSuccess )
-    {
-      Sampler sampler = Sampler::New();
-      sampler.SetWrapMode(  mWrapModeU, mWrapModeV  );
-      textureSet.SetSampler( 0u, sampler );
-      mImpl->mRenderer.SetTextures(textureSet);
-    }
-    else
+    if( !loadingSuccess )
     {
-      Image brokenImage = mFactoryCache.GetBrokenVisualImage();
+      Texture brokenImage = mFactoryCache.GetBrokenVisualImage();
 
       textureSet = TextureSet::New();
+      textureSet.SetTexture(0u, brokenImage);
       mImpl->mRenderer.SetTextures( textureSet );
-
-      ApplyImageToSampler( brokenImage );
     }
+
+    Sampler sampler = Sampler::New();
+    sampler.SetWrapMode(  mWrapModeU, mWrapModeV  );
+    textureSet.SetSampler( 0u, sampler );
+    mImpl->mRenderer.SetTextures(textureSet);
+
   }
 
   // Storing TextureSet needed when renderer staged.
@@ -1002,6 +859,37 @@ void ImageVisual::UploadComplete( bool loadingSuccess, int32_t textureId, Textur
   {
     resourceStatus = Toolkit::Visual::ResourceStatus::FAILED;
   }
+
+  // use geometry if needed
+  if( loadingSuccess )
+  {
+    uint32_t firstElementCount{0u};
+    uint32_t secondElementCount{0u};
+    auto geometry = mFactoryCache.GetTextureManager().GetRenderGeometry(mTextureId, firstElementCount, secondElementCount);
+    if (mImpl->mRenderer && geometry)
+    {
+      mImpl->mRenderer.SetGeometry(geometry);
+      Dali::DevelRenderer::DrawCommand drawCommand{};
+      drawCommand.drawType = DevelRenderer::DrawType::INDEXED;
+
+      if (firstElementCount)
+      {
+        drawCommand.firstIndex = 0;
+        drawCommand.elementCount = firstElementCount;
+        drawCommand.queue = DevelRenderer::RENDER_QUEUE_OPAQUE;
+        DevelRenderer::AddDrawCommand(mImpl->mRenderer, drawCommand);
+      }
+
+      if (secondElementCount)
+      {
+        drawCommand.firstIndex = firstElementCount;
+        drawCommand.elementCount = secondElementCount;
+        drawCommand.queue = DevelRenderer::RENDER_QUEUE_TRANSPARENT;
+        DevelRenderer::AddDrawCommand(mImpl->mRenderer, drawCommand);
+      }
+    }
+  }
+
   // Signal to observers ( control ) that resources are ready. Must be all resources.
   ResourceReady( resourceStatus );
   mLoading = false;
@@ -1011,7 +899,7 @@ void ImageVisual::RemoveTexture()
 {
   if( mTextureId != TextureManager::INVALID_TEXTURE_ID )
   {
-    mFactoryCache.GetTextureManager().Remove( mTextureId );
+    mFactoryCache.GetTextureManager().Remove( mTextureId, this );
     mTextureId = TextureManager::INVALID_TEXTURE_ID;
   }
   else