Cleaning up the property framework; removal of duplicate methods and incorrect assers
[platform/core/uifw/dali-core.git] / dali / internal / event / effects / shader-effect-impl.cpp
index 65db8f5..bd41274 100644 (file)
@@ -18,9 +18,6 @@
 // CLASS HEADER
 #include <dali/internal/event/effects/shader-effect-impl.h>
 
-// EXTERNAL INCLUDES
-#include <fstream>
-
 // INTERNAL INCLUDES
 #include <dali/public-api/math/vector2.h>
 #include <dali/public-api/math/matrix.h>
@@ -28,7 +25,6 @@
 #include <dali/public-api/shader-effects/shader-effect.h>
 #include <dali/public-api/object/type-registry.h>
 #include <dali/public-api/scripting/scripting.h>
-#include "dali-shaders.h"
 #include <dali/internal/event/effects/shader-declarations.h>
 #include <dali/internal/event/effects/shader-factory.h>
 #include <dali/internal/event/images/image-impl.h>
 #include <dali/internal/event/common/stage-impl.h>
 #include <dali/internal/event/common/thread-local-storage.h>
 #include <dali/internal/render/shaders/shader.h>
-#include <dali/internal/update/common/property-owner-messages.h>
+#include <dali/internal/render/shaders/uniform-meta.h>
 #include <dali/internal/update/animation/scene-graph-constraint-base.h>
+#include "dali-shaders.h"
 
 using Dali::Internal::SceneGraph::UpdateManager;
 using Dali::Internal::SceneGraph::UniformMeta;
 using Dali::Internal::SceneGraph::Shader;
 using Dali::Internal::SceneGraph::AnimatableProperty;
 using Dali::Internal::SceneGraph::PropertyBase;
-using Dali::Internal::SceneGraph::PropertyBase;
 using Dali::Internal::SceneGraph::RenderQueue;
 using std::string;
 
