Added double buffered properties that can be aged 54/37654/1
authorDavid Steele <david.steele@partner.samsung.com>
Wed, 1 Apr 2015 17:34:51 +0000 (18:34 +0100)
committerDavid Steele <david.steele@partner.samsung.com>
Wed, 1 Apr 2015 17:34:51 +0000 (18:34 +0100)
There is currently no means of aging a double buffered value on successive updates.
Added a new templated type DoubleBufferedProperty, which holds a double buffered
value type, and can be 'aged' by calling CopyPrevious.

Users of this type (e.g. SceneGraph::Geometry, etc) will call the CopyPrevious method
in the ResetDefaultProperties method (alongside resetting AnimatableProperty values with ResetToBaseValue()).

Removed ownership of scene graph property buffers from Geometry - they are fully
owned by UpdateManager. Instead, Geometry now holds raw pointers to the buffers.

Change-Id: I4682b3f31eb7947fb19ae34871bdc840e9553d5e
Signed-off-by: David Steele <david.steele@partner.samsung.com>
21 files changed:
dali/internal/event/actors/renderer-impl.cpp
dali/internal/event/common/object-impl-helper.h
dali/internal/event/effects/material-impl.cpp
dali/internal/event/effects/sampler-impl.cpp
dali/internal/event/geometry/geometry-impl.cpp
dali/internal/render/data-providers/geometry-data-provider.h
dali/internal/render/data-providers/material-data-provider.h
dali/internal/render/data-providers/uniform-map-data-provider.h
dali/internal/render/renderers/render-geometry.cpp
dali/internal/update/common/double-buffered-property.h [new file with mode: 0644]
dali/internal/update/common/inherited-property.h
dali/internal/update/common/property-owner-messages.cpp
dali/internal/update/common/property-owner-messages.h
dali/internal/update/effects/scene-graph-material.cpp
dali/internal/update/effects/scene-graph-material.h
dali/internal/update/effects/scene-graph-sampler.cpp
dali/internal/update/effects/scene-graph-sampler.h
dali/internal/update/geometry/scene-graph-geometry.cpp
dali/internal/update/geometry/scene-graph-geometry.h
dali/internal/update/node-attachments/scene-graph-renderer-attachment.cpp
dali/internal/update/node-attachments/scene-graph-renderer-attachment.h

index 45aa14e..42a935e 100644 (file)
@@ -69,7 +69,7 @@ void Renderer::SetMaterial( Material& material )
 
 void Renderer::SetDepthIndex( int depthIndex )
 {
-  SceneGraph::PropertyMessage<int>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mDepthIndex, &SceneGraph::AnimatableProperty<int>::Bake, depthIndex );
+  SceneGraph::AnimatablePropertyMessage<int>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mDepthIndex, &SceneGraph::AnimatableProperty<int>::Bake, depthIndex );
 }
 
 int Renderer::GetCurrentDepthIndex() const
index aeae9c1..1abc7c2 100644 (file)
@@ -201,7 +201,7 @@ struct ObjectImplHelper
         DALI_ASSERT_DEBUG( NULL != property );
 
         // property is being used in a separate thread; queue a message to set the property
-        SceneGraph::PropertyMessage<bool>::Send( eventThreadServices, sceneObject, property, &SceneGraph::AnimatableProperty<bool>::Bake, value.Get<bool>() );
+        SceneGraph::AnimatablePropertyMessage<bool>::Send( eventThreadServices, sceneObject, property, &SceneGraph::AnimatableProperty<bool>::Bake, value.Get<bool>() );
 
         break;
       }
@@ -212,7 +212,7 @@ struct ObjectImplHelper
         DALI_ASSERT_DEBUG( NULL != property );
 
         // property is being used in a separate thread; queue a message to set the property
-        SceneGraph::PropertyMessage<float>::Send( eventThreadServices, sceneObject, property, &SceneGraph::AnimatableProperty<float>::Bake, value.Get<float>() );
+        SceneGraph::AnimatablePropertyMessage<float>::Send( eventThreadServices, sceneObject, property, &SceneGraph::AnimatableProperty<float>::Bake, value.Get<float>() );
 
         break;
       }
@@ -223,7 +223,7 @@ struct ObjectImplHelper
         DALI_ASSERT_DEBUG( NULL != property );
 
         // property is being used in a separate thread; queue a message to set the property
-        SceneGraph::PropertyMessage<int>::Send( eventThreadServices, sceneObject, property, &SceneGraph::AnimatableProperty<int>::Bake, value.Get<int>() );
+        SceneGraph::AnimatablePropertyMessage<int>::Send( eventThreadServices, sceneObject, property, &SceneGraph::AnimatableProperty<int>::Bake, value.Get<int>() );
 
         break;
       }
@@ -234,7 +234,7 @@ struct ObjectImplHelper
         DALI_ASSERT_DEBUG( NULL != property );
 
         // property is being used in a separate thread; queue a message to set the property
-        SceneGraph::PropertyMessage<Vector2>::Send( eventThreadServices, sceneObject, property, &SceneGraph::AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
+        SceneGraph::AnimatablePropertyMessage<Vector2>::Send( eventThreadServices, sceneObject, property, &SceneGraph::AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
 
         break;
       }
@@ -245,7 +245,7 @@ struct ObjectImplHelper
         DALI_ASSERT_DEBUG( NULL != property );
 
         // property is being used in a separate thread; queue a message to set the property
-        SceneGraph::PropertyMessage<Vector3>::Send( eventThreadServices, sceneObject, property, &SceneGraph::AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
+        SceneGraph::AnimatablePropertyMessage<Vector3>::Send( eventThreadServices, sceneObject, property, &SceneGraph::AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
 
         break;
       }
@@ -256,7 +256,7 @@ struct ObjectImplHelper
         DALI_ASSERT_DEBUG( NULL != property );
 
         // property is being used in a separate thread; queue a message to set the property
-        SceneGraph::PropertyMessage<Vector4>::Send( eventThreadServices, sceneObject, property, &SceneGraph::AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
+        SceneGraph::AnimatablePropertyMessage<Vector4>::Send( eventThreadServices, sceneObject, property, &SceneGraph::AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
 
         break;
       }
@@ -267,7 +267,7 @@ struct ObjectImplHelper
         DALI_ASSERT_DEBUG( NULL != property );
 
         // property is being used in a separate thread; queue a message to set the property
-        SceneGraph::PropertyMessage<Quaternion>::Send( eventThreadServices, sceneObject, property,&SceneGraph::AnimatableProperty<Quaternion>::Bake,  value.Get<Quaternion>() );
+        SceneGraph::AnimatablePropertyMessage<Quaternion>::Send( eventThreadServices, sceneObject, property,&SceneGraph::AnimatableProperty<Quaternion>::Bake,  value.Get<Quaternion>() );
 
         break;
       }
@@ -278,7 +278,7 @@ struct ObjectImplHelper
         DALI_ASSERT_DEBUG( NULL != property );
 
         // property is being used in a separate thread; queue a message to set the property
-        SceneGraph::PropertyMessage<Matrix>::Send( eventThreadServices, sceneObject, property,&SceneGraph::AnimatableProperty<Matrix>::Bake,  value.Get<Matrix>() );
+        SceneGraph::AnimatablePropertyMessage<Matrix>::Send( eventThreadServices, sceneObject, property,&SceneGraph::AnimatableProperty<Matrix>::Bake,  value.Get<Matrix>() );
 
         break;
       }
@@ -289,7 +289,7 @@ struct ObjectImplHelper
         DALI_ASSERT_DEBUG( NULL != property );
 
         // property is being used in a separate thread; queue a message to set the property
-        SceneGraph::PropertyMessage<Matrix3>::Send( eventThreadServices, sceneObject, property, &SceneGraph::AnimatableProperty<Matrix3>::Bake,  value.Get<Matrix3>() );
+        SceneGraph::AnimatablePropertyMessage<Matrix3>::Send( eventThreadServices, sceneObject, property, &SceneGraph::AnimatableProperty<Matrix3>::Bake,  value.Get<Matrix3>() );
 
         break;
       }
index 2da87a4..d338c75 100644 (file)
@@ -91,8 +91,10 @@ void Material::RemoveSampler( std::size_t index )
 
 void Material::SetFaceCullingMode( Dali::Material::FaceCullingMode cullingMode )
 {
-  // TODO: MESH_REWORK
-  DALI_ASSERT_ALWAYS( false && "TODO: MESH_REWORK" );
+  if( NULL != mSceneObject )
+  {
+    SceneGraph::DoubleBufferedPropertyMessage<int>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mFaceCullingMode, &SceneGraph::DoubleBufferedProperty<int>::Set, static_cast<int>(cullingMode) );
+  }
 }
 
 void Material::SetBlendMode( BlendingMode::Type mode )
