Correctly calculate alignment of members in propertyBuffers. 26/39226/4
authorFrancisco Santos <f1.santos@samsung.com>
Mon, 11 May 2015 18:16:36 +0000 (19:16 +0100)
committerFrancisco Santos <f1.santos@samsung.com>
Wed, 13 May 2015 11:57:25 +0000 (12:57 +0100)
Change-Id: I7575c7ec1608517478f1a308f51d1eb90551e45f

dali/internal/event/common/property-buffer-impl.cpp
dali/internal/event/common/property-buffer-impl.h
dali/internal/update/common/scene-graph-property-buffer.cpp
dali/internal/update/common/scene-graph-property-buffer.h

index f6f92e5..1672469 100644 (file)
@@ -49,6 +49,175 @@ DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
 
 const ObjectImplHelper<DEFAULT_PROPERTY_COUNT> PROPERTY_BUFFER_IMPL = { DEFAULT_PROPERTY_DETAILS };
 
+unsigned int GetPropertyImplementationSize( Property::Type& propertyType )
+{
+  unsigned int size = 0u;
+
+  switch( propertyType )
+  {
+    case Property::NONE:
+    case Property::TYPE_COUNT:
+    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:
+    {
+      size = sizeof( PropertyImplementationType< Property::BOOLEAN >::Type );
+      break;
+    }
+    case Property::INTEGER:
+    {
+      size = sizeof( PropertyImplementationType< Property::INTEGER >::Type );
+      break;
+    }
+    case Property::UNSIGNED_INTEGER:
+    {
+      size = sizeof( PropertyImplementationType< Property::UNSIGNED_INTEGER >::Type );
+      break;
+    }
+    case Property::FLOAT:
+    {
+      size = sizeof( PropertyImplementationType< Property::FLOAT >::Type );
+      break;
+    }
+    case Property::VECTOR2:
+    {
+      size = sizeof( PropertyImplementationType< Property::VECTOR2 >::Type );
+      break;
+    }
+    case Property::VECTOR3:
+    {
+      size = sizeof( PropertyImplementationType< Property::VECTOR3 >::Type );
+      break;
+    }
+    case Property::VECTOR4:
+    {
+      size = sizeof( PropertyImplementationType< Property::VECTOR4 >::Type );
+      break;
+    }
+    case Property::MATRIX3:
+    {
+      size = sizeof( PropertyImplementationType< Property::MATRIX3 >::Type );
+      break;
+    }
+    case Property::MATRIX:
+    {
+      size = sizeof( PropertyImplementationType< Property::MATRIX >::Type );
+      break;
+    }
+    case Property::RECTANGLE:
+    {
+      size = sizeof( PropertyImplementationType< Property::RECTANGLE >::Type );
+      break;
+    }
+    case Property::ROTATION:
+    {
+      size = sizeof( PropertyImplementationType< Property::ROTATION >::Type );
+      break;
+    }
+  }
+
+  return size;
+}
+
+/**
+ * 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::TYPE_COUNT:
+    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 = sizeof( PropertyImplementationTypeAlignment< Property::BOOLEAN >::VALUE );
+      break;
+    }
+    case Property::INTEGER:
+    {
+      alignment = sizeof( PropertyImplementationTypeAlignment< Property::INTEGER >::VALUE );
+      break;
+    }
+    case Property::UNSIGNED_INTEGER:
+    {
+      alignment = sizeof( PropertyImplementationTypeAlignment< Property::UNSIGNED_INTEGER >::VALUE );
+      break;
+    }
+    case Property::FLOAT:
+    {
+      alignment = sizeof( PropertyImplementationTypeAlignment< Property::FLOAT >::VALUE );
+      break;
+    }
+    case Property::VECTOR2:
+    {
+      alignment = sizeof( PropertyImplementationTypeAlignment< Property::VECTOR2 >::VALUE );
+      break;
+    }
+    case Property::VECTOR3:
+    {
+      alignment = sizeof( PropertyImplementationTypeAlignment< Property::VECTOR3 >::VALUE );
+      break;
+    }
+    case Property::VECTOR4:
+    {
+      alignment = sizeof( PropertyImplementationTypeAlignment< Property::VECTOR4 >::VALUE );
+      break;
+    }
+    case Property::MATRIX3:
+    {
+      alignment = sizeof( PropertyImplementationTypeAlignment< Property::MATRIX3 >::VALUE );
+      break;
+    }
+    case Property::MATRIX:
+    {
+      alignment = sizeof( PropertyImplementationTypeAlignment< Property::MATRIX >::VALUE );
+      break;
+    }
+    case Property::RECTANGLE:
+    {
+      alignment = sizeof( PropertyImplementationTypeAlignment< Property::RECTANGLE >::VALUE );
+      break;
+    }
+    case Property::ROTATION:
+    {
+      alignment = sizeof( PropertyImplementationTypeAlignment< Property::ROTATION >::VALUE );
+      break;
+    }
+  }
+
+  return alignment;
+}
+
 } // unnamed namespace
 
 PropertyBufferPtr PropertyBuffer::New()
@@ -316,7 +485,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 );
@@ -324,14 +495,45 @@ void PropertyBuffer::FormatChanged()
     // Get the name
     bufferFormat->components[i].name = component.first;
 
-    // Get the size ( enums are stored in the map as int )
+    // 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;
+
+    // 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(),
@@ -349,91 +551,10 @@ 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 );
   }
 }
 
-unsigned int GetPropertyImplementationSize( Property::Type& propertyType )
-{
-  unsigned int size = 0u;
-
-  switch( propertyType )
-  {
-    case Property::NONE:
-    case Property::TYPE_COUNT:
-    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:
-    {
-      size = sizeof( PropertyImplementationType< Property::BOOLEAN >::Type );
-      break;
-    }
-    case Property::INTEGER:
-    {
-      size = sizeof( PropertyImplementationType< Property::INTEGER >::Type );
-      break;
-    }
-    case Property::UNSIGNED_INTEGER:
-    {
-      size = sizeof( PropertyImplementationType< Property::UNSIGNED_INTEGER >::Type );
-      break;
-    }
-    // TODO : MESH_REWORK : uncoment this code
-//    case Property::UNSIGNED_SHORT:
-//    {
-//      size = sizeof( PropertyImplementationType< Property::UNSIGNED_SHORT >::Type );
-//      break;
-//    }
-    case Property::FLOAT:
-    {
-      size = sizeof( PropertyImplementationType< Property::FLOAT >::Type );
-      break;
-    }
-    case Property::VECTOR2:
-    {
-      size = sizeof( PropertyImplementationType< Property::VECTOR2 >::Type );
-      break;
-    }
-    case Property::VECTOR3:
-    {
-      size = sizeof( PropertyImplementationType< Property::VECTOR3 >::Type );
-      break;
-    }
-    case Property::VECTOR4:
-    {
-      size = sizeof( PropertyImplementationType< Property::VECTOR4 >::Type );
-      break;
-    }
-    case Property::MATRIX3:
-    {
-      size = sizeof( PropertyImplementationType< Property::MATRIX3 >::Type );
-      break;
-    }
-    case Property::MATRIX:
-    {
-      size = sizeof( PropertyImplementationType< Property::MATRIX >::Type );
-      break;
-    }
-    case Property::RECTANGLE:
-    {
-      size = sizeof( PropertyImplementationType< Property::RECTANGLE >::Type );
-      break;
-    }
-    case Property::ROTATION:
-    {
-      size = sizeof( PropertyImplementationType< Property::ROTATION >::Type );
-      break;
-    }
-  }
-
-  return size;
-}
-
 } // namespace Internal
 } // namespace Dali
index 715e62d..760c32f 100644 (file)
@@ -18,6 +18,9 @@
  *
  */
 
