Use RegisterUniqueProperty for some more renderers
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / gradient / gradient-visual.cpp
index 4ea6a28..f3028c4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include "gradient-visual.h"
 
 // EXTERNAL INCLUDES
-#include <typeinfo>
+#include <dali/devel-api/rendering/renderer-devel.h>
+#include <dali/devel-api/scripting/enum-helper.h>
+#include <dali/devel-api/scripting/scripting.h>
 #include <dali/integration-api/debug.h>
 #include <dali/public-api/common/dali-vector.h>
-#include <dali/public-api/images/buffer-image.h>
 #include <dali/public-api/object/property-array.h>
-#include <dali/devel-api/scripting/enum-helper.h>
-#include <dali/devel-api/scripting/scripting.h>
+#include <typeinfo>
 
 // INTERNAL INCLUDES
-#include <dali-toolkit/public-api/visuals/gradient-visual-properties.h>
-#include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
-#include <dali-toolkit/internal/visuals/visual-factory-impl.h>
-#include <dali-toolkit/internal/visuals/visual-factory-cache.h>
-#include <dali-toolkit/internal/visuals/visual-string-constants.h>
+#include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
 #include <dali-toolkit/internal/visuals/gradient/linear-gradient.h>
 #include <dali-toolkit/internal/visuals/gradient/radial-gradient.h>
 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
+#include <dali-toolkit/internal/visuals/visual-factory-cache.h>
+#include <dali-toolkit/internal/visuals/visual-factory-impl.h>
+#include <dali-toolkit/internal/visuals/visual-string-constants.h>
+#include <dali-toolkit/public-api/visuals/gradient-visual-properties.h>
+#include <dali-toolkit/public-api/visuals/visual-properties.h>
 
 namespace Dali
 {
-
 namespace Toolkit
 {
-
 namespace Internal
 {
-
 namespace
 {
-// properties: linear gradient
-const char * const START_POSITION_NAME("startPosition"); // Property::VECTOR2
-const char * const END_POSITION_NAME("endPosition"); // Property::VECTOR2
-
-// properties: radial gradient
-const char * const CENTER_NAME("center"); // Property::VECTOR2
-const char * const RADIUS_NAME("radius"); // Property::FLOAT
-
-// properties: linear&radial gradient
-const char * const STOP_OFFSET_NAME("stopOffset"); // Property::Array FLOAT
-const char * const STOP_COLOR_NAME("stopColor"); // Property::Array VECTOR4
-const char * const UNITS_NAME("units"); // Property::String  "userSpaceOnUse | objectBoundingBox"
-const char * const SPREAD_METHOD_NAME("spreadMethod"); // Property::String  "pad | reflect | repeat"
-
-DALI_ENUM_TO_STRING_TABLE_BEGIN( UNITS )
-DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::GradientVisual::Units, OBJECT_BOUNDING_BOX )
-DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::GradientVisual::Units, USER_SPACE )
-DALI_ENUM_TO_STRING_TABLE_END( UNITS )
-
-DALI_ENUM_TO_STRING_TABLE_BEGIN( SPREAD_METHOD )
-DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::GradientVisual::SpreadMethod, PAD )
-DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::GradientVisual::SpreadMethod, REFLECT )
-DALI_ENUM_TO_STRING_WITH_SCOPE( Toolkit::GradientVisual::SpreadMethod, REPEAT )
-DALI_ENUM_TO_STRING_TABLE_END( SPREAD_METHOD )
+const int CUSTOM_PROPERTY_COUNT(11); // 5 transform properties + alignment + corner/border
+
+DALI_ENUM_TO_STRING_TABLE_BEGIN(UNITS)
+  DALI_ENUM_TO_STRING_WITH_SCOPE(Toolkit::GradientVisual::Units, OBJECT_BOUNDING_BOX)
+  DALI_ENUM_TO_STRING_WITH_SCOPE(Toolkit::GradientVisual::Units, USER_SPACE)
+DALI_ENUM_TO_STRING_TABLE_END(UNITS)
+
+DALI_ENUM_TO_STRING_TABLE_BEGIN(SPREAD_METHOD)
+  DALI_ENUM_TO_STRING_WITH_SCOPE(Toolkit::GradientVisual::SpreadMethod, PAD)
+  DALI_ENUM_TO_STRING_WITH_SCOPE(Toolkit::GradientVisual::SpreadMethod, REFLECT)
+  DALI_ENUM_TO_STRING_WITH_SCOPE(Toolkit::GradientVisual::SpreadMethod, REPEAT)
+DALI_ENUM_TO_STRING_TABLE_END(SPREAD_METHOD)
 
 // uniform names