@@ -154,15 +156,15 @@ void Material::GetBlendEquation( BlendingEquation::Type& equationRgb,
 
 void Material::SetBlendColor( const Vector4& color )
 {
-  // TODO: MESH_REWORK
-  DALI_ASSERT_ALWAYS( false && "TODO: MESH_REWORK" );
+  if( mSceneObject )
+  {
+    SceneGraph::AnimatablePropertyMessage<Vector4>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mBlendColor, &SceneGraph::AnimatableProperty<Vector4>::Bake, color );
+  }
 }
 
 const Vector4& Material::GetBlendColor() const
 {
-  // TODO: MESH_REWORK
-  DALI_ASSERT_ALWAYS( false && "TODO: MESH_REWORK" );
-  return Color::WHITE;
+  return mSceneObject->mBlendColor[ GetEventThreadServices().GetEventBufferIndex() ];
 }
 
 const SceneGraph::Material* Material::GetMaterialSceneObject() const
@@ -217,12 +219,12 @@ void Material::SetDefaultProperty( Property::Index index,
   {
     case Dali::Material::Property::COLOR:
     {
-      SceneGraph::PropertyMessage<Vector4>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mColor, &SceneGraph::AnimatableProperty<Vector4>::Bake, propertyValue.Get<Vector4>() );
+      SceneGraph::AnimatablePropertyMessage<Vector4>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mColor, &SceneGraph::AnimatableProperty<Vector4>::Bake, propertyValue.Get<Vector4>() );
       break;
     }
     case Dali::Material::Property::FACE_CULLING_MODE:
     {
-      DALI_ASSERT_ALWAYS( 0 && "Mesh Rework" );
+      SceneGraph::DoubleBufferedPropertyMessage<int>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mFaceCullingMode, &SceneGraph::DoubleBufferedProperty<int>::Set, propertyValue.Get<int>() );
       break;
     }
     case Dali::Material::Property::BLENDING_MODE:
@@ -257,7 +259,7 @@ void Material::SetDefaultProperty( Property::Index index,
     }
     case Dali::Material::Property::BLEND_COLOR:
     {
-      SceneGraph::PropertyMessage<Vector4>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mBlendColor, &SceneGraph::AnimatableProperty<Vector4>::Bake, propertyValue.Get<Vector4>() );
+      SceneGraph::AnimatablePropertyMessage<Vector4>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mBlendColor, &SceneGraph::AnimatableProperty<Vector4>::Bake, propertyValue.Get<Vector4>() );
       break;
     }
   }
@@ -288,7 +290,10 @@ Property::Value Material::GetDefaultProperty( Property::Index index ) const
     }
     case Dali::Material::Property::FACE_CULLING_MODE:
     {
-      DALI_ASSERT_ALWAYS( 0 && "Mesh Rework" );
+      if( mSceneObject )
+      {
+        value = mSceneObject->mFaceCullingMode[bufferIndex];
+      }
       break;
     }
     case Dali::Material::Property::BLENDING_MODE:
@@ -407,7 +412,7 @@ const PropertyInputImpl* Material::GetSceneObjectInputProperty( Property::Index
         }
         case Dali::Material::Property::FACE_CULLING_MODE:
         {
-          DALI_ASSERT_ALWAYS( 0 && "Mesh Rework" );
+          property = &mSceneObject->mFaceCullingMode;
           break;
         }
         case Dali::Material::Property::BLENDING_MODE:
index 8a27378..9634eb5 100644 (file)
@@ -63,8 +63,6 @@ void Sampler::SetUniformName( const std::string& name )
 
 void Sampler::SetImage( Image& image )
 {
-  // TODO: MESH_REWORK - should probably review this comment
-
   unsigned int resourceId = image.GetResourceId();
 
   // sceneObject is being used in a separate thread; queue a message to set
@@ -73,8 +71,6 @@ void Sampler::SetImage( Image& image )
 
 void Sampler::SetFilterMode( Dali::Sampler::FilterMode minFilter, Dali::Sampler::FilterMode magFilter )
 {
-  // TODO: MESH_REWORK
-  DALI_ASSERT_ALWAYS( false && "TODO: MESH_REWORK" );
 }
 
 void Sampler::SetWrapMode( Dali::Sampler::WrapMode uWrap, Dali::Sampler::WrapMode vWrap )
index 0a55826..8bb4028 100644 (file)
@@ -21,6 +21,7 @@
 // INTERNAL INCLUDES
 #include <dali/internal/event/common/object-impl-helper.h> // Dali::Internal::ObjectHelper
 #include <dali/internal/event/common/property-helper.h> // DALI_PROPERTY_TABLE_BEGIN, DALI_PROPERTY, DALI_PROPERTY_TABLE_END
+#include <dali/internal/update/common/double-buffered-property.h>
 #include <dali/internal/update/manager/update-manager.h>
 
 namespace Dali
@@ -57,6 +58,11 @@ std::size_t Geometry::AddVertexBuffer( PropertyBuffer& vertexBuffer )
   PropertyBufferConnector connector;
   connector.Set( vertexBuffer, OnStage() );
   mVertexBufferConnectors.push_back( connector );
+
+  const SceneGraph::PropertyBuffer& sceneGraphPropertyBuffer = dynamic_cast<const SceneGraph::PropertyBuffer&>( *vertexBuffer.GetSceneObject() );
+
+  SceneGraph::AddVertexBufferMessage( GetEventThreadServices(), *mSceneObject, sceneGraphPropertyBuffer );
+
   return mVertexBufferConnectors.size() - 1u;
 }
 
@@ -73,30 +79,40 @@ void Geometry::RemoveVertexBuffer( std::size_t index )
 void Geometry::SetIndexBuffer( PropertyBuffer& indexBuffer )
 {
   mIndexBufferConnector.Set( indexBuffer, OnStage() );
+
+  const SceneGraph::PropertyBuffer& sceneGraphPropertyBuffer = dynamic_cast<const SceneGraph::PropertyBuffer&>( *indexBuffer.GetSceneObject() );
+
+  SceneGraph::SetIndexBufferMessage( GetEventThreadServices(), *mSceneObject, sceneGraphPropertyBuffer );
 }
 
 void Geometry::SetGeometryType( Dali::Geometry::GeometryType geometryType )
 {
-  //TODO: MESH_REWORK
-  DALI_ASSERT_ALWAYS( false && "MESH REWORK" );
+  if( NULL != mSceneObject )
+  {
+    SceneGraph::DoubleBufferedPropertyMessage<int>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mGeometryType, &SceneGraph::DoubleBufferedProperty<int>::Set, static_cast<int>(geometryType) );
+  }
 }
 
 Dali::Geometry::GeometryType Geometry::GetGeometryType() const
 {
-  //TODO: MESH_REWORK
-  return Dali::Geometry::TRIANGLES;
+  return mSceneObject->GetGeometryType(GetEventThreadServices().GetEventBufferIndex());
 }
 
 void Geometry::SetRequiresDepthTesting( bool requiresDepthTest )
 {
-  //TODO: MESH_REWORK
-  DALI_ASSERT_ALWAYS( false && "MESH REWORK" );
+  if( NULL != mSceneObject )
+  {
+    SceneGraph::DoubleBufferedPropertyMessage<bool>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mRequiresDepthTest, &SceneGraph::DoubleBufferedProperty<bool>::Set, static_cast<int>(requiresDepthTest) );
+  }
 }
 
 bool Geometry::GetRequiresDepthTesting() const
 {
-  //TODO: MESH_REWORK
-  DALI_ASSERT_ALWAYS( false && "MESH REWORK" );
+  if( mSceneObject )
+  {
+    // mSceneObject is being used in a separate thread; copy the value from the previous update
+    return mSceneObject->GetRequiresDepthTesting(GetEventThreadServices().GetEventBufferIndex());
+  }
   return false;
 }
 
@@ -152,24 +168,24 @@ void Geometry::SetDefaultProperty( Property::Index index,
   {
     case Dali::Geometry::Property::GEOMETRY_TYPE :
     {
-      DALI_ASSERT_ALWAYS( 0 && "MESH_REWORK" );
+      SceneGraph::DoubleBufferedPropertyMessage<int>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mGeometryType, &SceneGraph::DoubleBufferedProperty<int>::Set, propertyValue.Get<int>() );
       break;
     }
     case Dali::Geometry::Property::GEOMETRY_CENTER :
     {
-      SceneGraph::PropertyMessage<Vector3>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mCenter, &SceneGraph::AnimatableProperty<Vector3>::Bake, propertyValue.Get<Vector3>() );
+      SceneGraph::AnimatablePropertyMessage<Vector3>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mCenter, &SceneGraph::AnimatableProperty<Vector3>::Bake, propertyValue.Get<Vector3>() );
       break;
     }
 
     case Dali::Geometry::Property::GEOMETRY_HALF_EXTENTS :
     {
-      SceneGraph::PropertyMessage<Vector3>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mHalfExtents, &SceneGraph::AnimatableProperty<Vector3>::Bake, propertyValue.Get<Vector3>() );
+      SceneGraph::AnimatablePropertyMessage<Vector3>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mHalfExtents, &SceneGraph::AnimatableProperty<Vector3>::Bake, propertyValue.Get<Vector3>() );
       break;
     }
 
     case Dali::Geometry::Property::REQUIRES_DEPTH_TEST :
     {
-      DALI_ASSERT_ALWAYS( 0 && "MESH_REWORK" );
+      SceneGraph::DoubleBufferedPropertyMessage<bool>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mRequiresDepthTest, &SceneGraph::DoubleBufferedProperty<bool>::Set, propertyValue.Get<bool>() );
       break;
     }
   }