+// EXTERNAL INCLUDES
+#include <utility> // std::pair
+
 // INTERNAL INCLUDES
 #include <dali/public-api/common/dali-common.h> // DALI_ASSERT_ALWAYS
 #include <dali/public-api/common/intrusive-ptr.h> // Dali::IntrusivePtr
@@ -263,15 +266,6 @@ template<> struct PropertyImplementationType< Property::MATRIX > { typedef Matri
 template<> struct PropertyImplementationType< Property::RECTANGLE > { typedef Rect<int> Type; };
 template<> struct PropertyImplementationType< Property::ROTATION > { typedef Quaternion Type; };
 
-/**
- * Get the size of the implementation of a Property::Type
- *
- * @param[in] propertyType Property::Type used to check the size
- *
- * @return Size given by sizeof for the implementation this propertyType
- */
-unsigned int GetPropertyImplementationSize( Property::Type& propertyType );
-
 } // namespace Internal
 
 // Helpers for public-api forwarding methods
index 97bbd51..537463e 100644 (file)
@@ -23,24 +23,6 @@ namespace Internal
 namespace SceneGraph
 {
 
-namespace PropertyBufferMetadata
-{
-
-unsigned int Format::GetComponentOffset( unsigned int index ) const
-{
-  DALI_ASSERT_DEBUG( index >= 0 && index < components.size() && "Index not within the correct boundaries." );
-  return index > 0 ? components[index-1u].accumulatedSize : 0;
-}
-
-unsigned int Format::GetElementSize() const
-{
-  unsigned int numComponents = components.size();
-  return numComponents ? components.back().accumulatedSize : 0;
-}
-
-} // namespace PropertyBufferMetadata
-
-
 PropertyBuffer::PropertyBuffer()
 : mBufferData(NULL),
   mSize(0u)
@@ -96,28 +78,14 @@ size_t PropertyBuffer::GetAttributeSize( BufferIndex bufferIndex, unsigned int i
 {
   DALI_ASSERT_DEBUG( mFormat && "Format should be set ");
 
-  size_t size = mFormat->components[index].accumulatedSize;
-
-  if ( index > 0 )
-  {
-    size -= mFormat->components[index - 1].accumulatedSize;
-  }
-
-  return size;
+  return mFormat->components[index].size;
 }
 
 size_t PropertyBuffer::GetAttributeOffset( BufferIndex bufferIndex, unsigned int index ) const
 {
   DALI_ASSERT_DEBUG( mFormat && "Format should be set ");
 
-  size_t offset = 0;
-
-  if ( index > 0 )
-  {
-    offset = mFormat->components[index - 1].accumulatedSize;
-  }
-
-  return offset;
+  return mFormat->components[index].offset;
 }
 
 const PropertyBufferDataProvider::BufferType& PropertyBuffer::GetData( BufferIndex bufferIndex ) const
@@ -131,12 +99,12 @@ std::size_t PropertyBuffer::GetDataSize( BufferIndex bufferIndex ) const
 {
   DALI_ASSERT_DEBUG( mFormat && "Format should be set ");
 
-  return mFormat->GetElementSize() * mSize[ bufferIndex ];
+  return mFormat->size * mSize[ bufferIndex ];
 }
 
 std::size_t PropertyBuffer::GetElementSize( BufferIndex bufferIndex ) const
 {
-  return mFormat->GetElementSize();
+  return mFormat->size;
 }
 
 unsigned int PropertyBuffer::GetElementCount( BufferIndex bufferIndex ) const
index b0c1dfb..48c3b8e 100644 (file)
@@ -39,7 +39,8 @@ namespace PropertyBufferMetadata
 struct Component
 {
   std::string name;
-  unsigned int accumulatedSize;
+  unsigned int offset;
+  unsigned int size;
 };
 
 /**
@@ -48,22 +49,7 @@ struct Component
 struct Format
 {
   std::vector<Component> components;
-
-  /**
-   * @brief Get the offset of a component within an element
-   *
-   * @pre index must be within 0 and components.Size()-1
-   *
-   * @return The offset for a component within an element
-   */
-  unsigned int GetComponentOffset( unsigned int index ) const;
-
-  /**
-   * @brief Get the size of an element
-   *
-   * @return The size of an element
-   */
-  unsigned int GetElementSize() const;
+  unsigned int size;
 };
 
 } // PropertyBufferMetadata