-const char * const UNIFORM_ALIGNMENT_MATRIX_NAME( "uAlignmentMatrix" );
+const char* const UNIFORM_ALIGNMENT_MATRIX_NAME("uAlignmentMatrix");
 
 // default offset value
 const unsigned int DEFAULT_OFFSET_MINIMUM = 0.0f;
 const unsigned int DEFAULT_OFFSET_MAXIMUM = 1.0f;
 
-VisualFactoryCache::ShaderType GetShaderType( GradientVisual::Type type, Toolkit::GradientVisual::Units::Type units )
-{
-  if( type == GradientVisual::LINEAR )
-  {
-   if( units == Toolkit::GradientVisual::Units::USER_SPACE )
-   {
-     return VisualFactoryCache::GRADIENT_SHADER_LINEAR_USER_SPACE;
-   }
-   return VisualFactoryCache::GRADIENT_SHADER_LINEAR_BOUNDING_BOX;
-  }
-  else if( units == Toolkit::GradientVisual::Units::USER_SPACE )
+VisualFactoryCache::ShaderType SHADER_TYPE_TABLE[16] =
   {
-    return VisualFactoryCache::GRADIENT_SHADER_RADIAL_USER_SPACE;
-  }
-
-  return VisualFactoryCache::GRADIENT_SHADER_RADIAL_BOUNDING_BOX;
-}
-
-const char* VERTEX_SHADER[] =
-{
-// vertex shader for gradient units as OBJECT_BOUNDING_BOX
- DALI_COMPOSE_SHADER(
-  attribute mediump vec2 aPosition;\n
-  uniform mediump mat4 uMvpMatrix;\n
-  uniform mediump vec3 uSize;\n
-  uniform mediump mat3 uAlignmentMatrix;\n
-  varying mediump vec2 vTexCoord;\n
-  \n
-
-  //Visual size and offset
-  uniform mediump vec2 offset;\n
-  uniform mediump vec2 size;\n
-  uniform mediump vec4 offsetSizeMode;\n
-  uniform mediump vec2 origin;\n
-  uniform mediump vec2 anchorPoint;\n
-
-  vec4 ComputeVertexPosition()\n
-  {\n
-    vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw );\n
-    vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy);\n
-    return vec4( (aPosition + anchorPoint)*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0 );\n
-  }\n
-
-  void main()\n
-  {\n
-    mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);\n
-    vTexCoord = (uAlignmentMatrix*vertexPosition.xyw).xy;\n
-    \n
-    gl_Position = uMvpMatrix * ComputeVertexPosition();\n
-  }\n
-),
-
-// vertex shader for gradient units as USER_SPACE
-DALI_COMPOSE_SHADER(
-  attribute mediump vec2 aPosition;\n
-  uniform mediump mat4 uMvpMatrix;\n
-  uniform mediump vec3 uSize;\n
-  uniform mediump mat3 uAlignmentMatrix;\n
-  varying mediump vec2 vTexCoord;\n
-  \n
-
-  //Visual size and offset
-  uniform mediump vec2 offset;\n
-  uniform mediump vec2 size;\n
-  uniform mediump vec4 offsetSizeMode;\n
-  uniform mediump vec2 origin;\n
-  uniform mediump vec2 anchorPoint;\n
-
-  vec4 ComputeVertexPosition()\n
-  {\n
-    vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw );\n
-    vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy);\n
-    return vec4( (aPosition + anchorPoint)*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0 );\n
-  }\n
-
-  void main()\n
-  {\n
-    mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);\n
-    vertexPosition.xyz *= uSize;\n
-    gl_Position = uMvpMatrix * ComputeVertexPosition();\n
-    \n
-    vTexCoord = (uAlignmentMatrix*vertexPosition.xyw).xy;\n
-  }\n
-)
+    VisualFactoryCache::GRADIENT_SHADER_LINEAR_BOUNDING_BOX,
+    VisualFactoryCache::GRADIENT_SHADER_LINEAR_BOUNDING_BOX_ROUNDED_CORNER,
+    VisualFactoryCache::GRADIENT_SHADER_LINEAR_BOUNDING_BOX_BORDERLINE,
+    VisualFactoryCache::GRADIENT_SHADER_LINEAR_BOUNDING_BOX_ROUNDED_BORDERLINE,
+    VisualFactoryCache::GRADIENT_SHADER_LINEAR_USER_SPACE,
+    VisualFactoryCache::GRADIENT_SHADER_LINEAR_USER_SPACE_ROUNDED_CORNER,
+    VisualFactoryCache::GRADIENT_SHADER_LINEAR_USER_SPACE_BORDERLINE,
+    VisualFactoryCache::GRADIENT_SHADER_LINEAR_USER_SPACE_ROUNDED_BORDERLINE,
+    VisualFactoryCache::GRADIENT_SHADER_RADIAL_BOUNDING_BOX,
+    VisualFactoryCache::GRADIENT_SHADER_RADIAL_BOUNDING_BOX_ROUNDED_CORNER,
+    VisualFactoryCache::GRADIENT_SHADER_RADIAL_BOUNDING_BOX_BORDERLINE,
+    VisualFactoryCache::GRADIENT_SHADER_RADIAL_BOUNDING_BOX_ROUNDED_BORDERLINE,
+    VisualFactoryCache::GRADIENT_SHADER_RADIAL_USER_SPACE,
+    VisualFactoryCache::GRADIENT_SHADER_RADIAL_USER_SPACE_ROUNDED_CORNER,
+    VisualFactoryCache::GRADIENT_SHADER_RADIAL_USER_SPACE_BORDERLINE,
+    VisualFactoryCache::GRADIENT_SHADER_RADIAL_USER_SPACE_ROUNDED_BORDERLINE,
 };
 