@@ -191,7 +207,10 @@ Property::Value Geometry::GetDefaultProperty( Property::Index index ) const
   {
     case Dali::Geometry::Property::GEOMETRY_TYPE :
     {
-      DALI_ASSERT_ALWAYS( 0 && "MESH_REWORK" );
+      if( mSceneObject )
+      {
+        value = mSceneObject->mGeometryType[bufferIndex];
+      }
       break;
     }
     case Dali::Geometry::Property::GEOMETRY_CENTER :
@@ -214,7 +233,10 @@ Property::Value Geometry::GetDefaultProperty( Property::Index index ) const
 
     case Dali::Geometry::Property::REQUIRES_DEPTH_TEST :
     {
-      DALI_ASSERT_ALWAYS( 0 && "MESH_REWORK" );
+      if( mSceneObject )
+      {
+        value = mSceneObject->mRequiresDepthTest[bufferIndex];
+      }
       break;
     }
   }
@@ -288,7 +310,7 @@ const PropertyInputImpl* Geometry::GetSceneObjectInputProperty( Property::Index
       {
         case Dali::Geometry::Property::GEOMETRY_TYPE :
         {
-          DALI_ASSERT_ALWAYS( 0 && "MESH_REWORK" );
+          property = &mSceneObject->mGeometryType;
           break;
         }
         case Dali::Geometry::Property::GEOMETRY_CENTER :
@@ -303,7 +325,7 @@ const PropertyInputImpl* Geometry::GetSceneObjectInputProperty( Property::Index
         }
         case Dali::Geometry::Property::REQUIRES_DEPTH_TEST :
         {
-          DALI_ASSERT_ALWAYS( 0 && "MESH_REWORK" );
+          property = &mSceneObject->mRequiresDepthTest;
           break;
         }
         default:
index e40a9ed..3063738 100644 (file)
@@ -39,7 +39,7 @@ class GeometryDataProvider
 {
 public:
   typedef Dali::Geometry::GeometryType GeometryType;
-  typedef OwnerContainer< PropertyBuffer* > VertexBuffers;
+  typedef Dali::Vector< const PropertyBuffer* > VertexBuffers;
 
   /**
    * Constructor. Nothing to do as a pure interface.
@@ -48,12 +48,14 @@ public:
 
 public: // GeometryDataProvider
   /**
+   * @todo MESH_REWORK FIX ME Don't get objects through this interface. Send via message instead
    * Get the vertex buffers of the geometry
    * @return A const reference to the vertex buffers
    */
   virtual const VertexBuffers& GetVertexBuffers() const = 0;
 
   /**
+   * @todo MESH_REWORK FIX ME Don't get objects through this interface. Send via message instead
    * Get the index buffer of the geometry
    * @return A const reference to the index buffer
    */
@@ -69,7 +71,7 @@ public: // GeometryDataProvider
    * Returns true if this geometry requires depth testing, e.g. if it is
    * a set of vertices with z != 0
    */
-  virtual bool GetRequiresDepthTest( BufferIndex bufferIndex ) const = 0;
+  virtual bool GetRequiresDepthTesting( BufferIndex bufferIndex ) const = 0;
 
 protected:
 
index ddeb8f8..622413a 100644 (file)
@@ -41,12 +41,15 @@ public:
   }
 
   /**
+   * @todo MESH_REWORK FIX ME Don't get objects through this interface. Send via message instead
+   *
    * Returns the shader
    * @return The shader
    */
   virtual Shader* GetShader() const = 0;
 
   /**
+   * @todo MESH_REWORK FIX ME Don't get objects through this interface. Send via message instead
    * Returns the list of samplers that this material provides
    * @return The list of samplers
    */
index e5610a5..97bcd39 100644 (file)
@@ -56,6 +56,8 @@ public:
 
   /**
    * Get the complete map of uniforms to property value addresses
+   * (The map is double buffered - it can be retrieved through this interface)
+   *
    * @param[in] bufferIndex The bufferIndex
    * @return the uniform map
    */
index c350fe1..8ebf81c 100644 (file)
@@ -103,7 +103,7 @@ void RenderGeometry::DoUpload(
 
   for( unsigned int i=0; i<vertexBuffers.Count(); ++i)
   {
-    PropertyBuffer* vertexBuffer = vertexBuffers[i];
+    const PropertyBuffer* vertexBuffer = vertexBuffers[i];
 
     // @todo MESH_REWORK STATIC_DRAW or DYNAMIC_DRAW depends on property buffer type (static / animated)
     GpuBuffer* vertexGpuBuffer = new GpuBuffer( *context, GpuBuffer::ARRAY_BUFFER, GpuBuffer::STATIC_DRAW );
diff --git a/dali/internal/update/common/double-buffered-property.h b/dali/internal/update/common/double-buffered-property.h
new file mode 100644 (file)
index 0000000..be934b1
--- /dev/null
@@ -0,0 +1,1159 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_DOUBLE_BUFFERED_PROPERTY_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_DOUBLE_BUFFERED_PROPERTY_H__
+
+/*
+ * Copyright (c) 2015 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <limits>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/object/property.h>
+#include <dali/public-api/object/property-input.h>
+#include <dali/public-api/object/property-types.h>
+#include <dali/internal/common/message.h>
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/event/common/property-input-impl.h>
+#include <dali/internal/update/common/double-buffered.h>
+#include <dali/internal/update/common/scene-graph-buffers.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+namespace DoubleBufferedPropertyFlags
+{
+/**
+ * Dirty flags record whether a doubleBuffered property has changed.
+ * In the frame following a change, the property is copied from the most recent
+ * buffer to the old buffer.
+ */
+static const unsigned int CLEAN_FLAG  = 0x00; ///< Indicates that the value did not change in this, or the previous frame
+static const unsigned int COPIED_FLAG = 0x01; ///< Indicates that the value was copied during the previous frame
+static const unsigned int SET_FLAG    = 0x02; ///< Indicates that the value was Set during the previous frame
+}
+
+template <class T>
+class DoubleBufferedProperty;
+
+/**
+ * Base class to reduce code size from the templates.
+ */
+class DoubleBufferedPropertyBase : public PropertyInputImpl
+{
+public:
+
+  /**
+   * Constructor, initialize the dirty flag
+   */
+  DoubleBufferedPropertyBase()
+  : PropertyInputImpl(),
+    mDirtyFlags( DoubleBufferedPropertyFlags::COPIED_FLAG )
+  {}
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~DoubleBufferedPropertyBase()
+  {}
+
+  /**
+   * Auto-age the property: if it was set the previous frame,
+   * then copy the value into the current frame's buffer.
+   */
+  virtual void CopyPrevious( BufferIndex updateBufferIndex ) = 0;
+
+
+protected: // for derived classes
+  /**
+   * Flag that the property has been Set during the current frame.
+   */
+  void OnSet()
+  {
+    mDirtyFlags = DoubleBufferedPropertyFlags::SET_FLAG;
+  }
+
+public: // From PropertyBase
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::InputChanged()
+   */
+  virtual bool InputChanged() const
+  {
+    return ( DoubleBufferedPropertyFlags::CLEAN_FLAG != mDirtyFlags );
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::InputInitialized()
+   */
+  virtual bool InputInitialized() const
+  {
+    return true; // DoubleBuffered properties are always valid
+  }
+
+protected: // so that ResetToBaseValue can set it directly
+
+  unsigned int mDirtyFlags; ///< Flag whether value changed during previous 2 frames
+
+};
+
+
+/**
+ * A boolean doubleBuffered property of a scene-graph object.
+ */
+template <>
+class DoubleBufferedProperty<bool> : public DoubleBufferedPropertyBase
+{
+public:
+
+  /**
+   * Create an doubleBuffered property.
+   * @param [in] initialValue The initial value of the property.
+   */
+  DoubleBufferedProperty( bool initialValue )
+  : mValue( initialValue )
+  {
+  }
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~DoubleBufferedProperty()
+  {
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::GetType()
+   */
+  virtual Dali::Property::Type GetType() const
+  {
+    return Dali::PropertyTypes::Get<bool>();
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::DoubleBufferedPropertyBase::CopyPrevious()
+   */
+  virtual void CopyPrevious( BufferIndex updateBufferIndex )
+  {
+    if( DoubleBufferedPropertyFlags::SET_FLAG == mDirtyFlags)
+    {
+      mValue[ updateBufferIndex ] = mValue[ 1-updateBufferIndex ];
+      mDirtyFlags = ( mDirtyFlags >> 1 );
+    }
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::GetBoolean()
+   */
+  virtual const bool& GetBoolean( BufferIndex bufferIndex ) const
+  {
+    return mValue[ bufferIndex ];
+  }
+
+  /**
+   * Set the property value. This will persist for the current frame, and will
+   * be copied to the other buffer next frame (unless it is set again)
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] value The new property value.
+   */
+  void Set(BufferIndex bufferIndex, bool value)
+  {
+    // check if the value actually changed to avoid dirtying nodes unnecessarily
+    if( mValue[bufferIndex] != value )
+    {
+      mValue[bufferIndex] = value;
+
+      OnSet();
+    }
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::DoubleBufferedProperty::Get()
+   */
+  bool& Get(size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::DoubleBufferedProperty::Get()
+   */
+  const bool& Get(size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  bool& operator[](size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  const bool& operator[](size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+private:
+  // Undefined
+  DoubleBufferedProperty(const DoubleBufferedProperty& property);
+
+  // Undefined
+  DoubleBufferedProperty& operator=(const DoubleBufferedProperty& rhs);
+
+private:
+  DoubleBuffered<bool> mValue; ///< The double-buffered property value
+};
+
+
+
+/**
+ * A float doubleBuffered property of a scene-graph object.
+ */
+template <>
+class DoubleBufferedProperty<float> : public DoubleBufferedPropertyBase
+{
+public:
+
+  /**
+   * Create a doubleBuffered property.
+   * @param[in] initialValue The initial value of the property.
+   */
+  DoubleBufferedProperty( float initialValue )
+  : mValue( initialValue )
+  {
+  }
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~DoubleBufferedProperty()
+  {
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::GetType()
+   */
+  virtual Dali::Property::Type GetType() const
+  {
+    return Dali::PropertyTypes::Get<float>();
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::DoubleBufferedPropertyBase::CopyPrevious()
+   */
+  virtual void CopyPrevious( BufferIndex updateBufferIndex )
+  {
+    if( DoubleBufferedPropertyFlags::SET_FLAG == mDirtyFlags)
+    {
+      mValue[ updateBufferIndex ] = mValue[ 1-updateBufferIndex ];
+      mDirtyFlags = ( mDirtyFlags >> 1 );
+    }
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::GetFloat()
+   */
+  virtual const float& GetFloat( BufferIndex bufferIndex ) const
+  {
+    return mValue[ bufferIndex ];
+  }
+
+  /**
+   * Set the property value. This will persist for the current frame, and will
+   * be copied to the other buffer next frame (unless it is set again)
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] value The new property value.
+   */
+  void Set(BufferIndex bufferIndex, float value)
+  {
+    mValue[bufferIndex] = value;
+    OnSet();
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::DoubleBufferedProperty::Get()
+   */
+  float& Get(size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::DoubleBufferedProperty::Get()
+   */
+  const float& Get(size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  float& operator[](size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  const float& operator[](size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+private:
+  // Undefined
+  DoubleBufferedProperty(const DoubleBufferedProperty& property);
+
+  // Undefined
+  DoubleBufferedProperty& operator=(const DoubleBufferedProperty& rhs);
+
+private:
+  DoubleBuffered<float> mValue; ///< The double-buffered property value
+};
+
+
+/**
+ * A double buffered integer property of a scene-graph object.
+ */
+template <>
+class DoubleBufferedProperty<int> : public DoubleBufferedPropertyBase
+{
+public:
+
+  /**
+   * Create a double buffered property.
+   * @param [in] initialValue The initial value of the property.
+   */
+  DoubleBufferedProperty( int initialValue )
+  : mValue( initialValue )
+  {
+  }
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~DoubleBufferedProperty()
+  {
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::GetType()
+   */
+  virtual Dali::Property::Type GetType() const
+  {
+    return Dali::PropertyTypes::Get<int>();
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::DoubleBufferedPropertyBase::CopyPrevious()
+   */
+  virtual void CopyPrevious( BufferIndex updateBufferIndex )
+  {
+    if( DoubleBufferedPropertyFlags::SET_FLAG == mDirtyFlags)
+    {
+      mValue[ updateBufferIndex ] = mValue[ 1-updateBufferIndex ];
+      mDirtyFlags = ( mDirtyFlags >> 1 );
+    }
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::GetInteger()
+   */
+  virtual const int& GetInteger( BufferIndex bufferIndex ) const
+  {
+    return mValue[ bufferIndex ];
+  }
+
+  /**
+   * Set the property value. This will persist for the current frame, and will
+   * be copied to the other buffer next frame (unless it is set again)
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] value The new property value.
+   */
+  void Set(BufferIndex bufferIndex, int value)
+  {
+    // check if the value actually changed to avoid dirtying nodes unnecessarily
+    if( mValue[bufferIndex] != value )
+    {
+      mValue[bufferIndex] = value;
+
+      OnSet();
+    }
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::DoubleBufferedProperty::Get()
+   */
+  int& Get(size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::DoubleBufferedProperty::Get()
+   */
+  const int& Get(size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  int& operator[](size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  const int& operator[](size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+private:
+  // Undefined
+  DoubleBufferedProperty(const DoubleBufferedProperty& property);
+
+  // Undefined
+  DoubleBufferedProperty& operator=(const DoubleBufferedProperty& rhs);
+
+private:
+  DoubleBuffered<int> mValue; ///< The double-buffered property value
+};
+
+/**
+ * A double buffered Vector2  property of a scene-graph object.
+ */
+template <>
+class DoubleBufferedProperty<Vector2> : public DoubleBufferedPropertyBase
+{
+public:
+
+  /**
+   * Create a double buffered property.
+   * @param [in] initialValue The initial value of the property.
+   */
+  DoubleBufferedProperty( Vector2 initialValue )
+  : mValue( initialValue )
+  {
+  }
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~DoubleBufferedProperty()
+  {
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::GetType()
+   */
+  virtual Dali::Property::Type GetType() const
+  {
+    return Dali::PropertyTypes::Get<Vector2>();
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::DoubleBufferedPropertyBase::CopyPrevious()
+   */
+  virtual void CopyPrevious( BufferIndex updateBufferIndex )
+  {
+    if( DoubleBufferedPropertyFlags::SET_FLAG == mDirtyFlags)
+    {
+      mValue[ updateBufferIndex ] = mValue[ 1-updateBufferIndex ];
+      mDirtyFlags = ( mDirtyFlags >> 1 );
+    }
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::GetVector2()
+   */
+  virtual const Vector2& GetVector2( BufferIndex bufferIndex ) const
+  {
+    return mValue[ bufferIndex ];
+  }
+
+  /**
+   * Set the property value. This will persist for the current frame, and will
+   * be copied to the other buffer next frame (unless it is set again)
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] value The new property value.
+   */
+  void Set(BufferIndex bufferIndex, Vector2 value)
+  {
+    mValue[bufferIndex] = value;
+    OnSet();
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::DoubleBufferedProperty::Get()
+   */
+  Vector2& Get(size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::DoubleBufferedProperty::Get()
+   */
+  const Vector2& Get(size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  Vector2& operator[](size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  const Vector2& operator[](size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+private:
+  // Undefined
+  DoubleBufferedProperty(const DoubleBufferedProperty& property);
+
+  // Undefined
+  DoubleBufferedProperty& operator=(const DoubleBufferedProperty& rhs);
+
+private:
+  DoubleBuffered<Vector2> mValue; ///< The double-buffered property value
+};
+
+/**
+ * A double buffered Vector3  property of a scene-graph object.
+ */
+template <>
+class DoubleBufferedProperty<Vector3> : public DoubleBufferedPropertyBase
+{
+public:
+
+  /**
+   * Create a double buffered property.
+   * @param [in] initialValue The initial value of the property.
+   */
+  DoubleBufferedProperty( Vector3 initialValue )
+  : mValue( initialValue )
+  {
+  }
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~DoubleBufferedProperty()
+  {
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::GetType()
+   */
+  virtual Dali::Property::Type GetType() const
+  {
+    return Dali::PropertyTypes::Get<Vector3>();
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::DoubleBufferedPropertyBase::CopyPrevious()
+   */
+  virtual void CopyPrevious( BufferIndex updateBufferIndex )
+  {
+    if( DoubleBufferedPropertyFlags::SET_FLAG == mDirtyFlags)
+    {
+      mValue[ updateBufferIndex ] = mValue[ 1-updateBufferIndex ];
+      mDirtyFlags = ( mDirtyFlags >> 1 );
+    }
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::GetVector3()
+   */
+  virtual const Vector3& GetVector3( BufferIndex bufferIndex ) const
+  {
+    return mValue[ bufferIndex ];
+  }
+
+  /**
+   * Set the property value. This will persist for the current frame, and will
+   * be copied to the other buffer next frame (unless it is set again)
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] value The new property value.
+   */
+  void Set(BufferIndex bufferIndex, Vector3 value)
+  {
+    mValue[bufferIndex] = value;
+    OnSet();
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::DoubleBufferedProperty::Get()
+   */
+  Vector3& Get(size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::DoubleBufferedProperty::Get()
+   */
+  const Vector3& Get(size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  Vector3& operator[](size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  const Vector3& operator[](size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+private:
+  // Undefined
+  DoubleBufferedProperty(const DoubleBufferedProperty& property);
+
+  // Undefined
+  DoubleBufferedProperty& operator=(const DoubleBufferedProperty& rhs);
+
+private:
+  DoubleBuffered<Vector3> mValue; ///< The double-buffered property value
+};
+
+/**
+ * A double buffered Vector4  property of a scene-graph object.
+ */
+template <>
+class DoubleBufferedProperty<Vector4> : public DoubleBufferedPropertyBase
+{
+public:
+
+  /**
+   * Create a double buffered property.
+   * @param [in] initialValue The initial value of the property.
+   */
+  DoubleBufferedProperty( Vector4 initialValue )
+  : mValue( initialValue )
+  {
+  }
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~DoubleBufferedProperty()
+  {
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::GetType()
+   */
+  virtual Dali::Property::Type GetType() const
+  {
+    return Dali::PropertyTypes::Get<Vector4>();
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::DoubleBufferedPropertyBase::CopyPrevious()
+   */
+  virtual void CopyPrevious( BufferIndex updateBufferIndex )
+  {
+    if( DoubleBufferedPropertyFlags::SET_FLAG == mDirtyFlags)
+    {
+      mValue[ updateBufferIndex ] = mValue[ 1-updateBufferIndex ];
+      mDirtyFlags = ( mDirtyFlags >> 1 );
+    }
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::GetVector4()
+   */
+  virtual const Vector4& GetVector4( BufferIndex bufferIndex ) const
+  {
+    return mValue[ bufferIndex ];
+  }
+
+  /**
+   * Set the property value. This will persist for the current frame, and will
+   * be copied to the other buffer next frame (unless it is set again)
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] value The new property value.
+   */
+  void Set(BufferIndex bufferIndex, Vector4 value)
+  {
+    mValue[bufferIndex] = value;
+    OnSet();
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::DoubleBufferedProperty::Get()
+   */
+  Vector4& Get(size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::DoubleBufferedProperty::Get()
+   */
+  const Vector4& Get(size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  Vector4& operator[](size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  const Vector4& operator[](size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+private:
+  // Undefined
+  DoubleBufferedProperty(const DoubleBufferedProperty& property);
+
+  // Undefined
+  DoubleBufferedProperty& operator=(const DoubleBufferedProperty& rhs);
+
+private:
+  DoubleBuffered<Vector4> mValue; ///< The double-buffered property value
+};
+
+
+/**
+ * A double buffered Quaternion  property of a scene-graph object.
+ */
+template <>
+class DoubleBufferedProperty<Quaternion> : public DoubleBufferedPropertyBase
+{
+public:
+
+  /**
+   * Create a double buffered property.
+   * @param [in] initialValue The initial value of the property.
+   */
+  DoubleBufferedProperty( Quaternion initialValue )
+  : mValue( initialValue )
+  {
+  }
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~DoubleBufferedProperty()
+  {
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::GetType()
+   */
+  virtual Dali::Property::Type GetType() const
+  {
+    return Dali::PropertyTypes::Get<Quaternion>();
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::DoubleBufferedPropertyBase::CopyPrevious()
+   */
+  virtual void CopyPrevious( BufferIndex updateBufferIndex )
+  {
+    if( DoubleBufferedPropertyFlags::SET_FLAG == mDirtyFlags)
+    {
+      mValue[ updateBufferIndex ] = mValue[ 1-updateBufferIndex ];
+      mDirtyFlags = ( mDirtyFlags >> 1 );
+    }
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::GetQuaternion()
+   */
+  virtual const Quaternion& GetQuaternion( BufferIndex bufferIndex ) const
+  {
+    return mValue[ bufferIndex ];
+  }
+
+  /**
+   * Set the property value. This will persist for the current frame, and will
+   * be copied to the other buffer next frame (unless it is set again)
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] value The new property value.
+   */
+  void Set(BufferIndex bufferIndex, Quaternion value)
+  {
+    mValue[bufferIndex] = value;
+    OnSet();
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::DoubleBufferedProperty::Get()
+   */
+  Quaternion& Get(size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::DoubleBufferedProperty::Get()
+   */
+  const Quaternion& Get(size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  Quaternion& operator[](size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  const Quaternion& operator[](size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+private:
+  // Undefined
+  DoubleBufferedProperty(const DoubleBufferedProperty& property);
+
+  // Undefined
+  DoubleBufferedProperty& operator=(const DoubleBufferedProperty& rhs);
+
+private:
+  DoubleBuffered<Quaternion> mValue; ///< The double-buffered property value
+};
+
+/**
+ * A double buffered Matrix  property of a scene-graph object.
+ */
+template <>
+class DoubleBufferedProperty<Matrix> : public DoubleBufferedPropertyBase
+{
+public:
+
+  /**
+   * Create a double buffered property.
+   * @param [in] initialValue The initial value of the property.
+   */
+  DoubleBufferedProperty( Matrix initialValue )
+  : mValue( initialValue )
+  {
+  }
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~DoubleBufferedProperty()
+  {
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::GetType()
+   */
+  virtual Dali::Property::Type GetType() const
+  {
+    return Dali::PropertyTypes::Get<Matrix>();
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::DoubleBufferedPropertyBase::CopyPrevious()
+   */
+  virtual void CopyPrevious( BufferIndex updateBufferIndex )
+  {
+    if( DoubleBufferedPropertyFlags::SET_FLAG == mDirtyFlags)
+    {
+      mValue[ updateBufferIndex ] = mValue[ 1-updateBufferIndex ];
+      mDirtyFlags = ( mDirtyFlags >> 1 );
+    }
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::GetMatrix()
+   */
+  virtual const Matrix& GetMatrix( BufferIndex bufferIndex ) const
+  {
+    return mValue[ bufferIndex ];
+  }
+
+  /**
+   * Set the property value. This will persist for the current frame, and will
+   * be copied to the other buffer next frame (unless it is set again)
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] value The new property value.
+   */
+  void Set(BufferIndex bufferIndex, Matrix value)
+  {
+    mValue[bufferIndex] = value;
+    OnSet();
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::DoubleBufferedProperty::Get()
+   */
+  Matrix& Get(size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::DoubleBufferedProperty::Get()
+   */
+  const Matrix& Get(size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  Matrix& operator[](size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  const Matrix& operator[](size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+private:
+  // Undefined
+  DoubleBufferedProperty(const DoubleBufferedProperty& property);
+
+  // Undefined
+  DoubleBufferedProperty& operator=(const DoubleBufferedProperty& rhs);
+
+private:
+  DoubleBuffered<Matrix> mValue; ///< The double-buffered property value
+};
+
+
+/**
+ * A double buffered Matrix3  property of a scene-graph object.
+ */
+template <>
+class DoubleBufferedProperty<Matrix3> : public DoubleBufferedPropertyBase
+{
+public:
+
+  /**
+   * Create a double buffered property.
+   * @param [in] initialValue The initial value of the property.
+   */
+  DoubleBufferedProperty( Matrix3 initialValue )
+  : mValue( initialValue )
+  {
+  }
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~DoubleBufferedProperty()
+  {
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::GetType()
+   */
+  virtual Dali::Property::Type GetType() const
+  {
+    return Dali::PropertyTypes::Get<Matrix3>();
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::DoubleBufferedPropertyBase::CopyPrevious()
+   */
+  virtual void CopyPrevious( BufferIndex updateBufferIndex )
+  {
+    if( DoubleBufferedPropertyFlags::SET_FLAG == mDirtyFlags)
+    {
+      mValue[ updateBufferIndex ] = mValue[ 1-updateBufferIndex ];
+      mDirtyFlags = ( mDirtyFlags >> 1 );
+    }
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::GetMatrix3()
+   */
+  virtual const Matrix3& GetMatrix3( BufferIndex bufferIndex ) const
+  {
+    return mValue[ bufferIndex ];
+  }
+
+  /**
+   * Set the property value. This will persist for the current frame, and will
+   * be copied to the other buffer next frame (unless it is set again)
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] value The new property value.
+   */
+  void Set(BufferIndex bufferIndex, Matrix3 value)
+  {
+    mValue[bufferIndex] = value;
+    OnSet();
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::DoubleBufferedProperty::Get()
+   */
+  Matrix3& Get(size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::DoubleBufferedProperty::Get()
+   */
+  const Matrix3& Get(size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  Matrix3& operator[](size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  const Matrix3& operator[](size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+private:
+  // Undefined
+  DoubleBufferedProperty(const DoubleBufferedProperty& property);
+
+  // Undefined
+  DoubleBufferedProperty& operator=(const DoubleBufferedProperty& rhs);
+
+private:
+  DoubleBuffered<Matrix3> mValue; ///< The double-buffered property value
+};
+
+} // namespace SceneGraph
+
+// Messages for DoubleBufferedProperty<T>
+
+template <class T>
+void SetMessage( EventThreadServices& eventThreadServices,
+                  const SceneGraph::DoubleBufferedProperty<T>& property,
+                  typename ParameterType< T >::PassingType newValue )
+{
+  typedef MessageDoubleBuffered1< SceneGraph::DoubleBufferedProperty<T>, T > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &property,
+                        &SceneGraph::DoubleBufferedProperty<T>::Set,
+                        newValue );
+}
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_DOUBLE_BUFFERED_PROPERTY_H__
index 6a9fa9a..ca50648 100644 (file)
@@ -365,7 +365,6 @@ private:
 
   bool mInheritedFlag   :1; ///< Flag whether the value has ever been inherited
   bool mReinheritedFlag :1; ///< Flag whether value was re-inherited in previous frame
-
 };
 
 /**
index addb142..9cc7014 100644 (file)
@@ -29,11 +29,11 @@ namespace SceneGraph
 
 // Messages for a property owner
 
-PropertyMessageBase::PropertyMessageBase()
+PropertyOwnerMessageBase::PropertyOwnerMessageBase()
 {
 }
 
-PropertyMessageBase::~PropertyMessageBase()
+PropertyOwnerMessageBase::~PropertyOwnerMessageBase()
 {
 }
 
index fe2045f..238f223 100644 (file)
@@ -23,6 +23,7 @@
 #include <dali/internal/event/common/event-thread-services.h>
 #include <dali/internal/event/common/property-input-impl.h>
 #include <dali/internal/update/common/property-owner.h>
+#include <dali/internal/update/common/double-buffered-property.h>
 #include <dali/internal/update/animation/scene-graph-constraint-base.h>
 #include <string>
 
@@ -37,32 +38,36 @@ class PropertyOwner;
 
 // Property Messages for PropertyOwner
 
-class PropertyMessageBase : public MessageBase
+/**
+ * A base class for property owner property messages.
+ * (For future optimization - see NodeMessageBase & Node.SetActive())
+ */
+class PropertyOwnerMessageBase : public MessageBase
 {
 public:
 
   /**
    * Create a message.
    */
-  PropertyMessageBase();
+  PropertyOwnerMessageBase();
 
   /**
    * Virtual destructor
    */
-  virtual ~PropertyMessageBase();
+  virtual ~PropertyOwnerMessageBase();
 
 private:
 
   // Undefined
-  PropertyMessageBase(const PropertyMessageBase&);
-  PropertyMessageBase& operator=(const PropertyMessageBase& rhs);
+  PropertyOwnerMessageBase(const PropertyOwnerMessageBase&);
+  PropertyOwnerMessageBase& operator=(const PropertyOwnerMessageBase& rhs);
 };
 
 /**
  * Templated message which bakes a property.
  */
 template< typename P >
-class PropertyMessage : public PropertyMessageBase
+class AnimatablePropertyMessage : public PropertyOwnerMessageBase
 {
 public:
 
@@ -72,7 +77,7 @@ public:
    * Create a message.
    * @note The scene object is expected to be const in the thread which sends this message.
    * However it can be modified when Process() is called in a different thread.
-   * @param[in] updateManager The update-manager.
+   * @param[in] eventThreadServices The object used to send messages to the scene graph
    * @param[in] sceneObject The property owner scene object
    * @param[in] property The property to bake.
    * @param[in] member The member function of the object.
@@ -85,16 +90,16 @@ public:
                     typename ParameterType< P >::PassingType value )
   {
     // Reserve some memory inside the message queue
-    unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( PropertyMessage ) );
+    unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( AnimatablePropertyMessage ) );
 
     // Construct message in the message queue memory; note that delete should not be called on the return value
-    new (slot) PropertyMessage( sceneObject, property, member, value );
+    new (slot) AnimatablePropertyMessage( sceneObject, property, member, value );
   }
 
   /**
    * Virtual destructor
    */
-  virtual ~PropertyMessage()
+  virtual ~AnimatablePropertyMessage()
   {
   }
 
@@ -117,11 +122,11 @@ private:
    * @param[in] member The member function of the object.
    * @param[in] value The new value of the property.
    */
-  PropertyMessage( const PropertyOwner* sceneObject,
-                   const AnimatableProperty<P>* property,
-                   MemberFunction member,
-                   typename ParameterType< P >::PassingType value )
-  : PropertyMessageBase(),
+  AnimatablePropertyMessage( const PropertyOwner* sceneObject,
+                             const AnimatableProperty<P>* property,
+                             MemberFunction member,
+                             typename ParameterType< P >::PassingType value )
+  : PropertyOwnerMessageBase(),
     mSceneObject( const_cast< PropertyOwner* >( sceneObject ) ),
     mProperty( const_cast< AnimatableProperty<P>* >( property ) ),
     mMemberFunction( member ),
@@ -141,7 +146,7 @@ private:
  * Templated message which bakes a property.
  */
 template< typename P >
-class PropertyComponentMessage : public PropertyMessageBase
+class AnimatablePropertyComponentMessage : public PropertyOwnerMessageBase
 {
 public:
 
@@ -164,16 +169,16 @@ public:
                     float value )
   {
     // Reserve some memory inside the message queue
-    unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( PropertyComponentMessage ) );
+    unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( AnimatablePropertyComponentMessage ) );
 
     // Construct message in the message queue memory; note that delete should not be called on the return value
-    new (slot) PropertyComponentMessage( sceneObject, property, member, value );
+    new (slot) AnimatablePropertyComponentMessage( sceneObject, property, member, value );
   }
 
   /**
    * Virtual destructor
    */
-  virtual ~PropertyComponentMessage()
+  virtual ~AnimatablePropertyComponentMessage()
   {
   }
 
@@ -196,11 +201,11 @@ private:
    * @param[in] member The member function of the object.
    * @param[in] value The new value of the X,Y,Z or W component.
   */
-  PropertyComponentMessage( const PropertyOwner* sceneObject,
-                            const AnimatableProperty<P>* property,
-                            MemberFunction member,
-                            float value )
-  : PropertyMessageBase(),
+  AnimatablePropertyComponentMessage( const PropertyOwner* sceneObject,
+                                      const AnimatableProperty<P>* property,
+                                      MemberFunction member,
+                                      float value )
+  : PropertyOwnerMessageBase(),
     mSceneObject( const_cast< PropertyOwner* >( sceneObject ) ),
     mProperty( const_cast< AnimatableProperty<P>* >( property ) ),
     mMemberFunction( member ),
@@ -216,6 +221,85 @@ private:
 };
 
 
+/**
+ * Template class for sending messages to double buffered properties in a PropertyOwner
+ */
+template< typename P >
+class DoubleBufferedPropertyMessage : public PropertyOwnerMessageBase
+{
+public:
+
+  typedef void(DoubleBufferedProperty<P>::*MemberFunction)( BufferIndex, typename ParameterType< P >::PassingType );
+
+  /**
+   * Create a message.
+   * @note The scene object is expected to be const in the thread which sends this message.
+   * However it can be modified when Process() is called in a different thread.
+   * @param[in] eventThreadServices The object used to send messages to the scene graph
+   * @param[in] sceneObject The property owner scene object
+   * @param[in] property The property to set.
+   * @param[in] member The member function of the object.
+   * @param[in] value The new value of the property.
+   */
+  static void Send( EventThreadServices& eventThreadServices,
+                    const PropertyOwner* sceneObject,
+                    const DoubleBufferedProperty<P>* property,
+                    MemberFunction member,
+                    typename ParameterType< P >::PassingType value )
+  {
+    // Reserve some memory inside the message queue
+    unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( DoubleBufferedPropertyMessage ) );
+
+    // Construct message in the message queue memory; note that delete should not be called on the return value
+    new (slot) DoubleBufferedPropertyMessage( sceneObject, property, member, value );
+  }
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~DoubleBufferedPropertyMessage()
+  {
+  }
+
+  /**
+   * @copydoc MessageBase::Process
+   */
+  virtual void Process( BufferIndex updateBufferIndex )
+  {
+    (mProperty->*mMemberFunction)( updateBufferIndex, mParam );
+  }
+
+private:
+
+  /**
+   * Create a message.
+   * @note The property owner is expected to be const in the thread which sends this message.
+   * However it can be modified when Process() is called in a different thread.
+   * @param[in] sceneObject the property owner scene object
+   * @param[in] property The property to set.
+   * @param[in] member The member function of the object.
+   * @param[in] value The new value of the property.
+   */
+  DoubleBufferedPropertyMessage( const PropertyOwner* sceneObject,
+                                 const DoubleBufferedProperty<P>* property,
+                                 MemberFunction member,
+                                 typename ParameterType< P >::PassingType value )
+  : PropertyOwnerMessageBase(),
+    mSceneObject( const_cast< PropertyOwner* >( sceneObject ) ),
+    mProperty( const_cast< DoubleBufferedProperty<P>* >( property ) ),
+    mMemberFunction( member ),
+    mParam( value )
+  {
+  }
+
+private:
+  PropertyOwner* mSceneObject;
+  DoubleBufferedProperty<P>* mProperty;
+  MemberFunction mMemberFunction;
+  typename ParameterType< P >::HolderType mParam;
+};
+
+
 // Messages for PropertyOwner
 
 inline void InstallCustomPropertyMessage( EventThreadServices& eventThreadServices, const PropertyOwner& owner, PropertyBase* property )
index a6773ce..dde1556 100644 (file)
@@ -18,6 +18,7 @@
 #include "scene-graph-material.h"
 
 // INTERNAL HEADERS
+#include <dali/public-api/shader-effects/material.h>
 #include <dali/internal/render/data-providers/sampler-data-provider.h>
 #include <dali/internal/update/effects/scene-graph-sampler.h>
 
@@ -31,6 +32,7 @@ namespace SceneGraph
 Material::Material()
 : mColor( Color::WHITE ),
   mBlendColor( Color::WHITE ),
+  mFaceCullingMode(Dali::Material::NONE),
   mShader(NULL)
 {
   // Observe own property-owner's uniform map
@@ -118,6 +120,13 @@ void Material::UniformMappingsChanged( const UniformMap& mappings )
   mConnectionObservers.ConnectedUniformMapChanged();
 }
 
+void Material::ResetDefaultProperties( BufferIndex updateBufferIndex )
+{
+  mColor.ResetToBaseValue( updateBufferIndex );
+  mBlendColor.ResetToBaseValue( updateBufferIndex );
+  mFaceCullingMode.CopyPrevious( updateBufferIndex );
+}
+
 } // namespace SceneGraph
 } // namespace Internal
 } // namespace Dali
index 54e3b10..7458e50 100644 (file)
@@ -22,7 +22,7 @@
 #include <dali/internal/common/blending-options.h>
 #include <dali/internal/event/common/event-thread-services.h>
 #include <dali/internal/update/common/animatable-property.h>
-#include <dali/internal/update/common/double-buffered.h>
+#include <dali/internal/update/common/double-buffered-property.h>
 #include <dali/internal/update/common/property-owner.h>
 #include <dali/internal/update/common/scene-graph-connection-observers.h>
 #include <dali/internal/update/common/uniform-map.h>
@@ -108,16 +108,22 @@ public: // MaterialDataProvider implementation
    */
   virtual const Samplers& GetSamplers() const;
 
-
 public: // UniformMap::Observer
   /**
    * @copydoc UniformMap::Observer::UniformMappingsChanged
    */
   virtual void UniformMappingsChanged( const UniformMap& mappings );
 
+public: // PropertyOwner implementation
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyOwner::ResetDefaultProperties()
+   */
+  virtual void ResetDefaultProperties( BufferIndex updateBufferIndex );
+
 public: // Property data
   AnimatableProperty<Vector4> mColor;
   AnimatableProperty<Vector4> mBlendColor;
+  DoubleBufferedProperty<int> mFaceCullingMode;
 
 private:
   const Shader* mShader;
index 05c4542..02410d0 100644 (file)
@@ -32,7 +32,8 @@ Sampler::Sampler( const std::string& unitName )
   mMinFilter( Dali::Sampler::DEFAULT ),
   mMagFilter( Dali::Sampler::DEFAULT ),
   mUWrapMode( Dali::Sampler::CLAMP_TO_EDGE ),
-  mVWrapMode( Dali::Sampler::CLAMP_TO_EDGE )
+  mVWrapMode( Dali::Sampler::CLAMP_TO_EDGE ),
+  mAffectsTransparency( false )
 {
   mTextureId[0] = 0;
   mTextureId[1] = 0;
@@ -78,22 +79,22 @@ Integration::ResourceId Sampler::GetTextureId( BufferIndex bufferIndex ) const
 
 Sampler::FilterMode Sampler::GetMinifyFilterMode( BufferIndex bufferIndex ) const
 {
-  return mMinFilter[bufferIndex];
+  return static_cast<Sampler::FilterMode>(mMinFilter[bufferIndex]);
 }
 
 Sampler::FilterMode Sampler::GetMagnifyFilterMode( BufferIndex bufferIndex ) const
 {
-  return mMagFilter[bufferIndex];
+  return static_cast<Sampler::FilterMode>(mMagFilter[bufferIndex]);
 }
 
 Sampler::WrapMode Sampler::GetUWrapMode( BufferIndex bufferIndex ) const
 {
-  return mUWrapMode[bufferIndex];
+  return static_cast<Sampler::WrapMode>(mUWrapMode[bufferIndex]);
 }
 
 Sampler::WrapMode Sampler::GetVWrapMode( BufferIndex bufferIndex ) const
 {
-  return mVWrapMode[bufferIndex];
+  return static_cast<Sampler::WrapMode>(mVWrapMode[bufferIndex]);
 }
 
 bool Sampler::AffectsTransparency( BufferIndex bufferIndex ) const
index 5b5a173..d50ccc5 100644 (file)
@@ -21,6 +21,7 @@
 #include <dali/integration-api/resource-declarations.h>
 #include <dali/internal/event/common/event-thread-services.h>
 #include <dali/internal/update/common/double-buffered.h>
+#include <dali/internal/update/common/double-buffered-property.h>
 #include <dali/internal/update/common/property-owner.h>
 #include <dali/internal/update/resources/bitmap-metadata.h>
 #include <dali/internal/render/data-providers/sampler-data-provider.h>
@@ -160,15 +161,13 @@ private:
 
   BitmapMetadata mBitmapMetadata[2]; /// The meta data of the associated texture for this frame (Not needed in RenderThread)
 
-  // @todo MESH_REWORK These need to be non-animatable properties (that also copy
-  // new values into old on frame change ) that can be read in RenderThread
-  DoubleBuffered<FilterMode> mMinFilter;    ///< The minify filter
-  DoubleBuffered<FilterMode> mMagFilter;    ///< The magnify filter
-  DoubleBuffered<WrapMode> mUWrapMode;      ///< The horizontal wrap mode
-  DoubleBuffered<WrapMode> mVWrapMode;      ///< The vertical wrap mode
+  DoubleBufferedProperty<int> mMinFilter;    ///< The minify filter
+  DoubleBufferedProperty<int> mMagFilter;    ///< The magnify filter
+  DoubleBufferedProperty<int> mUWrapMode;    ///< The horizontal wrap mode
+  DoubleBufferedProperty<int> mVWrapMode;    ///< The vertical wrap mode
 
   // Note, this is only called from UpdateThread
-  DoubleBuffered<bool>     mAffectsTransparency; ///< If this sampler affects renderer transparency
+  DoubleBufferedProperty<bool>     mAffectsTransparency; ///< If this sampler affects renderer transparency
 };
 
 } // namespace SceneGraph
index 3a94ca2..7bb9d2a 100644 (file)
@@ -47,24 +47,26 @@ Geometry::~Geometry()
   // could remove self from own uniform map observer, but it's about to be destroyed.
 }
 
-void Geometry::AddVertexBuffer( PropertyBuffer* vertexBuffer )
+void Geometry::AddVertexBuffer( const PropertyBuffer* vertexBuffer )
 {
   mVertexBuffers.PushBack( vertexBuffer );
-  vertexBuffer->AddUniformMapObserver(*this);
+  PropertyBuffer* theVertexBuffer = const_cast<PropertyBuffer*>(vertexBuffer);
+  theVertexBuffer->AddUniformMapObserver(*this);
   mConnectionObservers.ConnectionsChanged(*this);
 }
 
-void Geometry::RemoveVertexBuffer( PropertyBuffer* vertexBuffer )
+void Geometry::RemoveVertexBuffer( const PropertyBuffer* vertexBuffer )
 {
   DALI_ASSERT_DEBUG( NULL != vertexBuffer );
 
   // Find the object and destroy it
-  for ( OwnerContainer< PropertyBuffer* >::Iterator iter = mVertexBuffers.Begin(); iter != mVertexBuffers.End(); ++iter )
+  for ( VertexBuffers::Iterator iter = mVertexBuffers.Begin(); iter != mVertexBuffers.End(); ++iter )
   {
-    PropertyBuffer* current = *iter;
+    const PropertyBuffer* current = *iter;
     if ( current == vertexBuffer )
     {
-      vertexBuffer->RemoveUniformMapObserver(*this);
+      PropertyBuffer* theVertexBuffer = const_cast<PropertyBuffer*>(vertexBuffer);
+      theVertexBuffer->RemoveUniformMapObserver(*this);
       mVertexBuffers.Erase( iter );
       mConnectionObservers.ConnectionsChanged(*this);
       return;
@@ -74,9 +76,9 @@ void Geometry::RemoveVertexBuffer( PropertyBuffer* vertexBuffer )
   DALI_ASSERT_DEBUG(false);
 }
 
-void Geometry::SetIndexBuffer( PropertyBuffer* indexBuffer )
+void Geometry::SetIndexBuffer( const PropertyBuffer* indexBuffer )
 {
-  if( mIndexBuffer.Get() != indexBuffer )
+  if( mIndexBuffer != indexBuffer )
   {
     mIndexBuffer = indexBuffer;
     mConnectionObservers.ConnectionsChanged(*this);
@@ -86,7 +88,7 @@ void Geometry::SetIndexBuffer( PropertyBuffer* indexBuffer )
 void Geometry::ClearIndexBuffer()
 {
   // @todo Actually delete, or put on Discard Queue and tell Renderer in render thread?
-  mIndexBuffer.Reset();
+  mIndexBuffer = 0;
   mConnectionObservers.ConnectionsChanged(*this);
 }
 
@@ -102,7 +104,7 @@ const GeometryDataProvider::VertexBuffers& Geometry::GetVertexBuffers() const
 
 const PropertyBuffer* Geometry::GetIndexBuffer() const
 {
-  return mIndexBuffer.Get();
+  return mIndexBuffer;
 }
 
 Geometry::GeometryType Geometry::GetGeometryType( BufferIndex bufferIndex) const
@@ -111,11 +113,22 @@ Geometry::GeometryType Geometry::GetGeometryType( BufferIndex bufferIndex) const
   return static_cast< GeometryDataProvider::GeometryType > ( geometryType );
 }
 
-bool Geometry::GetRequiresDepthTest( BufferIndex bufferIndex ) const
+bool Geometry::GetRequiresDepthTesting( BufferIndex bufferIndex ) const
 {
   return mRequiresDepthTest.GetBoolean( bufferIndex );
 }
 
+void Geometry::ResetDefaultProperties( BufferIndex updateBufferIndex )
+{
+  // Reset the animated properties
+  mCenter.ResetToBaseValue( updateBufferIndex );
+  mHalfExtents.ResetToBaseValue( updateBufferIndex );
+
+  // Age the double buffered properties
+  mGeometryType.CopyPrevious(updateBufferIndex);
+  mRequiresDepthTest.CopyPrevious(updateBufferIndex);
+}
+
 void Geometry::ConnectToSceneGraph( SceneController& sceneController, BufferIndex bufferIndex )
 {
 }
index f0476de..194a853 100644 (file)
@@ -21,6 +21,7 @@
 #include <dali/internal/event/common/event-thread-services.h>
 #include <dali/internal/update/common/animatable-property.h>
 #include <dali/internal/update/common/double-buffered.h>
+#include <dali/internal/update/common/double-buffered-property.h>
 #include <dali/internal/update/common/property-owner.h>
 #include <dali/internal/update/common/property-boolean.h>
 #include <dali/internal/update/common/uniform-map.h>
@@ -57,19 +58,19 @@ public:
   /**
    * Add a property buffer to be used as a vertex buffer
    */
-  void AddVertexBuffer( PropertyBuffer* vertexBuffer );
+  void AddVertexBuffer( const PropertyBuffer* vertexBuffer );
 
   /**
    * Remove a property buffer to be used as a vertex buffer
    * @param[in] vertexBuffer the associated vertex buffer to remove
    */
-  void RemoveVertexBuffer( PropertyBuffer* vertexBuffer );
+  void RemoveVertexBuffer( const PropertyBuffer* vertexBuffer );
 
   /**
    * Set the buffer to be used as a source of indices for the geometry
    * @param[in] indexBuffer the Property buffer describing the indexes for Line, Triangle tyes.
    */
-  void SetIndexBuffer( PropertyBuffer* indexBuffer );
+  void SetIndexBuffer( const PropertyBuffer* indexBuffer );
 
   /**
    * Clear the index buffer if it is no longer required, e.g. if changing geometry type
@@ -136,24 +137,29 @@ public: // GeometryDataProvider
    * Returns true if this geometry requires depth testing, e.g. if it is
    * a set of vertices with z != 0
    */
-  virtual bool GetRequiresDepthTest( BufferIndex bufferIndex ) const;
+  virtual bool GetRequiresDepthTesting( BufferIndex bufferIndex ) const;
+
+protected: // From PropertyOwner
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyOwner::ResetDefaultProperties()
+   */
+  virtual void ResetDefaultProperties( BufferIndex updateBufferIndex );
 
 private:
   VertexBuffers mVertexBuffers; ///< The vertex buffers
-  OwnerPointer<PropertyBuffer> mIndexBuffer;  ///< The index buffer if required
+  const PropertyBuffer* mIndexBuffer;  ///< The index buffer if required
   ConnectionObservers mConnectionObservers;
 
 public: // Properties
   AnimatableProperty<Vector3>  mCenter;
   AnimatableProperty<Vector3>  mHalfExtents;
-
-  AnimatableProperty<int>      mGeometryType;   ///< The type of geometry (tris/lines etc)
-  PropertyBoolean              mRequiresDepthTest;
+  DoubleBufferedProperty<int>  mGeometryType;
+  DoubleBufferedProperty<bool> mRequiresDepthTest;
 };
 
-inline void AddVertexBufferMessage( EventThreadServices& eventThreadServices , const Geometry& geometry, PropertyBuffer& vertexBuffer )
+inline void AddVertexBufferMessage( EventThreadServices& eventThreadServices , const Geometry& geometry, const PropertyBuffer& vertexBuffer )
 {
-  typedef MessageValue1< Geometry, OwnerPointer<PropertyBuffer> > LocalType;
+  typedef MessageValue1< Geometry, const PropertyBuffer* > LocalType;
 
   // Reserve some memory inside the message queue
   unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
@@ -162,9 +168,9 @@ inline void AddVertexBufferMessage( EventThreadServices& eventThreadServices , c
   new (slot) LocalType( &geometry, &Geometry::AddVertexBuffer, &vertexBuffer );
 }
 
-inline void RemoveVertexBufferMessage( EventThreadServices& eventThreadServices, const Geometry& geometry, PropertyBuffer& vertexBuffer )
+inline void RemoveVertexBufferMessage( EventThreadServices& eventThreadServices, const Geometry& geometry, const PropertyBuffer& vertexBuffer )
 {
-  typedef MessageValue1< Geometry, PropertyBuffer* > LocalType;
+  typedef MessageValue1< Geometry, const PropertyBuffer* > LocalType;
 
   // Reserve some memory inside the message queue
   unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
@@ -173,9 +179,9 @@ inline void RemoveVertexBufferMessage( EventThreadServices& eventThreadServices,
   new (slot) LocalType( &geometry, &Geometry::RemoveVertexBuffer, &vertexBuffer );
 }
 
-inline void SetIndexBufferMessage( EventThreadServices& eventThreadServices, const Geometry& geometry, PropertyBuffer& indexBuffer )
+inline void SetIndexBufferMessage( EventThreadServices& eventThreadServices, const Geometry& geometry, const PropertyBuffer& indexBuffer )
 {
-  typedef MessageValue1< Geometry, OwnerPointer< PropertyBuffer > > LocalType;
+  typedef MessageValue1< Geometry, const PropertyBuffer* > LocalType;
 
   // Reserve some memory inside the message queue
   unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
index a78cb3e..ff41cf0 100644 (file)
@@ -66,8 +66,12 @@ RendererAttachment::RendererAttachment()
   mMaterial(NULL),
   mGeometry(NULL),
   mRegenerateUniformMap(REGENERATE_UNIFORM_MAP),
+  mResendChildPointers(false),
   mDepthIndex(0)
 {
+  mUniformMapChanged[0]=false;
+  mUniformMapChanged[1]=false;
+
   // Observe our own PropertyOwner's uniform map
   AddUniformMapObserver( *this );
 }
@@ -239,6 +243,13 @@ void RendererAttachment::DoPrepareRender( BufferIndex updateBufferIndex )
 
     mRegenerateUniformMap--;
   }
+
+  if( mResendChildPointers )
+  {
+    //@todo MESH_REWORK If the children have changed, then supply the NewRenderer with the
+    // new children. (Rather than accessing through the DataProvider interface)
+    mResendChildPointers = false;
+  }
 }
 
 bool RendererAttachment::IsFullyOpaque( BufferIndex updateBufferIndex )
@@ -355,6 +366,9 @@ void RendererAttachment::ConnectionsChanged( PropertyOwner& object )
   // One of our child objects has changed it's connections. Ensure the uniform
   // map gets regenerated during PrepareRender
   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
+
+  // Ensure the child object pointers get re-sent to the renderer
+  mResendChildPointers = true;
 }
 
 void RendererAttachment::ConnectedUniformMapChanged()
index 6bb2d55..b17db95 100644 (file)
@@ -204,8 +204,10 @@ private:
   Geometry* mGeometry; ///< The geometry this renderer uses. (Not owned)
 
   CollectedUniformMap mCollectedUniformMap[2];
-  bool mUniformMapChanged[2]; ///< Records if the uniform map has been altered this frame
   int mRegenerateUniformMap;  ///< 2 if the map should be regenerated, 1 if it should be copied.
+  bool mUniformMapChanged[2]; ///< Records if the uniform map has been altered this frame
+  bool mResendChildPointers;
+
 public: // Properties
 
   AnimatableProperty<int> mDepthIndex; ///< Used only in PrepareRenderInstructions