[3.0] Remove/move experimental features
[platform/core/uifw/dali-core.git] / dali / internal / event / effects / shader-effect-impl.cpp
index d808e39..cd76e36 100644 (file)
 // CLASS HEADER
 #include <dali/internal/event/effects/shader-effect-impl.h>
 
+// EXTERNAL INCLUDES
+#include <cstring> // for strcmp
+
 // INTERNAL INCLUDES
 #include <dali/public-api/math/matrix.h>
 #include <dali/public-api/math/matrix3.h>
 #include <dali/public-api/math/vector2.h>
 #include <dali/public-api/object/type-registry.h>
 #include <dali/devel-api/scripting/scripting.h>
-#include <dali/public-api/shader-effects/shader-effect.h>
+#include <dali/devel-api/shader-effects/shader-effect.h>
 #include <dali/internal/event/common/property-helper.h>
-#include <dali/internal/event/common/stage-impl.h>
-#include <dali/internal/event/common/thread-local-storage.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/render/shaders/shader.h>
-#include <dali/internal/render/shaders/uniform-meta.h>
-#include <dali/internal/update/animation/scene-graph-constraint-base.h>
-#include <dali/internal/update/common/animatable-property.h>
-#include <dali/internal/update/manager/update-manager.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::RenderQueue;
 using std::string;
 
 namespace Dali
@@ -59,10 +47,10 @@ namespace
 
 //              Name             Type   writable animatable constraint-input  enum for index-checking
 DALI_PROPERTY_TABLE_BEGIN
-DALI_PROPERTY( "grid-density",   FLOAT,   true,    false,   false,   Dali::ShaderEffect::Property::GRID_DENSITY   )
+DALI_PROPERTY( "gridDensity",    FLOAT,   true,    false,   false,   Dali::ShaderEffect::Property::GRID_DENSITY   )
 DALI_PROPERTY( "image",          MAP,     true,    false,   false,   Dali::ShaderEffect::Property::IMAGE          )
 DALI_PROPERTY( "program",        MAP,     true,    false,   false,   Dali::ShaderEffect::Property::PROGRAM        )
-DALI_PROPERTY( "geometry-hints", STRING,  true,    false,   false,   Dali::ShaderEffect::Property::GEOMETRY_HINTS )
+DALI_PROPERTY( "geometryHints",  STRING,  true,    false,   false,   Dali::ShaderEffect::Property::GEOMETRY_HINTS )
 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
 
 BaseHandle Create()
@@ -82,102 +70,57 @@ struct WrapperStrings
   const char* fragmentShaderPostfix;
 };
 
-WrapperStrings customShaderWrappers [] =
+WrapperStrings customImageShaderWrappers =
 {
-  {
-    CustomImagePrefixVertex, CustomImagePrefixFragment,
-    CustomImagePostfixVertex, CustomImagePostfixFragment
-  },
-  {
-    CustomUntexturedMeshPrefixVertex, CustomUntexturedMeshPrefixFragment,
-    CustomUntexturedMeshPostfixVertex, CustomUntexturedMeshPostfixFragment
-  },
-  {
-    CustomTexturedMeshPrefixVertex, CustomTexturedMeshPrefixFragment,
-    CustomTexturedMeshPostfixVertex, CustomTexturedMeshPostfixFragment
-  }
+  CustomImagePrefixVertex, CustomImagePrefixFragment,
+  CustomImagePostfixVertex, CustomImagePostfixFragment
 };
 
 /**
- * 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
+ * Helper to wrap the program with our default pre and postfix if needed
  * @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_UNTEXTURED_MESH:
-      {
-        index = 1;
-        break;
-      }
-      case GEOMETRY_TYPE_TEXTURED_MESH:
-      {
-        index = 2;
-        break;
-      }
-      case GEOMETRY_TYPE_LAST:
-      {
-        DALI_ASSERT_DEBUG(0 && "Wrong geometry type");
-        break;
-      }
-    }
+std::string WrapVertexShader( const std::string& vertexPrefix, const std::string& vertexBody )
+{
+  std::string vertexSource = vertexPrefix + customImageShaderWrappers.vertexShaderPrefix;
 
-    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 );
-    }
+  // Append the custom vertex shader code if supplied, otherwise append the default
+  if ( vertexBody.length() > 0 )
+  {
+    vertexSource.append( vertexBody );
+  }
+  else
+  {
+    vertexSource.append( customImageShaderWrappers.vertexShaderPostfix );
+  }
 
-    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 );
-    }
+  return vertexSource;
+}
 
-    effect.SendProgramMessage( expectedGeometryType, SHADER_SUBTYPE_ALL, vertexSource, fragmentSource, modifiesGeometry );
+/**
+ * Helper to wrap the program with our default pre and postfix if needed
+ * @param[in] fragmentPrefix from application
+ * @param[in] fragmentBody from application
+ */
+std::string WrapFragmentShader( const std::string& fragmentPrefix, const std::string& fragmentBody )
+{
+  std::string fragmentSource = fragmentPrefix + customImageShaderWrappers.fragmentShaderPrefix;
+
+  // Append the custom fragment shader code if supplied, otherwise append the default
+  if ( fragmentBody.length() > 0 )
+  {
+    fragmentSource.append( fragmentBody );
   }
+  else
+  {
+    fragmentSource.append( customImageShaderWrappers.fragmentShaderPostfix );
+  }
+
+  return fragmentSource;
 }
 