-const char* FRAGMENT_SHADER[] =
+// enum of required list when we select shader
+enum GradientVisualRequireFlag
 {
-// fragment shader for linear gradient
-DALI_COMPOSE_SHADER(
-  uniform sampler2D sTexture;\n // sampler1D?
-  uniform lowp vec4 uColor;\n
-  uniform lowp vec3 mixColor;\n
-  uniform lowp float opacity;\n
-  varying mediump vec2 vTexCoord;\n
-  \n
-  void main()\n
-  {\n
-    gl_FragColor = texture2D( sTexture, vec2( vTexCoord.y, 0.5 ) ) * vec4(mixColor*opacity, opacity) * uColor;\n
-  }\n
-),
-
-// fragment shader for radial gradient
-DALI_COMPOSE_SHADER(
-  uniform sampler2D sTexture;\n // sampler1D?
-  uniform lowp vec4 uColor;\n
-  uniform lowp vec3 mixColor;\n
-  uniform lowp float opacity;\n
-  varying mediump vec2 vTexCoord;\n
-  \n
-  void main()\n
-  {\n
-    gl_FragColor = texture2D( sTexture, vec2( length(vTexCoord), 0.5 ) ) * vec4(mixColor*opacity, opacity) * uColor;\n
-  }\n
-)
+  DEFAULT        = 0,
+  ROUNDED_CORNER = 1 << 0,
+  BORDERLINE     = 1 << 1,
+  USER_SPACE     = 1 << 2,
+  RADIAL         = 1 << 3,
 };
 
