Merge "Added New methods to cater for second step initialization" into devel/master
authorKimmo Hoikka <kimmo.hoikka@samsung.com>
Thu, 20 Oct 2016 15:14:53 +0000 (08:14 -0700)
committerGerrit Code Review <gerrit@review.vlan103.tizen.org>
Thu, 20 Oct 2016 15:14:53 +0000 (08:14 -0700)
1  2 
dali-toolkit/internal/visuals/image/image-visual.cpp
dali-toolkit/internal/visuals/image/image-visual.h

@@@ -16,7 -16,7 +16,7 @@@
   */
  
  // CLASS HEADER
 -#include "image-visual.h"
 +#include <dali-toolkit/internal/visuals/image/image-visual.h>
  
  // EXTERNAL HEADER
  #include <cstring> // for strncasecmp
@@@ -186,22 -186,40 +186,41 @@@ Geometry CreateGeometry( VisualFactoryC
    return geometry;
  }
  
- } //unnamed namespace
+ } // unnamed namespace
+ ImageVisualPtr ImageVisual::New( VisualFactoryCache& factoryCache )
+ {
+   return new ImageVisual( factoryCache );
+ }
+ ImageVisualPtr ImageVisual::New( VisualFactoryCache& factoryCache,
+                                  const std::string& imageUrl,
+                                  ImageDimensions size,
+                                  FittingMode::Type fittingMode,
+                                  Dali::SamplingMode::Type samplingMode )
+ {
+   return new ImageVisual( factoryCache, imageUrl, size, fittingMode, samplingMode );
+ }
+ ImageVisualPtr ImageVisual::New( VisualFactoryCache& factoryCache, const Image& image )
+ {
+   return new ImageVisual( factoryCache, image );
+ }
  
  ImageVisual::ImageVisual( VisualFactoryCache& factoryCache )
  : Visual::Base( factoryCache ),
    mImage(),
    mPixels(),
 +  mTextureSet(),
    mPixelArea( FULL_TEXTURE_RECT ),
    mPlacementActor(),
    mImageUrl(),
 +  mNativeFragmentShaderCode(),
    mDesiredSize(),
    mFittingMode( FittingMode::DEFAULT ),
    mSamplingMode( SamplingMode::DEFAULT ),
    mWrapModeU( WrapMode::DEFAULT ),
    mWrapModeV( WrapMode::DEFAULT ),
 -  mNativeFragmentShaderCode(),
    mNativeImageFlag( false )
  {
  }