-std::string GetShader(const std::string& field, const Property::Value& property)
+std::string GetStringProperty(const std::string& field, const Property::Value& property)
 {
   std::string retval;
   const Property::Map* map = property.GetMap();
@@ -193,189 +136,273 @@ std::string GetShader(const std::string& field, const Property::Value& property)
   return retval;
 }
 
+Dali::Shader::Hint::Value ConvertHints( Dali::ShaderEffect::GeometryHints hints)
+{
+  int convertedHints = Dali::Shader::Hint::NONE;
+
+  if( hints & Dali::ShaderEffect::HINT_BLENDING )
+  {
+    convertedHints |= Dali::Shader::Hint::OUTPUT_IS_TRANSPARENT;
+  }
+  if( !(hints & Dali::ShaderEffect::HINT_DOESNT_MODIFY_GEOMETRY) )
+  {
+    convertedHints |= Dali::Shader::Hint::MODIFIES_GEOMETRY;
+  }
+
+  return Dali::Shader::Hint::Value( convertedHints );
+}
+
 } // unnamed namespace
 
 ShaderEffectPtr ShaderEffect::New( Dali::ShaderEffect::GeometryHints hints )
 {
-  Stage* stage = Stage::GetCurrent();
-
-  ShaderEffectPtr shaderEffect( new ShaderEffect( *stage, hints ) );
+  ShaderEffectPtr shaderEffect( new ShaderEffect( hints ) );
   shaderEffect->RegisterObject();
-
   return shaderEffect;
 }
 