-Dali::WrapMode::Type GetWrapMode( Toolkit::GradientVisual::SpreadMethod::Type spread )
+Dali::WrapMode::Type GetWrapMode(Toolkit::GradientVisual::SpreadMethod::Type spread)
 {
   switch(spread)
   {
@@ -219,17 +118,18 @@ Dali::WrapMode::Type GetWrapMode( Toolkit::GradientVisual::SpreadMethod::Type sp
 
 } // unnamed namespace
 
-GradientVisualPtr GradientVisual::New( VisualFactoryCache& factoryCache, const Property::Map& properties )
+GradientVisualPtr GradientVisual::New(VisualFactoryCache& factoryCache, const Property::Map& properties)
 {
-  GradientVisualPtr gradientVisualPtr( new GradientVisual( factoryCache ) );
-  gradientVisualPtr->SetProperties( properties );
+  GradientVisualPtr gradientVisualPtr(new GradientVisual(factoryCache));
+  gradientVisualPtr->SetProperties(properties);
+  gradientVisualPtr->Initialize();
   return gradientVisualPtr;
 }
 
-GradientVisual::GradientVisual( VisualFactoryCache& factoryCache )
-: Visual::Base( factoryCache ),
-  mGradientType( LINEAR ),
-  mIsOpaque( true )
+GradientVisual::GradientVisual(VisualFactoryCache& factoryCache)
+: Visual::Base(factoryCache, Visual::FittingMode::FILL, Toolkit::Visual::GRADIENT),
+  mGradientType(LINEAR),
+  mIsOpaque(true)
 {
   mImpl->mFlags |= Impl::IS_PREMULTIPLIED_ALPHA;
 }
@@ -238,157 +138,163 @@ GradientVisual::~GradientVisual()
 {
 }
 
-void GradientVisual::DoSetProperties( const Property::Map& propertyMap )
+void GradientVisual::DoSetProperties(const Property::Map& propertyMap)
 {
   Toolkit::GradientVisual::Units::Type gradientUnits = Toolkit::GradientVisual::Units::OBJECT_BOUNDING_BOX;
 
-  Property::Value* unitsValue = propertyMap.Find( Toolkit::GradientVisual::Property::UNITS, UNITS_NAME );
-  if( unitsValue )
+  Property::Value* unitsValue = propertyMap.Find(Toolkit::GradientVisual::Property::UNITS, UNITS_NAME);
+  if(unitsValue)
   {
-    Scripting::GetEnumerationProperty( *unitsValue, UNITS_TABLE, UNITS_TABLE_COUNT, gradientUnits );
+    Scripting::GetEnumerationProperty(*unitsValue, UNITS_TABLE, UNITS_TABLE_COUNT, gradientUnits);
   }
 
-  mGradientType = LINEAR;
-  if( propertyMap.Find( Toolkit::GradientVisual::Property::RADIUS, RADIUS_NAME ) )
+  mGradientType = Type::LINEAR;
+  if(propertyMap.Find(Toolkit::GradientVisual::Property::RADIUS, RADIUS_NAME))
   {
-    mGradientType = RADIAL;
+    mGradientType = Type::RADIAL;
   }
 
-  if( NewGradient( mGradientType, propertyMap ) )
+  if(NewGradient(mGradientType, propertyMap))
   {
-    mGradient->SetGradientUnits( gradientUnits );
+    mGradient->SetGradientUnits(gradientUnits);
     mGradientTransform = mGradient->GetAlignmentTransform();
   }
   else
   {
-    DALI_LOG_ERROR( "Fail to provide valid properties to create a GradientVisual object\n" );
+    DALI_LOG_ERROR("Fail to provide valid properties to create a GradientVisual object\n");
   }
 }
 
 void GradientVisual::OnSetTransform()
 {
-  if( mImpl->mRenderer )
+  if(mImpl->mRenderer)
   {
-    mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT );
+    mImpl->mTransform.RegisterUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT);
   }
 }
 
-void GradientVisual::DoSetOnStage( Actor& actor )
+void GradientVisual::DoSetOnScene(Actor& actor)
 {
-  InitializeRenderer();
+  actor.AddRenderer(mImpl->mRenderer);
+
+  // Gradient Visual generated and ready to display
+  ResourceReady(Toolkit::Visual::ResourceStatus::READY);
+}
 
-  actor.AddRenderer( mImpl->mRenderer );
+void GradientVisual::UpdateShader()
+{
+  if(mImpl->mRenderer)
+  {
+    Shader shader = GenerateShader();
+    mImpl->mRenderer.SetShader(shader);
+  }
 }
 
-void GradientVisual::DoCreatePropertyMap( Property::Map& map ) const
+void GradientVisual::DoCreatePropertyMap(Property::Map& map) const
 {
   map.Clear();
-  map.Insert( Toolkit::DevelVisual::Property::TYPE, Toolkit::Visual::GRADIENT );
-  map.Insert( Toolkit::GradientVisual::Property::UNITS, mGradient->GetGradientUnits() );
-  map.Insert( Toolkit::GradientVisual::Property::SPREAD_METHOD, mGradient->GetSpreadMethod() );
-
-  const Vector<Gradient::GradientStop>& stops( mGradient->GetStops() );
-  Property::Array offsets;
-  Property::Array colors;
-  for( unsigned int i=0; i<stops.Count(); i++ )
+  map.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::GRADIENT);
+  map.Insert(Toolkit::GradientVisual::Property::UNITS, mGradient->GetGradientUnits());
+  map.Insert(Toolkit::GradientVisual::Property::SPREAD_METHOD, mGradient->GetSpreadMethod());
+
+  const Vector<Gradient::GradientStop>& stops(mGradient->GetStops());
+  Property::Array                       offsets;
+  Property::Array                       colors;
+  for(unsigned int i = 0; i < stops.Count(); i++)
   {
-    offsets.PushBack( stops[i].mOffset );
-    if( EqualsZero(stops[i].mStopColor.a) )
+    offsets.PushBack(stops[i].mOffset);
+    if(EqualsZero(stops[i].mStopColor.a))
     {
-      colors.PushBack( Vector4::ZERO );
+      colors.PushBack(Vector4::ZERO);
     }
     else
     {
-      colors.PushBack( Vector4( stops[i].mStopColor.r / stops[i].mStopColor.a,
-                                stops[i].mStopColor.g / stops[i].mStopColor.a,
-                                stops[i].mStopColor.b / stops[i].mStopColor.a,
-                                stops[i].mStopColor.a));
+      colors.PushBack(Vector4(stops[i].mStopColor.r / stops[i].mStopColor.a,
+                              stops[i].mStopColor.g / stops[i].mStopColor.a,
+                              stops[i].mStopColor.b / stops[i].mStopColor.a,
+                              stops[i].mStopColor.a));
     }
   }
 
