Remove UNSIGNED_INTEGER property type as it does not fully work and causes headache
[platform/core/uifw/dali-core.git] / dali / internal / event / common / property-buffer-impl.cpp
index 6d0b5db..7fa13f7 100644 (file)
@@ -22,7 +22,9 @@
 #include <algorithm> // std::sort
 
 // INTERNAL INCLUDES
-#include <dali/public-api/object/property-buffer.h> // Dali::Internal::PropertyBuffer
+#include <dali/public-api/object/type-registry.h>
+#include <dali/devel-api/object/property-buffer.h> // Dali::Internal::PropertyBuffer
+
 #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/scene-graph-property-buffer.h>
@@ -43,12 +45,107 @@ namespace
  *            |name    |type             |writable|animatable|constraint-input|enum for index-checking|
  */
 DALI_PROPERTY_TABLE_BEGIN
-DALI_PROPERTY( "size",          UNSIGNED_INTEGER, true, false,  true,   Dali::PropertyBuffer::Property::SIZE )
-DALI_PROPERTY( "buffer-format", MAP,              false, false, false,  Dali::PropertyBuffer::Property::BUFFER_FORMAT )
+DALI_PROPERTY( "size",          INTEGER, true,  false, true,   Dali::PropertyBuffer::Property::SIZE )
+DALI_PROPERTY( "buffer-format", MAP,     false, false, false,  Dali::PropertyBuffer::Property::BUFFER_FORMAT )
 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
 
 const ObjectImplHelper<DEFAULT_PROPERTY_COUNT> PROPERTY_BUFFER_IMPL = { DEFAULT_PROPERTY_DETAILS };
 
+BaseHandle Create()
+{
+  return Dali::BaseHandle();
+}
+
+TypeRegistration mType( typeid( Dali::PropertyBuffer ), typeid( Dali::Handle ), Create );
+
+/**
+ * Calculate the alignment requirements of a type
+ *
+ * This is used to calculate the memory alignment requirements of a type
+ * It creates a structure with a dummy char and a member of the type we want to check
+ * this will cause the second member to be aligned by it's alignment requirement.
+ */
+template<Property::Type type>
+struct PropertyImplementationTypeAlignment
+{
+  // Create a structure that forces alignment of the data type
+  struct TestStructure
+  {
+    char oneChar;  ///< Member with sizeof() == 1
+    typename PropertyImplementationType<type>::Type data;
+  };
+  enum { VALUE = offsetof( TestStructure, data ) };
+};
+
+unsigned int GetPropertyImplementationAlignment( Property::Type& propertyType )
+{
+  unsigned int alignment = 0u;
+
+  switch( propertyType )
+  {
+    case Property::NONE:
+    case Property::STRING:
+    case Property::ARRAY:
+    case Property::MAP:
+    {
+      DALI_ASSERT_ALWAYS( "No size for properties with no type, or dynamic sizes" );
+      break;
+    }
+    case Property::BOOLEAN:
+    {
+      alignment = PropertyImplementationTypeAlignment< Property::BOOLEAN >::VALUE;
+      break;
+    }
+    case Property::INTEGER:
+    {
+      alignment = PropertyImplementationTypeAlignment< Property::INTEGER >::VALUE;
+      break;
+    }
+    case Property::FLOAT:
+    {
+      alignment = PropertyImplementationTypeAlignment< Property::FLOAT >::VALUE;
+      break;
+    }
+    case Property::VECTOR2:
+    {
+      alignment = PropertyImplementationTypeAlignment< Property::VECTOR2 >::VALUE;
+      break;
+    }
+    case Property::VECTOR3:
+    {
+      alignment = PropertyImplementationTypeAlignment< Property::VECTOR3 >::VALUE;
+      break;
+    }
+    case Property::VECTOR4:
+    {
+      alignment = PropertyImplementationTypeAlignment< Property::VECTOR4 >::VALUE;
+      break;
+    }
+    case Property::MATRIX3:
+    {
+      alignment = PropertyImplementationTypeAlignment< Property::MATRIX3 >::VALUE;
+      break;
+    }
+    case Property::MATRIX:
+    {
+      alignment = PropertyImplementationTypeAlignment< Property::MATRIX >::VALUE;
+      break;
+    }
+    case Property::RECTANGLE:
+    {
+      alignment = PropertyImplementationTypeAlignment< Property::RECTANGLE >::VALUE;
+      break;
+    }
+    case Property::ROTATION:
+    {
+      alignment = PropertyImplementationTypeAlignment< Property::ROTATION >::VALUE;
+      break;
+    }
+  }
+
+  return alignment;
+}
+
 } // unnamed namespace
 
 PropertyBufferPtr PropertyBuffer::New()