@@@ -214,16 -232,15 +233,16 @@@ ImageVisual::ImageVisual( VisualFactory
  : Visual::Base( factoryCache ),
    mImage(),
    mPixels(),
 +  mTextureSet(),
    mPixelArea( FULL_TEXTURE_RECT ),
    mPlacementActor(),
    mImageUrl( imageUrl ),
 +  mNativeFragmentShaderCode(),
    mDesiredSize( size ),
    mFittingMode( fittingMode ),
    mSamplingMode( samplingMode ),
    mWrapModeU( WrapMode::DEFAULT ),
    mWrapModeV( WrapMode::DEFAULT ),
 -  mNativeFragmentShaderCode(),
    mNativeImageFlag( false )
  {
  }
@@@ -235,12 -252,12 +254,12 @@@ ImageVisual::ImageVisual( VisualFactory
    mPixelArea( FULL_TEXTURE_RECT ),
    mPlacementActor(),
    mImageUrl(),
 +  mNativeFragmentShaderCode(),
    mDesiredSize(),
    mFittingMode( FittingMode::DEFAULT ),
    mSamplingMode( SamplingMode::DEFAULT ),
    mWrapModeU( WrapMode::DEFAULT ),
    mWrapModeV( WrapMode::DEFAULT ),
 -  mNativeFragmentShaderCode(),
    mNativeImageFlag( false )
  {
    NativeImage newNativeImage = NativeImage::DownCast( image );
@@@ -275,17 -292,13 +294,17 @@@ void ImageVisual::DoInitialize( Actor& 
      Property::Value* fittingValue = propertyMap.Find( Toolkit::ImageVisual::Property::FITTING_MODE, IMAGE_FITTING_MODE );
      if( fittingValue )
      {
 -      Scripting::GetEnumerationProperty( *fittingValue, FITTING_MODE_TABLE, FITTING_MODE_TABLE_COUNT, mFittingMode );
 +      int value;
 +      Scripting::GetEnumerationProperty( *fittingValue, FITTING_MODE_TABLE, FITTING_MODE_TABLE_COUNT, value );
 +      mFittingMode = Dali::FittingMode::Type( value );
      }
  
      Property::Value* samplingValue = propertyMap.Find( Toolkit::ImageVisual::Property::SAMPLING_MODE, IMAGE_SAMPLING_MODE );
      if( samplingValue )
      {
 -      Scripting::GetEnumerationProperty( *samplingValue, SAMPLING_MODE_TABLE, SAMPLING_MODE_TABLE_COUNT, mSamplingMode );
 +      int value;
 +      Scripting::GetEnumerationProperty( *samplingValue, SAMPLING_MODE_TABLE, SAMPLING_MODE_TABLE_COUNT, value );
 +      mSamplingMode = Dali::SamplingMode::Type( value );
      }
  
      int desiredWidth = 0;
      Property::Value* wrapModeValueU = propertyMap.Find( Toolkit::ImageVisual::Property::WRAP_MODE_U, IMAGE_WRAP_MODE_U );
      if( wrapModeValueU )
      {
 -      Scripting::GetEnumerationProperty( *wrapModeValueU, WRAP_MODE_TABLE, WRAP_MODE_TABLE_COUNT, mWrapModeU );
 +      int value;
 +      Scripting::GetEnumerationProperty( *wrapModeValueU, WRAP_MODE_TABLE, WRAP_MODE_TABLE_COUNT, value );
 +      mWrapModeU = Dali::WrapMode::Type( value );
      }
  
      Property::Value* wrapModeValueV = propertyMap.Find( Toolkit::ImageVisual::Property::WRAP_MODE_V, IMAGE_WRAP_MODE_V );
      if( wrapModeValueV )
      {
 -      Scripting::GetEnumerationProperty( *wrapModeValueV, WRAP_MODE_TABLE, WRAP_MODE_TABLE_COUNT, mWrapModeV );
 +      int value;
 +      Scripting::GetEnumerationProperty( *wrapModeValueV, WRAP_MODE_TABLE, WRAP_MODE_TABLE_COUNT, value );
 +      mWrapModeV = Dali::WrapMode::Type( value );
      }
  
      mDesiredSize = ImageDimensions( desiredWidth, desiredHeight );
@@@ -388,7 -397,7 +407,7 @@@ void ImageVisual::GetNaturalSize( Vecto
    naturalSize = Vector2::ZERO;
  }
  
 -Renderer ImageVisual::CreateRenderer() const
 +void ImageVisual::CreateRenderer()
  {
    Geometry geometry;
    Shader shader;
    // Renderer can't be shared between NativeImage and other image types.
    if( !mNativeFragmentShaderCode.empty() )
    {
 -    return CreateNativeImageRenderer();
 +    CreateNativeImageRenderer();
 +    return;
    }
  
    if( !mImpl->mCustomShader )
      }
    }
  
 -  Renderer renderer = Renderer::New( geometry, shader );
 -
 -  return renderer;
 +  mImpl->mRenderer = Renderer::New( geometry, shader );
 +  // apply the texture set as well so it's only done in one place
 +  DALI_ASSERT_DEBUG( mTextureSet );
 +  mImpl->mRenderer.SetTextures( mTextureSet );
  }
  
 -Renderer ImageVisual::CreateNativeImageRenderer() const
 +void ImageVisual::CreateNativeImageRenderer()
  {
    Geometry geometry;
    Shader shader;
      }
    }
  
 -  TextureSet textureSet = TextureSet::New();
 -  Renderer renderer = Renderer::New( geometry, shader );
 -  renderer.SetTextures( textureSet );
 -  return renderer;
 +  mImpl->mRenderer = Renderer::New( geometry, shader );
 +  // apply the texture set as well so it's only done in one place
 +  DALI_ASSERT_DEBUG( mTextureSet );
 +  mImpl->mRenderer.SetTextures( mTextureSet );
  }
  
  