-ShaderEffect::ShaderEffect( EventThreadServices& eventThreadServices, Dali::ShaderEffect::GeometryHints hints )
-: mEventThreadServices( eventThreadServices ),
-  mConnectionCount (0),
+ShaderEffect::ShaderEffect( Dali::ShaderEffect::GeometryHints hints )
+: mGridDensity( Dali::ShaderEffect::DEFAULT_GRID_DENSITY ),
   mGeometryHints( hints )
 {
-  mSceneObject = new Shader( hints );
-  DALI_ASSERT_DEBUG( NULL != mSceneObject );
-
-  // Transfer shader ownership to a scene message
-  AddShaderMessage( eventThreadServices.GetUpdateManager(), *mSceneObject );
 }
 
 ShaderEffect::~ShaderEffect()
 {
   // Guard to allow handle destruction after Core has been destroyed
-  if ( Stage::IsInstalled() )
-  {
-    // Remove scene-object using a message to the UpdateManager
-    if( mSceneObject )
-    {
-      RemoveShaderMessage( mEventThreadServices.GetUpdateManager(), *mSceneObject );
-    }
-    UnregisterObject();
-  }
+  UnregisterObject();
 }
 
 void ShaderEffect::SetEffectImage( Dali::Image image )
 {
   // if images are the same, do nothing
-  if (mImage == image)
+  if ( mEffectImage == image )
   {
     return;
   }
 
-  if (mImage && mConnectionCount > 0)
+  if ( mEffectImage && mConnectedActors.size() > 0 )
   {
     // unset previous image
-    GetImplementation(mImage).Disconnect();
+    GetImplementation( mEffectImage ).Disconnect();
   }
 
   // in case image is empty this will reset our image handle
-  mImage = image;
+  mEffectImage = image;
 
-  if (!image)
-  {
-    // mSceneShader can be in a separate thread; queue a setter message
-    SetTextureIdMessage( mEventThreadServices, *mSceneObject, 0 );
-  }
-  else
+  if( image )
   {
     // tell image that we're using it
-    if (mConnectionCount > 0)
+    if (mConnectedActors.size() > 0)
     {
-      GetImplementation(mImage).Connect();
+      GetImplementation( mEffectImage ).Connect();
     }
-    // mSceneShader can be in a separate thread; queue a setter message
-    SetTextureIdMessage( mEventThreadServices, *mSceneObject, GetImplementation(mImage).GetResourceId() );
   }
+
+  //inform connected actors the image has been unset
+  // TODO or CHECK: ImageActor part was removed.
 }
 
 void ShaderEffect::SetUniform( const std::string& name, Property::Value value, UniformCoordinateType uniformCoordinateType )
 {
   // Register the property if it does not exist
-  Property::Index index = GetPropertyIndex( name );
-  if ( Property::INVALID_INDEX == index )
+  mShader->RegisterProperty( name, value );
+}
+
+void ShaderEffect::SetPrograms( const string& vertexSource, const string& fragmentSource )
+{
+  SetPrograms( "", "", vertexSource, fragmentSource );
+}
+
+void ShaderEffect::SetPrograms( const std::string& vertexPrefix, const std::string& fragmentPrefix,
+                                const std::string& vertexSource, const std::string& fragmentSource )
+{
+  mShader = Shader::New( WrapVertexShader( vertexPrefix, vertexSource ),
+                         WrapFragmentShader( fragmentPrefix, fragmentSource ),
+                         ConvertHints( mGeometryHints ) );
+}
+
+Vector2 ShaderEffect::GetGridSize( const Vector2& size )
+{
+  Vector2 gridSize( 1.f, 1.f );
+
+  if( mGridDensity > 0 )
   {
-    index = RegisterProperty( name, value );
+    if( ( mGeometryHints & Dali::ShaderEffect::HINT_GRID_X ) )
+    {
+      gridSize.x = ceil( size.width / mGridDensity );
+    }
+    if( ( mGeometryHints & Dali::ShaderEffect::HINT_GRID_Y ) )
+    {
+      gridSize.y = ceil( size.height / mGridDensity );
+    }
   }
 
-  SetProperty( index, value );
+  return gridSize;
+}
+
+void ShaderEffect::Connect( ActorPtr actor )
+{
+  if( !actor )
+  {
+    return;
+  }
 
-  // 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) )
+  std::vector< ActorPtr >::const_iterator it = std::find( mConnectedActors.begin(), mConnectedActors.end(), actor );
+  if( it == mConnectedActors.end() )
   {
-    mCoordinateTypes.Resize( metaIndex + 1 );
+    mConnectedActors.push_back( actor );
   }
-  // only send message if the value is different than current, initial value is COORDINATE_TYPE_DEFAULT (0)
-  if( uniformCoordinateType != mCoordinateTypes[ metaIndex ] )
+
+  if( mEffectImage && mConnectedActors.size() == 1 )
   {
-    mCoordinateTypes[ metaIndex ] = uniformCoordinateType;
-    SetCoordinateTypeMessage( mEventThreadServices, *mSceneObject, metaIndex, uniformCoordinateType );
+    GetImplementation( mEffectImage ).Connect();
   }
 }
-
-void ShaderEffect::AttachExtension( Dali::ShaderEffect::Extension *extension )
+void ShaderEffect::Disconnect( ActorPtr actor )
 {
-  DALI_ASSERT_ALWAYS( extension != NULL && "Attaching uninitialized extension" );
-  mExtension = IntrusivePtr<Dali::ShaderEffect::Extension>( extension );
+  if( !actor )
+  {
+    return;
+  }
+
+  DALI_ASSERT_DEBUG(mConnectedActors.size() > 0);
+  std::vector< ActorPtr >::iterator match( std::remove( mConnectedActors.begin(), mConnectedActors.end(), actor ) );
+  mConnectedActors.erase( match, mConnectedActors.end() );
+
+  if (mEffectImage && mConnectedActors.size() == 0)
+  {
+     GetImplementation(mEffectImage).Disconnect();
+  }
 }
 