@@ -89,41 +186,11 @@ void PropertyBuffer::SetData( const void* data )
                               new SceneGraph::PropertyBuffer::BufferType( mBuffer ) );
 }
 
-Dali::Property::Index PropertyBuffer::GetPropertyIndex( const std::string name, std::size_t index )
-{
-  //TODO: MESH_REWORK
-  DALI_ASSERT_ALWAYS( false && "MESH_REWORK" );
-  return 0;
-}
-
 const SceneGraph::PropertyBuffer* PropertyBuffer::GetPropertyBufferSceneObject() const
 {
   return mSceneObject;
 }
 
-void PropertyBuffer::SetType( Dali::PropertyBuffer::Type type )
-{
-  DALI_ASSERT_DEBUG( !mTypeSet && "Type of property buffer can only be set once." );
-
-  switch(type)
-  {
-    case  Dali::PropertyBuffer::STATIC:
-    {
-      mIsAnimatable = false;
-      break;
-    }
-    case  Dali::PropertyBuffer::ANIMATABLE:
-    {
-      mIsAnimatable = true;
-      break;
-    }
-  }
-
-#ifdef DEBUG_ENABLED
-  mTypeSet = true;
-#endif // DEBUG_ENABLED
-}
-
 void PropertyBuffer::SetFormat( Dali::Property::Map& format )
 {
   DALI_ASSERT_ALWAYS( format.Count() && "Format cannot be empty." );
@@ -208,7 +275,7 @@ Property::Value PropertyBuffer::GetDefaultProperty( Property::Index index ) cons
   {
     case Dali::PropertyBuffer::Property::SIZE:
     {
-      value = static_cast<int>( GetSize() ); // @todo MESH_REWORK Add a size_t type to PropertyValue
+      value = static_cast<int>( GetSize() );
       break;
     }
     case Dali::PropertyBuffer::Property::BUFFER_FORMAT:
@@ -280,7 +347,7 @@ const PropertyInputImpl* PropertyBuffer::GetSceneObjectInputProperty( Property::
 
 int PropertyBuffer::GetPropertyComponentIndex( Property::Index index ) const
 {
-  return PROPERTY_BUFFER_IMPL.GetPropertyComponentIndex( index );
+  return Property::INVALID_COMPONENT_INDEX;
 }
 
 bool PropertyBuffer::OnStage() const
@@ -300,17 +367,21 @@ void PropertyBuffer::Disconnect()
 
 PropertyBuffer::~PropertyBuffer()
 {
+  if( EventThreadServices::IsCoreRunning() )
+  {
+    EventThreadServices& eventThreadServices = GetEventThreadServices();
+    SceneGraph::UpdateManager& updateManager = eventThreadServices.GetUpdateManager();
+    RemoveMessage( updateManager, updateManager.GetPropertyBufferOwner(), *mSceneObject );
+
+    eventThreadServices.UnregisterObject( this );
+  }
 }
 
 PropertyBuffer::PropertyBuffer()
 : mSceneObject( NULL ),
   mBufferFormat( NULL ),
   mSize( 0 ),
-  mIsAnimatable( false ),
   mOnStage( false )
-#ifdef DEBUG_ENABLED
-  , mTypeSet( false )
-#endif
 {
 }
 
@@ -319,10 +390,10 @@ void PropertyBuffer::Initialize()
   EventThreadServices& eventThreadServices = GetEventThreadServices();
   SceneGraph::UpdateManager& updateManager = eventThreadServices.GetUpdateManager();
 
-  DALI_ASSERT_ALWAYS( EventThreadServices::IsCoreRunning() && "Core is not running" );
-
   mSceneObject = new SceneGraph::PropertyBuffer();
   AddMessage( updateManager, updateManager.GetPropertyBufferOwner(), *mSceneObject );
+
+  eventThreadServices.RegisterObject( this );
 }
 
 void PropertyBuffer::FormatChanged()
@@ -334,7 +405,9 @@ void PropertyBuffer::FormatChanged()
   Format* bufferFormat = new Format();
   bufferFormat->components.resize( numComponents );
 
-  unsigned int elementSize = 0;
+  unsigned int currentAlignment = 0u;
+  unsigned int maxAlignmentRequired = 0u;
+
   for( size_t i = 0u; i < numComponents; ++i )
   {
     StringValuePair component = mFormat.GetPair( i );
@@ -342,14 +415,46 @@ void PropertyBuffer::FormatChanged()
     // Get the name
     bufferFormat->components[i].name = component.first;
 
-    // Get the size
+    // enums are stored in the map as int
     Property::Type type = Property::Type( component.second.Get<int>() );
-    elementSize += GetPropertyImplementationSize( type );
 
-    // write the accumulatedSize
-    bufferFormat->components[i].accumulatedSize = elementSize;
+    // Get the size and alignment
+    unsigned int elementSize = GetPropertyImplementationSize( type );
+    unsigned int elementAlignment = GetPropertyImplementationAlignment( type );
+
+    // check if current alignment is compatible with new member
+    if( unsigned int offset = currentAlignment % elementAlignment )
+    {
+      // Not compatible, realign
+      currentAlignment = currentAlignment + elementSize - offset;
+    }
+
+    // write to the format
+    bufferFormat->components[i].size = elementSize;
+    bufferFormat->components[i].offset = currentAlignment;
+    bufferFormat->components[i].type = type;
+
+    // update offset
+    currentAlignment += elementSize;
+
+    // update max alignment requirement
+    if( elementAlignment > maxAlignmentRequired )
+    {
+      maxAlignmentRequired = elementAlignment;
+    }
+
+  }
+
+  // Check the alignment for the maxAlignment required to calculate the size of the format
+  if( unsigned int offset = currentAlignment % maxAlignmentRequired )
+  {
+    // Not compatible, realign
+    currentAlignment = currentAlignment + maxAlignmentRequired - offset;
   }
 
+  // Set the format size
+  bufferFormat->size = currentAlignment;
+
   mBufferFormat = bufferFormat;
 
   SceneGraph::SetFormatMessage( GetEventThreadServices(),
@@ -367,7 +472,7 @@ void PropertyBuffer::SizeChanged()
   // Check if format and size have been set yet
   if( mBufferFormat != NULL )
   {
-    unsigned int bufferSize = mBufferFormat->GetElementSize() * mSize;
+    unsigned int bufferSize = mBufferFormat->size * mSize;
     mBuffer.Resize( bufferSize );
   }
 }
@@ -379,7 +484,6 @@ unsigned int GetPropertyImplementationSize( Property::Type& propertyType )
   switch( propertyType )
   {
     case Property::NONE:
-    case Property::TYPE_COUNT:
     case Property::STRING:
     case Property::ARRAY:
     case Property::MAP:
@@ -392,19 +496,14 @@ unsigned int GetPropertyImplementationSize( Property::Type& propertyType )
       size = sizeof( PropertyImplementationType< Property::BOOLEAN >::Type );
       break;
     }
-    case Property::FLOAT:
-    {
-      size = sizeof( PropertyImplementationType< Property::FLOAT >::Type );
-      break;
-    }
     case Property::INTEGER:
     {
       size = sizeof( PropertyImplementationType< Property::INTEGER >::Type );
       break;
     }
-    case Property::UNSIGNED_INTEGER:
+    case Property::FLOAT:
     {
-      size = sizeof( PropertyImplementationType< Property::UNSIGNED_INTEGER >::Type );
+      size = sizeof( PropertyImplementationType< Property::FLOAT >::Type );
       break;
     }
     case Property::VECTOR2:
@@ -447,5 +546,6 @@ unsigned int GetPropertyImplementationSize( Property::Type& propertyType )
   return size;
 }
 
+
 } // namespace Internal
 } // namespace Dali