-  map.Insert( Toolkit::GradientVisual::Property::STOP_OFFSET, offsets );
-  map.Insert( Toolkit::GradientVisual::Property::STOP_COLOR, colors );
+  map.Insert(Toolkit::GradientVisual::Property::STOP_OFFSET, offsets);
+  map.Insert(Toolkit::GradientVisual::Property::STOP_COLOR, colors);
 
-  if( &typeid( *mGradient ) == &typeid(LinearGradient) )
+  if(&typeid(*mGradient) == &typeid(LinearGradient))
   {
-    LinearGradient* gradient = static_cast<LinearGradient*>( mGradient.Get() );
-    map.Insert( Toolkit::GradientVisual::Property::START_POSITION, gradient->GetStartPosition() );
-    map.Insert( Toolkit::GradientVisual::Property::END_POSITION, gradient->GetEndPosition() );
+    LinearGradient* gradient = static_cast<LinearGradient*>(mGradient.Get());
+    map.Insert(Toolkit::GradientVisual::Property::START_POSITION, gradient->GetStartPosition());
+    map.Insert(Toolkit::GradientVisual::Property::END_POSITION, gradient->GetEndPosition());
   }
   else // if( &typeid( *mGradient ) == &typeid(RadialGradient) )
   {
-    RadialGradient* gradient = static_cast<RadialGradient*>( mGradient.Get() );
-    map.Insert( Toolkit::GradientVisual::Property::CENTER, gradient->GetCenter() );
-    map.Insert( Toolkit::GradientVisual::Property::RADIUS, gradient->GetRadius() );
+    RadialGradient* gradient = static_cast<RadialGradient*>(mGradient.Get());
+    map.Insert(Toolkit::GradientVisual::Property::CENTER, gradient->GetCenter());
+    map.Insert(Toolkit::GradientVisual::Property::RADIUS, gradient->GetRadius());
   }
 }
 
-void GradientVisual::InitializeRenderer()
+void GradientVisual::DoCreateInstancePropertyMap(Property::Map& map) const
 {
-  Geometry geometry = mFactoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY );
+  // Do nothing
+}
 
-  Toolkit::GradientVisual::Units::Type gradientUnits = mGradient->GetGradientUnits();
-  VisualFactoryCache::ShaderType shaderType = GetShaderType( mGradientType, gradientUnits );
-  Shader shader = mFactoryCache.GetShader( shaderType );
-  if( !shader )
-  {
-    shader = Shader::New( VERTEX_SHADER[gradientUnits], FRAGMENT_SHADER[ mGradientType ] );
-    mFactoryCache.SaveShader( shaderType, shader );
-  }
+void GradientVisual::OnInitialize()
+{
+  Geometry geometry = mFactoryCache.GetGeometry(VisualFactoryCache::QUAD_GEOMETRY);
+  Shader   shader   = GenerateShader();
 
   //Set up the texture set
-  TextureSet textureSet = TextureSet::New();
+  TextureSet    textureSet    = TextureSet::New();
   Dali::Texture lookupTexture = mGradient->GenerateLookupTexture();
-  textureSet.SetTexture( 0u, lookupTexture );
-  Dali::WrapMode::Type wrap = GetWrapMode( mGradient->GetSpreadMethod() );
-  Sampler sampler = Sampler::New();
-  sampler.SetWrapMode(  wrap, wrap  );
-  textureSet.SetSampler( 0u, sampler );
-
-  mImpl->mRenderer = Renderer::New( geometry, shader );
-  mImpl->mRenderer.SetTextures( textureSet );
-
-  // If opaque then no need to have blending
-  if( mIsOpaque )
+  textureSet.SetTexture(0u, lookupTexture);
+  Dali::WrapMode::Type wrap    = GetWrapMode(mGradient->GetSpreadMethod());
+  Sampler              sampler = Sampler::New();
+  sampler.SetWrapMode(wrap, wrap);
+  textureSet.SetSampler(0u, sampler);
+
+  mImpl->mRenderer = Renderer::New(geometry, shader);
+  mImpl->mRenderer.ReserveCustomProperties(CUSTOM_PROPERTY_COUNT);
+  mImpl->mRenderer.SetTextures(textureSet);
+
+  // If opaque and then no need to have blending
+  if(mIsOpaque)
   {
-    mImpl->mRenderer.SetProperty( Renderer::Property::BLEND_MODE, BlendMode::OFF );
+    mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::OFF);
   }
 