-Dali::ShaderEffect::Extension& ShaderEffect::GetExtension()
+unsigned int ShaderEffect::GetPropertyCount() const
 {
-  DALI_ASSERT_ALWAYS( mExtension && "Getting uninitialized extension" );
-  return *mExtension;
+  return GetDefaultPropertyCount() + mShader->GetPropertyCount();
 }
 
-const Dali::ShaderEffect::Extension& ShaderEffect::GetExtension() const
+std::string ShaderEffect::GetPropertyName( Property::Index index ) const
 {
-  DALI_ASSERT_ALWAYS( mExtension && "Getting uninitialized extension" );
-  return *mExtension;
+  if ( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return GetDefaultPropertyName( index );
+  }
+  else
+  {
+    return mShader->GetPropertyName( index );
+  }
 }
 
-void ShaderEffect::SetPrograms( GeometryType geometryType, const string& vertexSource, const string& fragmentSource )
+Property::Index ShaderEffect::GetPropertyIndex( const std::string& name ) const
 {
-  SetPrograms( geometryType, "", "", vertexSource, fragmentSource );
+  Property::Index index = GetDefaultPropertyIndex( name );
+  if( index == Property::INVALID_INDEX )
+  {
+    return mShader->GetPropertyIndex( name );
+  }
+  else
+  {
+    return index;
+  }
 }
 
-void ShaderEffect::SetPrograms( GeometryType geometryType,
-                                const std::string& vertexPrefix, const std::string& fragmentPrefix,
-                                const std::string& vertexSource, const std::string& fragmentSource )
+bool ShaderEffect::IsPropertyWritable( Property::Index index ) const
 {
-  bool modifiesGeometry = true;
-  // check if the vertex shader is empty (means it cannot modify geometry)
-  if( (vertexPrefix.length() == 0 )&&( vertexSource.length() == 0 ) )
+  if ( index < DEFAULT_PROPERTY_COUNT )
   {
-    modifiesGeometry = false;
+    return IsDefaultPropertyWritable( index );
   }
-  // check the hint second
-  if( (mGeometryHints & Dali::ShaderEffect::HINT_DOESNT_MODIFY_GEOMETRY ) != 0 )
+  else
   {
-    modifiesGeometry = false;
+    return mShader->IsPropertyWritable( index );
   }
+}
 
-  WrapAndSetProgram( *this, geometryType, GEOMETRY_TYPE_IMAGE, 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 );
+bool ShaderEffect::IsPropertyAnimatable( Property::Index index ) const
+{
+  if ( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return IsDefaultPropertyAnimatable( index );
+  }
+  else
+  {
+    return mShader->IsPropertyAnimatable( index );
+  }
 }
 
-void ShaderEffect::SendProgramMessage( GeometryType geometryType, ShaderSubTypes subType,
-                                       const string& vertexSource, const string& fragmentSource,
-                                       bool modifiesGeometry )
+bool ShaderEffect::IsPropertyAConstraintInput( Property::Index index ) const
 {
-  ThreadLocalStorage& tls = ThreadLocalStorage::Get();
-  ShaderFactory& shaderFactory = tls.GetShaderFactory();
-  size_t shaderHash;
+  if ( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return IsDefaultPropertyAConstraintInput( index );
+  }
+  else
+  {
+    return mShader->IsPropertyAConstraintInput( index );
+  }
+}
 
-  ResourceTicketPtr ticket( shaderFactory.Load(vertexSource, fragmentSource, shaderHash) );
+Property::Type ShaderEffect::GetPropertyType( Property::Index index ) const
+{
+  if ( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return GetDefaultPropertyType( index );
+  }
+  return mShader->GetPropertyType( index );
+}
 
-  DALI_LOG_INFO( Debug::Filter::gShader, Debug::General, "ShaderEffect: SetProgram(geometryType %d subType:%d ticket.id:%d)\n", geometryType, subType, ticket->GetId() );
+void ShaderEffect::SetProperty( Property::Index index, const Property::Value& propertyValue )
+{
+  if ( index < DEFAULT_PROPERTY_COUNT )
+  {
+    SetDefaultProperty( index, propertyValue );
+  }
+  else
+  {
+    mShader->SetProperty( index, propertyValue );
+  }
+}
 