@@ -60,10 +56,27 @@ const Property::Index ShaderEffect::GEOMETRY_HINTS      = 3;
 namespace Internal
 {
 
-ShaderEffect::DefaultPropertyLookup* ShaderEffect::mDefaultPropertyLookup = NULL;
-
 namespace
 {
+const PropertyDetails DEFAULT_PROPERTY_DETAILS[] =
+{
+ // Name               Type            writable animatable constraint-input
+ { "grid-density",   Property::FLOAT,   true,    false,   false  }, // GRID_DENSITY
+ { "image",          Property::MAP,     true,    false,   false  }, // IMAGE
+ { "program",        Property::MAP,     true,    false,   false  }, // PROGRAM
+ { "geometry-hints", Property::INTEGER, true,    false,   false  }, // GEOMETRY_HINTS
+};
+
+const int DEFAULT_PROPERTY_COUNT = sizeof( DEFAULT_PROPERTY_DETAILS ) / sizeof( DEFAULT_PROPERTY_DETAILS[0] );
+
+BaseHandle Create()
+{
+  Internal::ShaderEffectPtr internal = Internal::ShaderEffect::New();
+
+  return Dali::ShaderEffect(internal.Get());
+}
+
+TypeRegistration mType( typeid(Dali::ShaderEffect), typeid(Dali::Handle), Create );
 
 struct WrapperStrings
 {
@@ -80,120 +93,118 @@ WrapperStrings customShaderWrappers [] =
     CustomImagePostfixVertex, CustomImagePostfixFragment
   },
   {
-    CustomFontPrefixVertex, CustomFontPrefixFragment,
-    CustomFontPostfixVertex, CustomFontPostfixFragment
+    CustomTextDistanceFieldPrefixVertex, CustomTextDistanceFieldPrefixFragment,
+    CustomTextDistanceFieldPostfixVertex, CustomTextDistanceFieldPostfixFragment
   },
   {
-    CustomMeshPrefixVertex, CustomMeshPrefixFragment,
-    MeshVertex, MeshFragment
+    CustomUntexturedMeshPrefixVertex, CustomUntexturedMeshPrefixFragment,
+    CustomUntexturedMeshPostfixVertex, CustomUntexturedMeshPostfixFragment
+  },
+  {
+    CustomTexturedMeshPrefixVertex, CustomTexturedMeshPrefixFragment,
+    CustomTexturedMeshPostfixVertex, CustomTexturedMeshPostfixFragment
   }
 };
 
-BaseHandle Create()
-{
-  Internal::ShaderEffectPtr internal = Internal::ShaderEffect::New( );
-
-  ShaderFactory::LoadTextSubtypeShaders(internal);
-
-  return Dali::ShaderEffect(internal.Get());
-}
-
-TypeRegistration mType( typeid(Dali::ShaderEffect), typeid(Dali::Handle), Create );
+/**
+ * Helper to wrap the program with our default pre and postfix if needed and then send it to update/render thread
+ * @param[in] effect of the shader
+ * @param[in] actualGeometryType of the shader
+ * @param[in] expectedGeometryType of the shader
+ * @param[in] vertexPrefix from application
+ * @param[in] fragmentPrefix from application
+ * @param[in] vertexBody from application
+ * @param[in] fragmentBody from application
+ * @param[in] modifiesGeometry based on flags and vertex shader
+ */
+void WrapAndSetProgram( Internal::ShaderEffect& effect,
+                        GeometryType actualGeometryType, GeometryType expectedGeometryType,
+                        const std::string& vertexPrefix, const std::string& fragmentPrefix,
+                        const std::string& vertexBody, const std::string& fragmentBody,
+                        bool modifiesGeometry )
+{
+  // if geometry type matches and there is some real data in the strings
+  if( ( actualGeometryType & expectedGeometryType )&&
+      ( ( vertexPrefix.length() > 0   )||
+        ( fragmentPrefix.length() > 0 )||
+        ( vertexBody.length() > 0     )||
+        ( fragmentBody.length() > 0   ) ) )
+  {
+    std::string vertexSource = vertexPrefix;
+    std::string fragmentSource = fragmentPrefix;
+
+    // create complete shader program strings for the given geometry type
+    unsigned int index = 0;
+    switch( expectedGeometryType )
+    {
+      case GEOMETRY_TYPE_IMAGE:
+      {
+        index = 0;
+        break;
+      }
+      case GEOMETRY_TYPE_TEXT:
+      {
+        index = 1;
+        break;
+      }
+      case GEOMETRY_TYPE_UNTEXTURED_MESH:
+      {
+        index = 2;
+        break;
+      }
+      case GEOMETRY_TYPE_TEXTURED_MESH:
+      {
+        index = 3;
+        break;
+      }
+      case GEOMETRY_TYPE_LAST:
+      {
+        DALI_ASSERT_DEBUG(0 && "Wrong geometry type");
+        break;
+      }
+    }
 
-const std::string DEFAULT_PROPERTY_NAMES[] =
-{
-  "grid-density",
-  "image",
-  "program",
-  "geometry-hints",
-};
-const int DEFAULT_PROPERTY_COUNT = sizeof( DEFAULT_PROPERTY_NAMES ) / sizeof( std::string );
+    vertexSource += customShaderWrappers[index].vertexShaderPrefix;
+    // Append the custom vertex shader code if supplied, otherwise append the default
+    if ( vertexBody.length() > 0 )
+    {
+      vertexSource.append( vertexBody );
+    }
+    else
+    {
+      vertexSource.append( customShaderWrappers[index].vertexShaderPostfix );
+    }
 
-const Property::Type DEFAULT_PROPERTY_TYPES[DEFAULT_PROPERTY_COUNT] =
-{
-  Property::FLOAT,    // "grid-density",
-  Property::MAP,      // "image",
-  Property::MAP,      // "program",
-  Property::INTEGER,  // "geometry-hints",
-};
+    fragmentSource += customShaderWrappers[index].fragmentShaderPrefix;
+    // Append the custom fragment shader code if supplied, otherwise append the default
+    if ( fragmentBody.length() > 0 )
+    {
+      fragmentSource.append( fragmentBody );
+    }
+    else
+    {
+      fragmentSource.append( customShaderWrappers[index].fragmentShaderPostfix );
+    }
 
-std::string GetFileContents( const std::string& filename )
-{
-  std::ifstream input( filename.c_str() );
-  return std::string( std::istreambuf_iterator<char>(input), std::istreambuf_iterator<char>() );
+    effect.SendProgramMessage( expectedGeometryType, SHADER_SUBTYPE_ALL, vertexSource, fragmentSource, modifiesGeometry );
+  }
 }
 
 std::string GetShader(const std::string& field, const Property::Value& property)
 {
+  std::string value;
   if( property.HasKey(field) )
   {
     DALI_ASSERT_ALWAYS(property.GetValue(field).GetType() == Property::STRING && "Shader property is not a string" );
 
     // we could also check here for an array of strings as convenience for json not having multi line strings
-    return property.GetValue(field).Get<std::string>();
-  }
-  else
-  {
-    // convention of shader field appended with -filename signifies a file
-    std::string filenameKey(std::string(field) + std::string("-filename"));
-
-    if( property.HasKey( filenameKey ) )
-    {
-      DALI_ASSERT_ALWAYS(property.GetValue(filenameKey).GetType() == Property::STRING && "Shader filename property is not a string" );
-      // this should eventually be done by an adaptor interface
-      return GetFileContents( property.GetValue(filenameKey).Get<std::string>() );
-    }
+    value = property.GetValue(field).Get<std::string>();
   }
 
-  return std::string();
-}
-
-} // anon namespace
-
-
-ShaderEffectPtr ShaderEffect::New( const string& vertexShader,
-                                   const string& fragmentShader,
-                                   GeometryType geometryType,
-                                   Dali::ShaderEffect::GeometryHints hints )
-{
-  return NewWithPrefix( "", vertexShader, "", fragmentShader, geometryType, hints);
-}
-
-ShaderEffectPtr ShaderEffect::NewWithPrefix( const string& vertexShaderPrefix,
-                                             const string& vertexShader,
-                                             const string& fragmentShaderPrefix,
-                                             const string& fragmentShader,
-                                             GeometryType geometryTypes,
-                                             Dali::ShaderEffect::GeometryHints hints )
-{
-  ShaderEffectPtr shaderEffect( New(hints) );
-  ShaderFactory::LoadTextSubtypeShaders(shaderEffect);
-
-  shaderEffect->SetPrograms( geometryTypes, vertexShaderPrefix, vertexShader, fragmentShaderPrefix, fragmentShader );
-  return shaderEffect;
+  return value;
 }
 
-ShaderEffectPtr ShaderEffect::New( const string& imageVertexShader,
-                                   const string& imageFragmentShader,
-                                   const string& textVertexShader,
-                                   const string& textFragmentShader,
-                                   const string& texturedMeshVertexShader,
-                                   const string& texturedMeshFragmentShader,
-                                   const string& meshVertexShader,
-                                   const string& meshFragmentShader,
-                                   Dali::ShaderEffect::GeometryHints hints )
-{
-  ShaderEffectPtr shaderEffect( New(hints) );
-
-  ShaderFactory::LoadTextSubtypeShaders(shaderEffect);
-
-  shaderEffect->SetWrappedProgram( GEOMETRY_TYPE_IMAGE, SHADER_SUBTYPE_ALL, "", "", imageVertexShader, imageFragmentShader );
-  shaderEffect->SetWrappedProgram( GEOMETRY_TYPE_TEXT, SHADER_DEFAULT, "", "", textVertexShader, textFragmentShader );
-  shaderEffect->SetWrappedProgram( GEOMETRY_TYPE_TEXTURED_MESH, SHADER_SUBTYPE_ALL, "", "", texturedMeshVertexShader, texturedMeshFragmentShader );
-  shaderEffect->SetWrappedProgram( GEOMETRY_TYPE_MESH, SHADER_SUBTYPE_ALL, "", "", meshVertexShader, meshFragmentShader );
-
-  return shaderEffect;
-}
+} // unnamed namespace
 
 ShaderEffectPtr ShaderEffect::New( Dali::ShaderEffect::GeometryHints hints )
 {
@@ -220,14 +231,14 @@ ShaderEffect::ShaderEffect( UpdateManager& updateManager, Dali::ShaderEffect::Ge
 
 ShaderEffect::~ShaderEffect()
 {
-  DALI_ASSERT_DEBUG( mSceneObject != NULL );
-
   // Guard to allow handle destruction after Core has been destroyed
   if ( Stage::IsInstalled() )
   {
     // Remove scene-object using a message to the UpdateManager
-    RemoveShaderMessage( mUpdateManager, *mSceneObject );
-
+    if( mSceneObject )
+    {
+      RemoveShaderMessage( mUpdateManager, *mSceneObject );
+    }
     UnregisterObject();
   }
 }
@@ -277,7 +288,20 @@ void ShaderEffect::SetUniform( const std::string& name, Property::Value value, U
 
   SetProperty( index, value );
 
-  SetCoordinateTypeMessage( mUpdateManager.GetEventToUpdate(), *mCustomMetadata[index], uniformCoordinateType );
+  // RegisterProperty guarantees a positive value as index
+  DALI_ASSERT_DEBUG( static_cast<unsigned int>(index) >= CustomPropertyStartIndex() );
+  unsigned int metaIndex = index - CustomPropertyStartIndex();
+  // check if there's space in cache
+  if( mCoordinateTypes.Count() < (metaIndex + 1) )
+  {
+    mCoordinateTypes.Resize( metaIndex + 1 );
+  }
+  // only send message if the value is different than current, initial value is COORDINATE_TYPE_DEFAULT (0)
+  if( uniformCoordinateType != mCoordinateTypes[ metaIndex ] )
+  {
+    mCoordinateTypes[ metaIndex ] = uniformCoordinateType;
+    SetCoordinateTypeMessage( mUpdateManager.GetEventToUpdate(), *mSceneObject, metaIndex, uniformCoordinateType );
+  }
 }
 
 void ShaderEffect::AttachExtension( Dali::ShaderEffect::Extension *extension )
@@ -298,21 +322,49 @@ const Dali::ShaderEffect::Extension& ShaderEffect::GetExtension() const
   return *mExtension;
 }
 
-void ShaderEffect::SetProgram( GeometryType geometryType, ShaderSubTypes subType,
-                               const string& vertexSource, const string& fragmentSource,
-                               GeometryState modifiesGeometry )
+void ShaderEffect::SetPrograms( GeometryType geometryType, const string& vertexSource, const string& fragmentSource )
 {
-  SetProgramImpl(geometryType, subType, vertexSource, fragmentSource, modifiesGeometry);
+  SetPrograms( geometryType, "", "", vertexSource, fragmentSource );
 }
 
-void ShaderEffect::SetProgram( GeometryType geometryType, ShaderSubTypes subType,
-                               const std::string& vertexPrefix, const std::string& fragmentPrefix,
-                               const std::string& vertexSource, const std::string& fragmentSource,
-                               GeometryState modifiesGeometry )
+void ShaderEffect::SetPrograms( GeometryType geometryType,
+                                const std::string& vertexPrefix, const std::string& fragmentPrefix,
+                                const std::string& vertexSource, const std::string& fragmentSource )
 {
-  const std::string vertex( vertexPrefix + vertexSource );
-  const std::string fragment( fragmentPrefix + fragmentSource );
-  SetProgramImpl( geometryType, subType, vertex, fragment, modifiesGeometry );
+  bool modifiesGeometry = true;
+  // check if the vertex shader is empty (means it cannot modify geometry)
+  if( (vertexPrefix.length() == 0 )&&( vertexSource.length() == 0 ) )
+  {
+    modifiesGeometry = false;
+  }
+  // check the hint second
+  if( (mGeometryHints & Dali::ShaderEffect::HINT_DOESNT_MODIFY_GEOMETRY ) != 0 )
+  {
+    modifiesGeometry = false;
+  }
+
+  WrapAndSetProgram( *this, geometryType, GEOMETRY_TYPE_IMAGE, vertexPrefix, fragmentPrefix, vertexSource, fragmentSource, modifiesGeometry );
+  WrapAndSetProgram( *this, geometryType, GEOMETRY_TYPE_TEXT, vertexPrefix, fragmentPrefix, vertexSource, fragmentSource, modifiesGeometry );
+  WrapAndSetProgram( *this, geometryType, GEOMETRY_TYPE_TEXTURED_MESH, vertexPrefix, fragmentPrefix, vertexSource, fragmentSource, modifiesGeometry );
+  WrapAndSetProgram( *this, geometryType, GEOMETRY_TYPE_UNTEXTURED_MESH, vertexPrefix, fragmentPrefix, vertexSource, fragmentSource, modifiesGeometry );
+}
+
+void ShaderEffect::SendProgramMessage( GeometryType geometryType, ShaderSubTypes subType,
+                                       const string& vertexSource, const string& fragmentSource,
+                                       bool modifiesGeometry )
+{
+  ThreadLocalStorage& tls = ThreadLocalStorage::Get();
+  ShaderFactory& shaderFactory = tls.GetShaderFactory();
+  size_t shaderHash;
+
+  ResourceTicketPtr ticket( shaderFactory.Load(vertexSource, fragmentSource, shaderHash) );
+
+  DALI_LOG_INFO( Debug::Filter::gShader, Debug::General, "ShaderEffect: SetProgram(geometryType %d subType:%d ticket.id:%d)\n", geometryType, subType, ticket->GetId() );
+
+  // Add shader program to scene-object using a message to the UpdateManager
+  SetShaderProgramMessage( mUpdateManager, *mSceneObject, geometryType, subType, ticket->GetId(), shaderHash, modifiesGeometry );
+
+  mTickets.push_back(ticket);       // add ticket to collection to keep it alive.
 }
 
 void ShaderEffect::Connect()
@@ -339,11 +391,6 @@ void ShaderEffect::Disconnect()
   }
 }
 