-  mImpl->mRenderer.RegisterProperty( UNIFORM_ALIGNMENT_MATRIX_NAME, mGradientTransform );
+  mImpl->mRenderer.RegisterUniqueProperty(UNIFORM_ALIGNMENT_MATRIX_NAME, mGradientTransform);
 
   //Register transform properties
-  mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT );
+  mImpl->mTransform.RegisterUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT);
 }
 
 bool GradientVisual::NewGradient(Type gradientType, const Property::Map& propertyMap)
 {
-  if( gradientType == LINEAR )
+  if(gradientType == Type::LINEAR)
   {
-    Property::Value* startPositionValue = propertyMap.Find( Toolkit::GradientVisual::Property::START_POSITION, START_POSITION_NAME );
-    Property::Value* endPositionValue = propertyMap.Find( Toolkit::GradientVisual::Property::END_POSITION, END_POSITION_NAME );
-    Vector2 startPosition;
-    Vector2 endPosition;
+    Property::Value* startPositionValue = propertyMap.Find(Toolkit::GradientVisual::Property::START_POSITION, START_POSITION_NAME);
+    Property::Value* endPositionValue   = propertyMap.Find(Toolkit::GradientVisual::Property::END_POSITION, END_POSITION_NAME);
+    Vector2          startPosition;
+    Vector2          endPosition;
 
-    if( startPositionValue && startPositionValue->Get(startPosition)
-     && endPositionValue && endPositionValue->Get( endPosition ) )
+    if(startPositionValue && startPositionValue->Get(startPosition) && endPositionValue && endPositionValue->Get(endPosition))
     {
-      mGradient = new LinearGradient( startPosition, endPosition );
+      mGradient = new LinearGradient(startPosition, endPosition);
     }
     else
     {
       return false;
     }
   }
-  else // type==RADIAL
+  else // type==Type::RADIAL
   {
-    Property::Value* centerValue = propertyMap.Find( Toolkit::GradientVisual::Property::CENTER, CENTER_NAME );
-    Property::Value* radiusValue = propertyMap.Find( Toolkit::GradientVisual::Property::RADIUS, RADIUS_NAME );
-    Vector2 center;
-    float radius;
-    if( centerValue && centerValue->Get(center)
-        && radiusValue && radiusValue->Get(radius) )
+    Property::Value* centerValue = propertyMap.Find(Toolkit::GradientVisual::Property::CENTER, CENTER_NAME);
+    Property::Value* radiusValue = propertyMap.Find(Toolkit::GradientVisual::Property::RADIUS, RADIUS_NAME);
+    Vector2          center;
+    float            radius;
+    if(centerValue && centerValue->Get(center) && radiusValue && radiusValue->Get(radius))
     {
-      mGradient = new RadialGradient( center, radius );
+      mGradient = new RadialGradient(center, radius);
     }
     else
     {
@@ -396,26 +302,25 @@ bool GradientVisual::NewGradient(Type gradientType, const Property::Map& propert
     }
   }
 
-  unsigned int numValidStop = 0u;
-  Property::Value* stopOffsetValue = propertyMap.Find( Toolkit::GradientVisual::Property::STOP_OFFSET, STOP_OFFSET_NAME );
-  Property::Value* stopColorValue = propertyMap.Find( Toolkit::GradientVisual::Property::STOP_COLOR, STOP_COLOR_NAME );
-  if( stopColorValue )
+  unsigned int     numValidStop    = 0u;
+  Property::Value* stopOffsetValue = propertyMap.Find(Toolkit::GradientVisual::Property::STOP_OFFSET, STOP_OFFSET_NAME);
+  Property::Value* stopColorValue  = propertyMap.Find(Toolkit::GradientVisual::Property::STOP_COLOR, STOP_COLOR_NAME);
+  if(stopColorValue)
   {
-    Vector<float> offsetArray;
+    Vector<float>    offsetArray;
     Property::Array* colorArray = stopColorValue->GetArray();
-    if( colorArray )
+    if(colorArray)
     {
-      GetStopOffsets( stopOffsetValue, offsetArray );
-      unsigned int numStop = offsetArray.Count() < colorArray->Count() ?
-                             offsetArray.Count() : colorArray->Count();
-      Vector4 color;
-      for( unsigned int i=0; i<numStop; i++ )
+      GetStopOffsets(stopOffsetValue, offsetArray);
+      unsigned int numStop = offsetArray.Count() < colorArray->Count() ? offsetArray.Count() : colorArray->Count();
+      Vector4      color;
+      for(unsigned int i = 0; i < numStop; i++)
       {
-        if( (colorArray->GetElementAt(i)).Get(color) )
+        if((colorArray->GetElementAt(i)).Get(color))
         {
-          mGradient->AddStop( offsetArray[i], Vector4(color.r*color.a, color.g*color.a, color.b*color.a, color.a));
+          mGradient->AddStop(offsetArray[i], Vector4(color.r * color.a, color.g * color.a, color.b * color.a, color.a));
           numValidStop++;
-          if( ! Equals( color.a, 1.0f, Math::MACHINE_EPSILON_1 ) )
+          if(!Equals(color.a, 1.0f, Math::MACHINE_EPSILON_1))
           {
             mIsOpaque = false;
           }
@@ -424,71 +329,129 @@ bool GradientVisual::NewGradient(Type gradientType, const Property::Map& propert
     }
   }
 
-  if( numValidStop < 1u ) // no valid stop
+  if(numValidStop < 1u) // no valid stop
   {
     return false;
   }
 
-  Property::Value* spread = propertyMap.Find( Toolkit::GradientVisual::Property::SPREAD_METHOD, SPREAD_METHOD_NAME );
+  Property::Value* spread = propertyMap.Find(Toolkit::GradientVisual::Property::SPREAD_METHOD, SPREAD_METHOD_NAME);
   // The default spread method is PAD. Only need to set new spread if it's anything else.
-  if( spread )
+  if(spread)
   {
     Toolkit::GradientVisual::SpreadMethod::Type spreadMethod = Toolkit::GradientVisual::SpreadMethod::PAD;
-    if( Scripting::GetEnumerationProperty( *spread, SPREAD_METHOD_TABLE, SPREAD_METHOD_TABLE_COUNT, spreadMethod ) )
+    if(Scripting::GetEnumerationProperty(*spread, SPREAD_METHOD_TABLE, SPREAD_METHOD_TABLE_COUNT, spreadMethod))
     {
-      mGradient->SetSpreadMethod( spreadMethod );
+      mGradient->SetSpreadMethod(spreadMethod);
     }
   }
 
   return true;
 }
 
-void GradientVisual::GetStopOffsets(const Property::Value* value, Vector<float>& stopOffsets)
+Shader GradientVisual::GenerateShader() const
 {
+  bool userspaceUnit  = (mGradient->GetGradientUnits() == Toolkit::GradientVisual::Units::USER_SPACE);
+  bool roundedCorner  = IsRoundedCornerRequired();
+  bool borderline     = IsBorderlineRequired();
+  bool radialGradient = (mGradientType == Type::RADIAL);
+
+  int shaderTypeFlag = GradientVisualRequireFlag::DEFAULT;
+  if(roundedCorner)
+  {
+    shaderTypeFlag |= GradientVisualRequireFlag::ROUNDED_CORNER;
+  }
+  if(borderline)
+  {
+    shaderTypeFlag |= GradientVisualRequireFlag::BORDERLINE;
+  }
+  if(userspaceUnit)
+  {
+    shaderTypeFlag |= GradientVisualRequireFlag::USER_SPACE;
+  }
+  if(radialGradient)
+  {
+    shaderTypeFlag |= GradientVisualRequireFlag::RADIAL;
+  }
+
+  VisualFactoryCache::ShaderType shaderType = SHADER_TYPE_TABLE[shaderTypeFlag];
+  Shader                         shader     = mFactoryCache.GetShader(shaderType);
+  if(!shader)
+  {
+    std::string vertexShaderPrefixList;
+    std::string fragmentShaderPrefixList;
+
+    if(roundedCorner)
+    {
+      vertexShaderPrefixList += "#define IS_REQUIRED_ROUNDED_CORNER 1\n";
+      fragmentShaderPrefixList += "#define IS_REQUIRED_ROUNDED_CORNER 1\n";
+    }
+    if(borderline)
+    {
+      vertexShaderPrefixList += "#define IS_REQUIRED_BORDERLINE 1\n";
+      fragmentShaderPrefixList += "#define IS_REQUIRED_BORDERLINE 1\n";
+    }
+    if(radialGradient)
+    {
+      fragmentShaderPrefixList += "#define RADIAL 1\n";
+    }
+    if(userspaceUnit)
+    {
+      vertexShaderPrefixList += "#define USER_SPACE 1\n";
+    }
+
+    shader = Shader::New(Dali::Shader::GetVertexShaderPrefix() + vertexShaderPrefixList + SHADER_GRADIENT_VISUAL_SHADER_VERT.data(),
+                         Dali::Shader::GetFragmentShaderPrefix() + fragmentShaderPrefixList + SHADER_GRADIENT_VISUAL_SHADER_FRAG.data());
+    mFactoryCache.SaveShader(shaderType, shader);
+  }
 
-  if ( value ) // Only check valve type if a valid Property has been passed in
+  return shader;
+}
+
+void GradientVisual::GetStopOffsets(const Property::Value* value, Vector<float>& stopOffsets)
+{
+  if(value) // Only check valve type if a valid Property has been passed in
   {
-    switch ( value->GetType() )
+    switch(value->GetType())
     {
       case Property::VECTOR2:
       {
         Vector2 offset2;
-        value->Get( offset2 );
-        stopOffsets.PushBack( offset2.x );
-        stopOffsets.PushBack( offset2.y );
+        value->Get(offset2);
+        stopOffsets.PushBack(offset2.x);
+        stopOffsets.PushBack(offset2.y);
         break;
       }
       case Property::VECTOR3:
       {
         Vector3 offset3;
-        value->Get( offset3 );
-        stopOffsets.PushBack( offset3.x );
-        stopOffsets.PushBack( offset3.y );
-        stopOffsets.PushBack( offset3.z );
+        value->Get(offset3);
+        stopOffsets.PushBack(offset3.x);
+        stopOffsets.PushBack(offset3.y);
+        stopOffsets.PushBack(offset3.z);
         break;
       }
       case Property::VECTOR4:
       {
         Vector4 offset4;
-        value->Get( offset4 );
-        stopOffsets.PushBack( offset4.x );
-        stopOffsets.PushBack( offset4.y );
-        stopOffsets.PushBack( offset4.z );
-        stopOffsets.PushBack( offset4.w );
+        value->Get(offset4);
+        stopOffsets.PushBack(offset4.x);
+        stopOffsets.PushBack(offset4.y);
+        stopOffsets.PushBack(offset4.z);
+        stopOffsets.PushBack(offset4.w);
         break;
       }
       case Property::ARRAY:
       {
-        Property::Array* offsetArray = value->GetArray();
-        if( offsetArray )
+        const Property::Array* offsetArray = value->GetArray();
+        if(offsetArray)
         {
           unsigned int numStop = offsetArray->Count();
-          float offset;
-          for( unsigned int i=0; i<numStop; i++ )
+          float        offset;
+          for(unsigned int i = 0; i < numStop; i++)
           {
-            if( offsetArray->GetElementAt(i).Get(offset) )
+            if(offsetArray->GetElementAt(i).Get(offset))
             {
-              stopOffsets.PushBack( offset );
+              stopOffsets.PushBack(offset);
             }
           }
         }
@@ -502,11 +465,11 @@ void GradientVisual::GetStopOffsets(const Property::Value* value, Vector<float>&
     }
   }
 
-  if ( stopOffsets.Empty() )
+  if(stopOffsets.Empty())
   {
     // Set default offset if none set by Property system, need a minimum and maximum
-    stopOffsets.PushBack( DEFAULT_OFFSET_MINIMUM );
-    stopOffsets.PushBack( DEFAULT_OFFSET_MAXIMUM );
+    stopOffsets.PushBack(DEFAULT_OFFSET_MINIMUM);
+    stopOffsets.PushBack(DEFAULT_OFFSET_MAXIMUM);
   }
 }