-  // Add shader program to scene-object using a message to the UpdateManager
-  SetShaderProgramMessage( mEventThreadServices.GetUpdateManager(), *mSceneObject, geometryType, subType, ticket->GetId(), shaderHash, modifiesGeometry );
+Property::Value ShaderEffect::GetProperty( Property::Index index ) const
+{
+  if ( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return GetDefaultProperty( index );
+  }
+  return mShader->GetProperty( index );
+}
 
-  mTickets.push_back(ticket);       // add ticket to collection to keep it alive.
+void ShaderEffect::GetPropertyIndices( Property::IndexContainer& indices ) const
+{
+  mShader->GetPropertyIndices( indices );
+  GetDefaultPropertyIndices( indices );
 }
 
-void ShaderEffect::Connect()
+Property::Index ShaderEffect::RegisterProperty( const std::string& name, const Property::Value& propertyValue )
 {
-  ++mConnectionCount;
+  return mShader->RegisterProperty( name, propertyValue );
+}
 
-  if (mImage && mConnectionCount == 1)
-  {
-    GetImplementation(mImage).Connect();
+Property::Index ShaderEffect::RegisterProperty( const std::string& name, const Property::Value& propertyValue, Property::AccessMode accessMode )
+{
+  return mShader->RegisterProperty( name, propertyValue, accessMode );
+}
 
-    // Image may have changed resource due to load/release policy. Ensure correct texture ID is set on scene graph object
-    SetTextureIdMessage( mEventThreadServices, *mSceneObject, GetImplementation(mImage).GetResourceId() );
-  }
+Dali::PropertyNotification ShaderEffect::AddPropertyNotification( Property::Index index,
+                                                                  int componentIndex,
+                                                                  const Dali::PropertyCondition& condition )
+{
+  return mShader->AddPropertyNotification( index, componentIndex, condition );
 }
 
-void ShaderEffect::Disconnect()
+void ShaderEffect::RemovePropertyNotification( Dali::PropertyNotification propertyNotification )
 {
-  DALI_ASSERT_DEBUG(mConnectionCount > 0);
-  --mConnectionCount;
+  mShader->RemovePropertyNotification( propertyNotification );
+}
 
-  if (mImage && mConnectionCount == 0)
-  {
-     GetImplementation(mImage).Disconnect();
-  }
+void ShaderEffect::RemovePropertyNotifications()
+{
+  mShader->RemovePropertyNotifications();
 }
 
 unsigned int ShaderEffect::GetDefaultPropertyCount() const