-bool ShaderEffect::IsSceneObjectRemovable() const
-{
-  return false; // The Shader is not removed during this proxy's lifetime
-}
-
 unsigned int ShaderEffect::GetDefaultPropertyCount() const
 {
   return DEFAULT_PROPERTY_COUNT;
@@ -359,17 +406,15 @@ void ShaderEffect::GetDefaultPropertyIndices( Property::IndexContainer& indices
   }
 }
 
-const std::string& ShaderEffect::GetDefaultPropertyName(Property::Index index) const
+const char* ShaderEffect::GetDefaultPropertyName(Property::Index index) const
 {
   if( index < DEFAULT_PROPERTY_COUNT )
   {
-    return DEFAULT_PROPERTY_NAMES[index];
+    return DEFAULT_PROPERTY_DETAILS[index].name;
   }
   else
   {
-    // index out of range..return empty string
-    static const std::string INVALID_PROPERTY_NAME;
-    return INVALID_PROPERTY_NAME;
+    return NULL;
   }
 }
 
@@ -377,48 +422,41 @@ Property::Index ShaderEffect::GetDefaultPropertyIndex(const std::string& name) c
 {
   Property::Index index = Property::INVALID_INDEX;
 
-  // Lazy initialization of static mDefaultPropertyLookup
-  if (!mDefaultPropertyLookup)
+  // Look for name in default properties
+  for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
   {
-    mDefaultPropertyLookup = new DefaultPropertyLookup();
-
-    for (int i=0; i<DEFAULT_PROPERTY_COUNT; ++i)
+    const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
+    if( 0 == strcmp( name.c_str(), property->name ) ) // dont want to convert rhs to string
     {
-      (*mDefaultPropertyLookup)[DEFAULT_PROPERTY_NAMES[i]] = i;
+      index = i;
+      break;
     }
   }
-  DALI_ASSERT_DEBUG( NULL != mDefaultPropertyLookup );
-
-  // Look for name in default properties
-  DefaultPropertyLookup::const_iterator result = mDefaultPropertyLookup->find( name );
-  if ( mDefaultPropertyLookup->end() != result )
-  {
-    index = result->second;
-  }
 
   return index;
+
 }
 
 bool ShaderEffect::IsDefaultPropertyWritable(Property::Index index) const
 {
-  return true;
+  return true; // all properties are writable
 }
 
 bool ShaderEffect::IsDefaultPropertyAnimatable(Property::Index index) const
 {
-  return false;
+  return false; // all properties are non animatable
 }
 
 bool ShaderEffect::IsDefaultPropertyAConstraintInput( Property::Index index ) const
 {
-  return false;
+  return false; // all properties cannot be used as constraint input
 }
 
 Property::Type ShaderEffect::GetDefaultPropertyType(Property::Index index) const
 {
   if( index < DEFAULT_PROPERTY_COUNT )
   {
-    return DEFAULT_PROPERTY_TYPES[index];
+    return DEFAULT_PROPERTY_DETAILS[index].type;
   }
   else
   {
@@ -474,9 +512,9 @@ void ShaderEffect::SetDefaultProperty( Property::Index index, const Property::Va
         {
           geometryType  = GEOMETRY_TYPE_TEXT;
         }
-        else if( s == "GEOMETRY_TYPE_MESH")
+        else if( s == "GEOMETRY_TYPE_UNTEXTURED_MESH")
         {
-          geometryType  = GEOMETRY_TYPE_MESH;
+          geometryType  = GEOMETRY_TYPE_UNTEXTURED_MESH;
         }
         else if( s == "GEOMETRY_TYPE_TEXTURED_MESH")
         {
@@ -487,7 +525,7 @@ void ShaderEffect::SetDefaultProperty( Property::Index index, const Property::Va
           DALI_ASSERT_ALWAYS(!"Geometry type unknown" );
         }
       }
-      SetPrograms( geometryType, vertexPrefix, vertex, fragmentPrefix, fragment );
+      SetPrograms( geometryType, vertexPrefix, fragmentPrefix, vertex, fragment );
       break;
     }
 
@@ -537,7 +575,7 @@ void ShaderEffect::SetDefaultProperty( Property::Index index, const Property::Va
 
     default:
     {
-      DALI_ASSERT_ALWAYS(false && "ShaderEffect property enumeration out of range"); // should not come here
+      // nothing to do
       break;
     }
   }
@@ -549,20 +587,14 @@ Property::Value ShaderEffect::GetDefaultProperty(Property::Index /*index*/) cons
   return Property::Value();
 }
 
-void ShaderEffect::InstallSceneObjectProperty( PropertyBase& newProperty, const std::string& name, unsigned int index )
+void ShaderEffect::NotifyScenePropertyInstalled( const SceneGraph::PropertyBase& newProperty, const std::string& name, unsigned int index )
 {
   // Warning - the property is added to the Shader object in the Update thread and the meta-data is added in the Render thread (through a secondary message)
 
-  // mSceneObject is being used in a separate thread; queue a message to add the property
-  InstallCustomPropertyMessage( mUpdateManager.GetEventToUpdate(), *mSceneObject, newProperty ); // Message takes ownership
-
   // mSceneObject requires metadata for each custom property (uniform)
   UniformMeta* meta = UniformMeta::New( name, newProperty, Dali::ShaderEffect::COORDINATE_TYPE_DEFAULT );
   // mSceneObject is being used in a separate thread; queue a message to add the property
   InstallUniformMetaMessage( mUpdateManager.GetEventToUpdate(), *mSceneObject, *meta ); // Message takes ownership
-
-  // Add entry to the metadata lookup
-  mCustomMetadata[index] = meta;
 }
 
 const SceneGraph::PropertyOwner* ShaderEffect::GetSceneObject() const
@@ -572,166 +604,16 @@ const SceneGraph::PropertyOwner* ShaderEffect::GetSceneObject() const
 
 const PropertyBase* ShaderEffect::GetSceneObjectAnimatableProperty( Property::Index index ) const
 {
-  CustomPropertyLookup::const_iterator entry = GetCustomPropertyLookup().find( index );
-
-  DALI_ASSERT_ALWAYS( GetCustomPropertyLookup().end() != entry && "Property index is invalid" );
-
-  DALI_ASSERT_ALWAYS( entry->second.IsAnimatable() && "shader effect has only animatable properties" );
-
-  return dynamic_cast<const PropertyBase*>( entry->second.GetSceneGraphProperty() );
+  CustomProperty* custom = FindCustomProperty( index );
+  DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
+  return custom->GetSceneGraphProperty();
 }
 
 const PropertyInputImpl* ShaderEffect::GetSceneObjectInputProperty( Property::Index index ) const
 {
-  CustomPropertyLookup::const_iterator entry = GetCustomPropertyLookup().find( index );
-
-  DALI_ASSERT_ALWAYS( GetCustomPropertyLookup().end() != entry && "Property index is invalid" );
-
-  DALI_ASSERT_ALWAYS( entry->second.IsAnimatable() && "shader effect has only animatable properties" );
-
-  return entry->second.GetSceneGraphProperty();
-}
-
-void ShaderEffect::SetPrograms( GeometryType  geometryTypes,
-                                const std::string& vertexShaderPrefix,
-                                const std::string& vertexShader,
-                                const std::string& fragmentShaderPrefix,
-                                const std::string& fragmentShader )
-{
-  static std::string emptyStr;
-
-  if( geometryTypes & GEOMETRY_TYPE_IMAGE )
-  {
-    SetWrappedProgram( GEOMETRY_TYPE_IMAGE, SHADER_SUBTYPE_ALL, vertexShaderPrefix, fragmentShaderPrefix, vertexShader, fragmentShader );
-  }
-  else
-  {
-    SetWrappedProgram( GEOMETRY_TYPE_IMAGE, SHADER_SUBTYPE_ALL, emptyStr, emptyStr, emptyStr, emptyStr );
-  }
-
-  if( geometryTypes & GEOMETRY_TYPE_TEXT )
-  {
-    // Only change the default program, leaving the other sub-types as-is.
-    SetWrappedProgram( GEOMETRY_TYPE_TEXT, SHADER_DEFAULT, vertexShaderPrefix, fragmentShaderPrefix, vertexShader, fragmentShader );
-  }
-  else
-  {
-    SetWrappedProgram( GEOMETRY_TYPE_TEXT, SHADER_DEFAULT, emptyStr, emptyStr, emptyStr, emptyStr );
-  }
-
-  if( geometryTypes & GEOMETRY_TYPE_TEXTURED_MESH )
-  {
-    SetWrappedProgram( GEOMETRY_TYPE_TEXTURED_MESH, SHADER_SUBTYPE_ALL, vertexShaderPrefix, fragmentShaderPrefix, vertexShader, fragmentShader );
-  }
-  else
-  {
-    SetWrappedProgram( GEOMETRY_TYPE_TEXTURED_MESH, SHADER_SUBTYPE_ALL, emptyStr, emptyStr, emptyStr, emptyStr );
-  }
-
-  if( geometryTypes & GEOMETRY_TYPE_MESH )
-  {
-    SetWrappedProgram( GEOMETRY_TYPE_MESH, SHADER_SUBTYPE_ALL, vertexShaderPrefix, fragmentShaderPrefix, vertexShader, fragmentShader );
-  }
-  else
-  {
-    SetWrappedProgram( GEOMETRY_TYPE_MESH, SHADER_SUBTYPE_ALL, emptyStr, emptyStr, emptyStr, emptyStr );
-  }
-}
-
-void ShaderEffect::SetWrappedProgram( GeometryType geometryType, ShaderSubTypes subType,
-                                      const string& vertexPrefix, const string& fragmentPrefix,
-                                      const string& vertexSnippet, const string& fragmentSnippet )
-{
-  // create complete shader program strings for the given geometry type
-  unsigned int index = 0;
-  switch( geometryType )
-  {
-    case GEOMETRY_TYPE_IMAGE:
-    {
-      index = 0;
-      break;
-    }
-    case GEOMETRY_TYPE_TEXT:
-    {
-      index = 1;
-      break;
-    }
-    case GEOMETRY_TYPE_MESH:
-    case GEOMETRY_TYPE_TEXTURED_MESH:
-    {
-      index = 2;
-      break;
-    }
-    case GEOMETRY_TYPE_LAST:
-    {
-      DALI_ASSERT_DEBUG(0 && "Wrong geometry type");
-      break;
-    }
-  }
-
-  string vertexSource = vertexPrefix + customShaderWrappers[index].vertexShaderPrefix;
-  string fragmentSource = fragmentPrefix + customShaderWrappers[index].fragmentShaderPrefix;
-
-  // Append the custom vertex shader code if supplied, otherwise append the default
-  if ( vertexSnippet.length() > 0 )
-  {
-    vertexSource.append( vertexSnippet );
-  }
-  else
-  {
-    vertexSource.append( customShaderWrappers[index].vertexShaderPostfix );
-  }
-
-  // Append the custom fragment shader code if supplied, otherwise append the default
-  if ( fragmentSnippet.length() > 0 )
-  {
-    fragmentSource.append( fragmentSnippet );
-  }
-  else
-  {
-    fragmentSource.append( customShaderWrappers[index].fragmentShaderPostfix );
-  }
-
-  // Add the program
-  SetProgramImpl( geometryType, subType, vertexSource, fragmentSource );
-}
-
-void ShaderEffect::SetProgramImpl( GeometryType geometryType, ShaderSubTypes subType,
-                                   const string& vertexSource, const string& fragmentSource )
-{
-  GeometryState modifiesGeometry = MODIFIES_GEOMETRY;
-
-  if( (mGeometryHints & Dali::ShaderEffect::HINT_DOESNT_MODIFY_GEOMETRY ) != 0 )
-  {
-    modifiesGeometry = DOESNT_MODIFY_GEOMETRY;
-  }
-
-  SetProgramImpl( geometryType, subType, vertexSource, fragmentSource, modifiesGeometry );
+  return GetSceneObjectAnimatableProperty( index );
 }
 
-void ShaderEffect::SetProgramImpl( GeometryType geometryType, ShaderSubTypes subType,
-                                   const string& vertexSource, const string& fragmentSource,
-                                   GeometryState modifiesGeometry )
-{
-  // Load done asynchronously in update thread. SetProgram message below must be processed afterwards.
-  // Therefore, resource manager cannot farm out the loading to the adaptor resource threads,
-  // but must instead use synchronous loading via PlatformAbstraction::LoadFile()
-
-  ThreadLocalStorage& tls = ThreadLocalStorage::Get();
-  ShaderFactory& shaderFactory = tls.GetShaderFactory();
-  size_t shaderHash;
-
-  ResourceTicketPtr ticket( shaderFactory.Load(vertexSource, fragmentSource, shaderHash) );
-
-  DALI_LOG_INFO( Debug::Filter::gShader, Debug::General, "ShaderEffect: SetProgram(geometryType %d subType:%d ticket.id:%d)\n", geometryType, subType, ticket->GetId() );
-
-  // Add shader program to scene-object using a message to the UpdateManager
-  SetShaderProgramMessage( mUpdateManager, *mSceneObject, geometryType, subType, ticket->GetId(), shaderHash, modifiesGeometry==MODIFIES_GEOMETRY );
-
-  mTickets.push_back(ticket);       // add ticket to collection to keep it alive.
-}
-
-
 } // namespace Internal
 
 } // namespace Dali