@@@ -480,49 -487,64 +499,49 @@@ void ImageVisual::LoadResourceSynchrono
    }
  }
  
 -Image ImageVisual::LoadImage( const std::string& url, bool synchronousLoading )
 +void ImageVisual::CreateTextureSet( Vector4& textureRect, const std::string& url, bool synchronousLoading, bool attemptAtlasing )
  {
 -  if( synchronousLoading )
 -  {
 -    if( !mPixels )
 -    {
 -      // use broken image
 -      return VisualFactoryCache::GetBrokenVisualImage();
 -    }
 -    Atlas image = Atlas::New( mPixels.GetWidth(), mPixels.GetHeight(), mPixels.GetPixelFormat() );
 -    image.Upload( mPixels, 0, 0 );
 -    return image;
 -  }
 -  else
 -  {
 -    ResourceImage resourceImage = Dali::ResourceImage::New( url, mDesiredSize, mFittingMode, mSamplingMode );
 -    resourceImage.LoadingFinishedSignal().Connect( this, &ImageVisual::OnImageLoaded );
 -    return resourceImage;
 -  }
 -}
 -
 -TextureSet ImageVisual::CreateTextureSet( Vector4& textureRect, const std::string& url, bool synchronousLoading )
 -{
 -  TextureSet textureSet;
    textureRect = FULL_TEXTURE_RECT;
    if( synchronousLoading )
    {
      if( !mPixels )
      {
        // use broken image
 -      textureSet = TextureSet::New();
 -      TextureSetImage( textureSet, 0u, VisualFactoryCache::GetBrokenVisualImage() );
 +      mTextureSet = TextureSet::New();
 +      TextureSetImage( mTextureSet, 0u, VisualFactoryCache::GetBrokenVisualImage() );
      }
      else
      {
 -      textureSet = mFactoryCache.GetAtlasManager()->Add(textureRect, mPixels );
 -      mImpl->mFlags |= Impl::IS_ATLASING_APPLIED;
 -      if( !textureSet ) // big image, no atlasing
 +      if( attemptAtlasing )
 +      {
 +        mTextureSet = mFactoryCache.GetAtlasManager()->Add(textureRect, mPixels );
 +        mImpl->mFlags |= Impl::IS_ATLASING_APPLIED;
 +      }
 +      if( !mTextureSet ) // big image, no atlasing or atlasing failed
        {
          mImpl->mFlags &= ~Impl::IS_ATLASING_APPLIED;
 -        Atlas image = Atlas::New( mPixels.GetWidth(), mPixels.GetHeight(), mPixels.GetPixelFormat() );
 -        image.Upload( mPixels, 0, 0 );
 -        textureSet = TextureSet::New();
 -        TextureSetImage( textureSet, 0u, image );
 +        Texture texture = Texture::New( Dali::TextureType::TEXTURE_2D, mPixels.GetPixelFormat(),
 +                                        mPixels.GetWidth(), mPixels.GetHeight() );
 +        texture.Upload( mPixels );
 +        mTextureSet = TextureSet::New();
 +        mTextureSet.SetTexture( 0u, texture );
        }
      }
    }
    else
    {
 -    textureSet = mFactoryCache.GetAtlasManager()->Add(textureRect, url, mDesiredSize, mFittingMode, true, this );
 -    mImpl->mFlags |= Impl::IS_ATLASING_APPLIED;
 -    if( !textureSet ) // big image, no atlasing
 +    if( attemptAtlasing )
 +    {
 +      mTextureSet = mFactoryCache.GetAtlasManager()->Add(textureRect, url, mDesiredSize, mFittingMode, true, this );
 +      mImpl->mFlags |= Impl::IS_ATLASING_APPLIED;
 +    }
 +    if( !mTextureSet ) // big image, no atlasing or atlasing failed
      {
        mImpl->mFlags &= ~Impl::IS_ATLASING_APPLIED;
        ResourceImage resourceImage = Dali::ResourceImage::New( url, mDesiredSize, mFittingMode, mSamplingMode );
        resourceImage.LoadingFinishedSignal().Connect( this, &ImageVisual::OnImageLoaded );
 -      textureSet = TextureSet::New();
 -      TextureSetImage( textureSet, 0u, resourceImage );
 +      mTextureSet = TextureSet::New();
 +      TextureSetImage( mTextureSet, 0u, resourceImage );
      }
    }
  
    {
      Sampler sampler = Sampler::New();
      sampler.SetWrapMode(  mWrapModeU, mWrapModeV  );
 -    textureSet.SetSampler( 0u, sampler );
 +    mTextureSet.SetSampler( 0u, sampler );
    }
 -
 -  return textureSet;
  }
  
  void ImageVisual::InitializeRenderer( const std::string& imageUrl )
      if( !mImpl->mRenderer ) // new renderer is needed
      {
        Vector4 atlasRect;
 -      TextureSet textureSet = CreateTextureSet(atlasRect, imageUrl, IsSynchronousResourceLoading() );
 -      Geometry geometry = CreateGeometry( mFactoryCache, ImageDimensions( 1, 1 ) );
 -      Shader shader( GetImageShader(mFactoryCache, mImpl->mFlags & Impl::IS_ATLASING_APPLIED, defaultWrapMode) );
 -      mImpl->mRenderer = Renderer::New( geometry, shader );
 -      mImpl->mRenderer.SetTextures( textureSet );
 +      // texture set has to be created first as we need to know if atlasing succeeded or not
 +      // when selecting the shader
 +      CreateTextureSet( atlasRect, imageUrl, IsSynchronousResourceLoading(), true );
 +      CreateRenderer();
  
        if( mImpl->mFlags & Impl::IS_ATLASING_APPLIED ) // the texture is packed inside atlas
        {
    {
      // for custom shader or remote image, renderer is not cached and atlas is not applied
      mImpl->mFlags &= ~Impl::IS_FROM_CACHE;
 -    mImpl->mRenderer = CreateRenderer();
 -    Image image = LoadImage( imageUrl, IsSynchronousResourceLoading() );
 -    ApplyImageToSampler( image );
 +    Vector4 atlasRect; // ignored in this case
 +    CreateTextureSet( atlasRect, imageUrl, IsSynchronousResourceLoading(), false );
 +    CreateRenderer();
    }
  }
  
@@@ -599,9 -624,7 +618,9 @@@ void ImageVisual::InitializeRenderer( c
  {
    mImpl->mFlags &= ~Impl::IS_FROM_CACHE;
  
 -  mImpl->mRenderer = CreateRenderer();
 +  // don't reuse CreateTextureSet
 +  mTextureSet = TextureSet::New();
 +  CreateRenderer();
  
    if( image )
    {
@@@ -661,7 -684,6 +680,7 @@@ void ImageVisual::DoSetOffStage( Actor
      mImpl->mRenderer.Reset();
    }
    mPlacementActor.Reset();
 +  mTextureSet.Reset(); // release texture when going offstage
  }
  
  void ImageVisual::DoCreatePropertyMap( Property::Map& map ) const
@@@ -749,12 -771,16 +768,12 @@@ void ImageVisual::ApplyImageToSampler( 
  {
    if( image )
    {
 -    TextureSet textureSet = mImpl->mRenderer.GetTextures();
 -    if( !textureSet )
 -    {
 -      textureSet = TextureSet::New();
 -      mImpl->mRenderer.SetTextures( textureSet );
 -    }
 -    TextureSetImage( textureSet, 0u, image );
 +    DALI_ASSERT_DEBUG( mTextureSet ); // texture set should always exist by this time
 +
 +    TextureSetImage( mTextureSet, 0u, image );
      Sampler sampler = Sampler::New();
      sampler.SetWrapMode(  mWrapModeU, mWrapModeV  );
 -    textureSet.SetSampler( 0u, sampler );
 +    mTextureSet.SetSampler( 0u, sampler );
    }
  }
  
@@@ -774,6 -800,8 +793,6 @@@ void ImageVisual::CleanCache(const std:
  {
    if( IsFromCache() )
    {
 -    TextureSet textureSet = mImpl->mRenderer.GetTextures();
 -
      Vector4 atlasRect( 0.f, 0.f, 1.f, 1.f );
      Property::Index index = mImpl->mRenderer.GetPropertyIndex( ATLAS_RECT_UNIFORM_NAME );
      if( index != Property::INVALID_INDEX )
      mImpl->mRenderer.Reset();
      if( mFactoryCache.CleanRendererCache( url ) && index != Property::INVALID_INDEX )
      {
 -      mFactoryCache.GetAtlasManager()->Remove( textureSet, atlasRect );
 +      mFactoryCache.GetAtlasManager()->Remove( mTextureSet, atlasRect );
      }
    }
  }
   *
   */
  
- // INTERNAL INCLUDES
- #include <dali-toolkit/internal/visuals/visual-base-impl.h>
- #include <dali-toolkit/devel-api/image-loader/atlas-upload-observer.h>
  // EXTERNAL INCLUDES
+ #include <dali/public-api/common/intrusive-ptr.h>
  #include <dali/public-api/images/image.h>
  #include <dali/public-api/images/image-operations.h>
  #include <dali/public-api/images/resource-image.h>
  #include <dali/devel-api/object/weak-handle.h>
  
+ // INTERNAL INCLUDES
+ #include <dali-toolkit/internal/visuals/visual-base-impl.h>
+ #include <dali-toolkit/devel-api/image-loader/atlas-upload-observer.h>
  namespace Dali
  {
  
@@@ -79,14 -80,15 +80,15 @@@ class ImageVisual: public Visual::Base
  public:
  
    /**
-    * @brief Constructor.
+    * @brief Create a new image visual.
     *
-    * @param[in] factoryCache The VisualFactoryCache object
+    * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object
+    * @return A smart-pointer to the newly allocated visual.
     */
-   ImageVisual( VisualFactoryCache& factoryCache );
+   static ImageVisualPtr New( VisualFactoryCache& factoryCache );
  
    /**
-    * @brief Constructor with a URL.
+    * @brief Create a new image visual with a URL.
     *
     * The visual will load the Image asynchronously when the associated actor is put on stage, and destroy the image when it is off stage
     *
     * @param[in] fittingMode The FittingMode of the resource to load
     * @param[in] samplingMode The SamplingMode of the resource to load
     */
-   ImageVisual( VisualFactoryCache& factoryCache,
-                const std::string& imageUrl,
-                ImageDimensions size=ImageDimensions(),
-                FittingMode::Type fittingMode = FittingMode::DEFAULT,
-                Dali::SamplingMode::Type samplingMode = SamplingMode::BOX_THEN_LINEAR );
+   static ImageVisualPtr New( VisualFactoryCache& factoryCache,
+                              const std::string& imageUrl,
+                              ImageDimensions size = ImageDimensions(),
+                              FittingMode::Type fittingMode = FittingMode::DEFAULT,
+                              Dali::SamplingMode::Type samplingMode = SamplingMode::BOX_THEN_LINEAR );
  
    /**
-    * @brief Constructor with an Image type.
+    * @brief Create a new image visual with an Image type.
     *
     * @param[in] factoryCache The VisualFactoryCache object
     * @param[in] image The image to use
     */
-   ImageVisual( VisualFactoryCache& factoryCache, const Image& image );
-   /**
-    * @brief A reference counted object may only be deleted by calling Unreference().
-    */
-   ~ImageVisual();
+   static ImageVisualPtr New( VisualFactoryCache& factoryCache, const Image& image );
  
  public:  // from Visual
  
    virtual Dali::Property::Value DoGetProperty( Dali::Property::Index index );
  
  protected:
+   /**
+    * @brief Constructor.
+    *
+    * @param[in] factoryCache The VisualFactoryCache object
+    */
+   ImageVisual( VisualFactoryCache& factoryCache );
+   /**
+    * @brief Constructor with a URL.
+    *
+    * The visual will load the Image asynchronously when the associated actor is put on stage, and destroy the image when it is off stage
+    *
+    * @param[in] factoryCache The VisualFactoryCache object
+    * @param[in] imageUrl The URL of the image resource to use
+    * @param[in] size The width and height to fit the loaded image to.
+    * @param[in] fittingMode The FittingMode of the resource to load
+    * @param[in] samplingMode The SamplingMode of the resource to load
+    */
+   ImageVisual( VisualFactoryCache& factoryCache,
+                const std::string& imageUrl,
+                ImageDimensions size,
+                FittingMode::Type fittingMode,
+                Dali::SamplingMode::Type samplingMode );
+   /**
+    * @brief Constructor with an Image type.
+    *
+    * @param[in] factoryCache The VisualFactoryCache object
+    * @param[in] image The image to use
+    */
+   ImageVisual( VisualFactoryCache& factoryCache, const Image& image );
+   /**
+    * @brief A reference counted object may only be deleted by calling Unreference().
+    */
+   virtual ~ImageVisual();
    /**
     * @copydoc Visual::Base::DoInitialize
     */
@@@ -196,13 -231,17 +231,13 @@@ private
  
    /**
     * @brief Creates the Dali::Renderer (potentially from the renderer cache), initializing it
 -   *
 -   * @return Returns the created Dali::Renderer
     */
 -  Renderer CreateRenderer() const;
 +  void CreateRenderer();
  
    /**
     * @brief Creates the Dali::Renderer for NativeImage with custom sampler type and prefix, initializing it
 -   *
 -   * @return Returns the created Dali::Renderer
     */
 -  Renderer CreateNativeImageRenderer() const;
 +  void CreateNativeImageRenderer();
  
    /**
     * @brief Query whether resources requires to be loaded synchronously.
    void LoadResourceSynchronously();
  
    /**
 -   * Load the image.
 -   * @param[in] url The URL of the image resource to use.
 -   * @param[in] synchronousLoading If true, the resource is loaded synchronously, otherwise asynchronously.
 -   */
 -  Image LoadImage( const std::string& url, bool synchronousLoading );
 -
 -  /**
 -   * Load the image and create a texture set to hold the texture, with automatic atlasing applied.
 -   * @param [out] textureRect The texture area of the resource image in the atlas.
 +   * Creates the texture set and adds the texture to it
 +   * @param[out] textureRect The texture area of the texture in the atlas.
     * @param[in] url The URL of the image resource to use.
     * @param[in] synchronousLoading If true, the resource is loaded synchronously, otherwise asynchronously.
 +   * @param[in] attemptAtlasing If true will attempt atlasing, otherwise create unique texture
     */
 -  TextureSet CreateTextureSet( Vector4& textureRect, const std::string& url, bool synchronousLoading );
 +  void CreateTextureSet( Vector4& textureRect, const std::string& url, bool synchronousLoading, bool attemptAtlasing );
  
    /**
     * Callback function of image resource loading succeed
    void SetNativeFragmentShaderCode( Dali::NativeImage& nativeImage );
  
  private:
 +
    Image mImage;
    PixelData mPixels;
 +  TextureSet mTextureSet;
    Vector4 mPixelArea;
    WeakHandle<Actor> mPlacementActor;
 -
    std::string mImageUrl;
 -  Dali::ImageDimensions mDesiredSize;
 -  Dali::FittingMode::Type mFittingMode;
 -  Dali::SamplingMode::Type mSamplingMode;
 -  Dali::WrapMode::Type mWrapModeU;
 -  Dali::WrapMode::Type mWrapModeV;
 -
    std::string mNativeFragmentShaderCode;
 -  bool mNativeImageFlag;
 +
 +  Dali::ImageDimensions mDesiredSize;
 +  Dali::FittingMode::Type mFittingMode:3;
 +  Dali::SamplingMode::Type mSamplingMode:4;
 +  Dali::WrapMode::Type mWrapModeU:3;
 +  Dali::WrapMode::Type mWrapModeV:3;
 +  bool mNativeImageFlag:1;
  };
  
  } // namespace Internal