@@ -385,7 +412,7 @@ unsigned int ShaderEffect::GetDefaultPropertyCount() const
 
 void ShaderEffect::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
 {
-  indices.Reserve( DEFAULT_PROPERTY_COUNT );
+  indices.Reserve( indices.Size() + DEFAULT_PROPERTY_COUNT );
 
   for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
   {
@@ -453,7 +480,16 @@ void ShaderEffect::SetDefaultProperty( Property::Index index, const Property::Va
   {
     case Dali::ShaderEffect::Property::GRID_DENSITY:
     {
-      SetGridDensityMessage( mEventThreadServices, *mSceneObject, propertyValue.Get<float>() );
+      propertyValue.Get( mGridDensity );
+      if( ( mGeometryHints & Dali::ShaderEffect::HINT_GRID_X ) ||
+          ( mGeometryHints & Dali::ShaderEffect::HINT_GRID_Y ) )
+      {
+        //inform all the connected actors
+        for(std::vector< ActorPtr >::iterator it = mConnectedActors.begin(); it != mConnectedActors.end(); ++it )
+        {
+          (*it)->RelayoutRequest();
+        }
+      }
       break;
     }
 
@@ -473,55 +509,51 @@ void ShaderEffect::SetDefaultProperty( Property::Index index, const Property::Va
 
     case Dali::ShaderEffect::Property::PROGRAM:
     {
-      std::string vertexPrefix   = GetShader("vertex-prefix", propertyValue);
-      std::string fragmentPrefix = GetShader("fragment-prefix", propertyValue);
-      std::string vertex         = GetShader("vertex", propertyValue);
-      std::string fragment       = GetShader("fragment", propertyValue);
+      std::string vertexPrefix   = GetStringProperty("vertexPrefix",  propertyValue);
+      std::string fragmentPrefix = GetStringProperty("fragmentPrefix",  propertyValue);
+      std::string vertex         = GetStringProperty("vertex", propertyValue);
+      std::string fragment       = GetStringProperty("fragment", propertyValue);
 
-      GeometryType geometryType      = GEOMETRY_TYPE_IMAGE; // only images are supported
-      SetPrograms( geometryType, vertexPrefix, fragmentPrefix, vertex, fragment );
+      SetPrograms( vertexPrefix, fragmentPrefix, vertex, fragment );
       break;
     }
 
     case Dali::ShaderEffect::Property::GEOMETRY_HINTS:
     {
-      Dali::ShaderEffect::GeometryHints hint = Dali::ShaderEffect::HINT_NONE;
+      mGeometryHints = Dali::ShaderEffect::HINT_NONE;
       std::string s = propertyValue.Get<std::string>();
       if(s == "HINT_NONE")
       {
-        hint = Dali::ShaderEffect::HINT_NONE;
+        mGeometryHints = Dali::ShaderEffect::HINT_NONE;
       }
       else if(s == "HINT_GRID_X")
       {
-        hint = Dali::ShaderEffect::HINT_GRID_X;
+        mGeometryHints = Dali::ShaderEffect::HINT_GRID_X;
       }
       else if(s == "HINT_GRID_Y")
       {
-        hint = Dali::ShaderEffect::HINT_GRID_Y;
+        mGeometryHints = Dali::ShaderEffect::HINT_GRID_Y;
       }
       else if(s == "HINT_GRID")
       {
-        hint = Dali::ShaderEffect::HINT_GRID;
+        mGeometryHints = Dali::ShaderEffect::HINT_GRID;
       }
       else if(s == "HINT_DEPTH_BUFFER")
       {
-        hint = Dali::ShaderEffect::HINT_DEPTH_BUFFER;
+        mGeometryHints = Dali::ShaderEffect::HINT_DEPTH_BUFFER;
       }
       else if(s == "HINT_BLENDING")
       {
-        hint = Dali::ShaderEffect::HINT_BLENDING;
+        mGeometryHints = Dali::ShaderEffect::HINT_BLENDING;
       }
       else if(s == "HINT_DOESNT_MODIFY_GEOMETRY")
       {
-        hint = Dali::ShaderEffect::HINT_DOESNT_MODIFY_GEOMETRY;
+        mGeometryHints = Dali::ShaderEffect::HINT_DOESNT_MODIFY_GEOMETRY;
       }
       else
       {
         DALI_ASSERT_ALWAYS(!"Geometry hint unknown" );
       }
-
-      SetHintsMessage( mEventThreadServices, *mSceneObject, hint );
-
       break;
     }
 
@@ -539,31 +571,24 @@ Property::Value ShaderEffect::GetDefaultProperty(Property::Index /*index*/) cons
   return Property::Value();
 }
 
-void ShaderEffect::NotifyScenePropertyInstalled( const SceneGraph::PropertyBase& newProperty, const std::string& name, unsigned int index ) const
+const SceneGraph::PropertyOwner* ShaderEffect::GetSceneObject() const
 {
-  // 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 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( mEventThreadServices, *mSceneObject, *meta ); // Message takes ownership
+  return mShader->GetSceneObject();
 }
 
-const SceneGraph::PropertyOwner* ShaderEffect::GetSceneObject() const
+const SceneGraph::PropertyBase* ShaderEffect::GetSceneObjectAnimatableProperty( Property::Index index ) const
 {
-  return mSceneObject;
+  return mShader->GetSceneObjectAnimatableProperty( index );
 }
 
-const PropertyBase* ShaderEffect::GetSceneObjectAnimatableProperty( Property::Index index ) const
+const PropertyInputImpl* ShaderEffect::GetSceneObjectInputProperty( Property::Index index ) const
 {
-  PropertyMetadata* property = index >= PROPERTY_CUSTOM_START_INDEX ? static_cast<PropertyMetadata*>(FindCustomProperty( index )) : static_cast<PropertyMetadata*>(FindAnimatableProperty( index ));
-  DALI_ASSERT_ALWAYS( property && "Property index is invalid" );
-  return property->GetSceneGraphProperty();
+  return mShader->GetSceneObjectInputProperty( index );
 }
 
-const PropertyInputImpl* ShaderEffect::GetSceneObjectInputProperty( Property::Index index ) const
+int ShaderEffect::GetPropertyComponentIndex( Property::Index index ) const
 {
-  return GetSceneObjectAnimatableProperty( index );
+  return mShader->GetPropertyComponentIndex( index );
 }
 
 } // namespace Internal