// CLASS HEADER
#include <dali/internal/event/common/property-buffer-impl.h> // Dali::Internal::PropertyBuffer
+// EXTERNAL INCLUDE
+#include <algorithm> // std::sort
+
// INTERNAL INCLUDES
-#include <dali/public-api/object/property-buffer.h> // Dali::Internal::PropertyBuffer
+#include <dali/public-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>
#include <dali/internal/update/manager/update-manager.h>
-// @todo MESH_REWORK remove this comment - Don't include "stage.h" - use GetEventThreadServices() instead.
namespace Dali
{
namespace Internal
{
+using SceneGraph::PropertyBufferMetadata::Format;
+using SceneGraph::PropertyBufferMetadata::Component;
+
namespace
{
PropertyBufferPtr PropertyBuffer::New()
{
- return PropertyBufferPtr( new PropertyBuffer() );
+ PropertyBufferPtr propertyBuffer( new PropertyBuffer() );
+ propertyBuffer->Initialize();
+
+ return propertyBuffer;
}
void PropertyBuffer::SetSize( std::size_t size )
{
- //TODO: MESH_REWORK
- DALI_ASSERT_ALWAYS( false && "MESH_REWORK" );
+ mSize = size;
+
+ SizeChanged();
+
+ SceneGraph::SetSizeMessage( GetEventThreadServices(),
+ *mSceneObject,
+ mSize );
}
std::size_t PropertyBuffer::GetSize() const
{
- //TODO: MESH_REWORK
- DALI_ASSERT_ALWAYS( false && "MESH_REWORK" );
-
- return 0;
+ return mSize;
}
-void PropertyBuffer::SetData( void* data )
+void PropertyBuffer::SetData( const void* data )
{
- //TODO: MESH_REWORK
- DALI_ASSERT_ALWAYS( false && "MESH_REWORK" );
+ DALI_ASSERT_DEBUG( mFormat.Count() && "Format must be set before setting the data." );
+
+ DALI_ASSERT_ALWAYS( mSize && "Size of the buffer must be set before setting the data." );
+
+ const char* source = static_cast<const char*>( data );
+ std::copy( source, source + mBuffer.Size(), &mBuffer[0] );
+
+ SceneGraph::SetDataMessage( GetEventThreadServices(),
+ *mSceneObject,
+ new SceneGraph::PropertyBuffer::BufferType( mBuffer ) );
}
Dali::Property::Index PropertyBuffer::GetPropertyIndex( const std::string name, std::size_t index )
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." );
+
+ DALI_ASSERT_DEBUG( 0 == mFormat.Count() && "Format of property buffer can only be set once." );
+
+ mFormat = format;
+
+ FormatChanged();
+}
+
unsigned int PropertyBuffer::GetDefaultPropertyCount() const
{
return PROPERTY_BUFFER_IMPL.GetDefaultPropertyCount();
mOnStage = false;
}
+PropertyBuffer::~PropertyBuffer()
+{
+}
+
PropertyBuffer::PropertyBuffer()
-: mSceneObject(NULL),
+: mSceneObject( NULL ),
+ mBufferFormat( NULL ),
+ mSize( 0 ),
+ mIsAnimatable( false ),
mOnStage( false )
+#ifdef DEBUG_ENABLED
+ , mTypeSet( false )
+#endif
+{
+}
+
+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 );
+}
+
+void PropertyBuffer::FormatChanged()
+{
+ size_t numComponents = mFormat.Count();
+
+ // Create the format
+ DALI_ASSERT_DEBUG( mBufferFormat == NULL && "PropertyFormat should not be set yet" );
+ Format* bufferFormat = new Format();
+ bufferFormat->components.resize( numComponents );
+
+ unsigned int elementSize = 0;
+ for( size_t i = 0u; i < numComponents; ++i )
+ {
+ StringValuePair component = mFormat.GetPair( i );
+
+ // Get the name
+ bufferFormat->components[i].name = component.first;
+
+ // Get the size
+ Property::Type type = Property::Type( component.second.Get<int>() );
+ elementSize += GetPropertyImplementationSize( type );
+
+ // write the accumulatedSize
+ bufferFormat->components[i].accumulatedSize = elementSize;
+ }
+
+ mBufferFormat = bufferFormat;
+
+ SceneGraph::SetFormatMessage( GetEventThreadServices(),
+ *mSceneObject,
+ bufferFormat );
+
+ if( mSize )
+ {
+ SizeChanged();
+ }
+}
+
+void PropertyBuffer::SizeChanged()
{
+ // Check if format and size have been set yet
+ if( mBufferFormat != NULL )
+ {
+ unsigned int bufferSize = mBufferFormat->GetElementSize() * 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::FLOAT:
+ {
+ size = sizeof( PropertyImplementationType< Property::FLOAT >::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::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
#include <dali/public-api/common/dali-common.h> // DALI_ASSERT_ALWAYS
#include <dali/public-api/common/intrusive-ptr.h> // Dali::IntrusivePtr
#include <dali/public-api/object/property-buffer.h> // Dali::PropertyBuffer
+#include <dali/public-api/object/property-map.h> // Dali::Property::Map
#include <dali/internal/event/common/connectable.h> // Dali::Internal::Connectable
#include <dali/internal/event/common/object-connector.h> // Dali::Internal::ObjectConnector
#include <dali/internal/event/common/object-impl.h> // Dali::Internal::Object
namespace SceneGraph
{
class PropertyBuffer;
-}
+
+namespace PropertyBufferMetadata
+{
+struct Format;
+} // namespace PropertyBufferMetadata
+
+} // namespace SceneGraph
class PropertyBuffer;
typedef IntrusivePtr<PropertyBuffer> PropertyBufferPtr;
/**
* @copydoc PropertBuffer::SetData()
*/
- void SetData( void* data );
+ void SetData( const void* data );
/**
* @copydoc PropertBuffer::GetPropertyIndex()
*/
const SceneGraph::PropertyBuffer* GetPropertyBufferSceneObject() const;
+ /**
+ * @brief Set the type of PropertyBuffer
+ *
+ * @pre Has not been set yet
+ *
+ * @param[in] type of PropertyBuffer
+ */
+ void SetType( Dali::PropertyBuffer::Type type );
+
+ /**
+ * @brief Set the format of the PropertyBuffer
+ *
+ * @pre Has not been set yet
+ *
+ * @param[in] format of the PropertyBuffer
+ */
+ void SetFormat( Dali::Property::Map& format );
+
public: // Default property extensions from Object
/**
virtual bool OnStage() const;
/**
- * @copydoc Dali::Internal::Connectable::Connect()
+ * @copydoc Dali::Internal::Connectable::Contnect()
*/
virtual void Connect();
*/
virtual void Disconnect();
+protected:
+ /**
+ * @brief Destructor
+ */
+ ~PropertyBuffer();
+
private: // implementation
+ /**
+ * @brief Default constructor
+ */
PropertyBuffer();
+ /**
+ * Second stage initialization
+ */
+ void Initialize();
+
+ /**
+ * Update the buffer when the format changes
+ */
+ void FormatChanged();
+
+ /**
+ * Update the buffer when the size changes
+ */
+ void SizeChanged();
+
private: // unimplemented methods
PropertyBuffer( const PropertyBuffer& );
PropertyBuffer& operator=( const PropertyBuffer& );
private: // data
- SceneGraph::PropertyBuffer* mSceneObject;
- bool mOnStage;
+ SceneGraph::PropertyBuffer* mSceneObject; ///< Update side object
+
+ Property::Map mFormat; ///< Format of the property buffer
+ const SceneGraph::PropertyBufferMetadata::Format* mBufferFormat; ///< Metadata for the format of the property buffer
+
+ unsigned int mSize; ///< Size of the buffer
+ bool mIsAnimatable; ///< Flag to know if the property buffer is animatable
+
+ Dali::Vector< char > mBuffer;
+
+ bool mOnStage; ///< Flag to know if the object is on stage
+
+#ifdef DEBUG_ENABLED
+private:
+ bool mTypeSet; // used to ensure the type doesn't change at runtime
+#endif // DEBUG_ENABLED
};
+/**
+ * Get the implementation type from a Property::Type
+ */
+template<Property::Type type> struct PropertyImplementationType
+{
+ // typedef ... Type; not defined, only support types declared bellow
+};
+template<> struct PropertyImplementationType< Property::BOOLEAN > { typedef bool Type; };
+template<> struct PropertyImplementationType< Property::FLOAT > { typedef float Type; };
+template<> struct PropertyImplementationType< Property::INTEGER > { typedef int Type; };
+template<> struct PropertyImplementationType< Property::UNSIGNED_INTEGER > { typedef unsigned int Type; };
+template<> struct PropertyImplementationType< Property::VECTOR2 > { typedef Vector2 Type; };
+template<> struct PropertyImplementationType< Property::VECTOR3 > { typedef Vector3 Type; };
+template<> struct PropertyImplementationType< Property::VECTOR4 > { typedef Vector4 Type; };
+template<> struct PropertyImplementationType< Property::MATRIX3 > { typedef Matrix3 Type; };
+template<> struct PropertyImplementationType< Property::MATRIX > { typedef Matrix Type; };
+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
if( indexBuffer )
{
- numIndices = indexBuffer->GetDataSize(bufferIndex) / indexBuffer->GetElementSize(bufferIndex);
+ numIndices = /* TODO: MESH_REWORK remove this 2, should implement unsigned short properties */ 2 * indexBuffer->GetDataSize(bufferIndex) / indexBuffer->GetElementSize(bufferIndex);
}
switch(type)
* limitations under the License.
*/
-#include "scene-graph-property-buffer.h"
+#include <dali/internal/update/common/scene-graph-property-buffer.h>
namespace Dali
{
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()
+: mRenderBufferData( NULL ),
+ mSize(0u)
{
}
{
}
-//@todo MESH_REWORK Remove when we have working property buffers
-PropertyBuffer* PropertyBuffer::NewQuadVertices()
+std::size_t PropertyBuffer::GetDataSize( BufferIndex bufferIndex ) const
{
- PropertyBuffer* propertyBuffer = new PropertyBuffer();
- propertyBuffer->mElementSize = sizeof(Vector4);
- propertyBuffer->mData.Resize( propertyBuffer->mElementSize * 4 );
- Vector4* vertices = reinterpret_cast<Vector4*>(&propertyBuffer->mData[0]);
-
- vertices[ 0 ] = Vector4( -0.5f, -0.5f, 0.0f, 0.0f );
- vertices[ 1 ] = Vector4( 0.5f, -0.5f, 1.0f, 0.0f );
- vertices[ 2 ] = Vector4( -0.5f, 0.5f, 0.0f, 1.0f );
- vertices[ 3 ] = Vector4( 0.5f, 0.5f, 1.0f, 1.0f );
+ DALI_ASSERT_DEBUG( mFormat && "Format must have been set!" );
- return propertyBuffer;
+ // @todo MESH_REWORK mData should be double buffered?
+ return mFormat->components.back().accumulatedSize * mSize;
}
-//@todo MESH_REWORK Remove when we have working property buffers
-PropertyBuffer* PropertyBuffer::NewQuadIndices()
+std::size_t PropertyBuffer::GetElementSize( BufferIndex bufferIndex ) const
{
- PropertyBuffer* propertyBuffer = new PropertyBuffer();
+ DALI_ASSERT_DEBUG( mFormat && "Format must have been set!" );
- propertyBuffer->mElementSize = sizeof( unsigned short );
- propertyBuffer->mData.Resize( propertyBuffer->mElementSize * 6 );
- unsigned short* indices = reinterpret_cast<unsigned short*>(&propertyBuffer->mData[0]);
-
- indices[0] = 0; indices[1] = 3; indices[2] = 1;
- indices[3] = 0; indices[4] = 2; indices[5] = 3;
+ // @todo MESH_REWORK mData should be double buffered?
+ return mFormat->GetElementSize();
+}
- return propertyBuffer;
+void PropertyBuffer::SetFormat( PropertyBufferMetadata::Format* format )
+{
+ mFormat = format;
}
-std::size_t PropertyBuffer::GetDataSize( BufferIndex bufferIndex ) const
+//TODO:: MESH_REWORK Remove this, should be a property
+void PropertyBuffer::SetSize( unsigned int size )
{
- // @todo MESH_REWORK mData should be double buffered
- return mData.Count();
+ mSize = size;
}
-std::size_t PropertyBuffer::GetElementSize( BufferIndex bufferIndex ) const
+void PropertyBuffer::SetData( BufferType* data )
{
- // @todo MESH_REWORK mElementSize should be double buffered
- return mElementSize;
+ mBufferData = data;
}
const void* PropertyBuffer::GetData( BufferIndex bufferIndex ) const
{
// @todo MESH_REWORK mData should be double buffered
- return reinterpret_cast< const void* >(&mData[0]);
+ return reinterpret_cast< const void* >(&(*mBufferData.Get())[0]);
}
void PropertyBuffer::ConnectToSceneGraph( SceneController& sceneController, BufferIndex bufferIndex )
* limitations under the License.
*/
-#include <dali/public-api/common/dali-vector.h>
#include <dali/internal/common/buffer-index.h>
#include <dali/internal/update/common/property-owner.h>
+#include <dali/internal/event/common/event-thread-services.h>
namespace Dali
{
{
class SceneController;
+namespace PropertyBufferMetadata
+{
+/**
+ * Structure that holds name and size of a component in the PropertyBuffer.
+ */
+struct Component
+{
+ std::string name;
+ unsigned int accumulatedSize;
+};
+
+/**
+ * Structure that holds the meta-data of the format of PropertyBuffer.
+ */
+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;
+};
+
+} // PropertyBufferMetadata
+
class PropertyBuffer : public PropertyOwner
{
public:
- //@todo MESH_REWORK Remove when we have working property buffers
- static PropertyBuffer* NewQuadVertices();
- //@todo MESH_REWORK Remove when we have working property buffers
- static PropertyBuffer* NewQuadIndices();
+ /**
+ * Type for the data contained in the buffer
+ */
+ typedef Dali::Vector< char > BufferType;
/**
* Constructor
std::size_t GetElementSize( BufferIndex bufferIndex ) const;
/**
+ * Set the format of the buffer
+ * @param[in] format The format for the PropertyBuffer
+ */
+ void SetFormat( PropertyBufferMetadata::Format* format );
+
+ /**
+ * Set the data of the PropertyBuffer
+ * @param[in] data The new data of the PropertyBuffer
+ */
+ void SetData( BufferType* data );
+
+ //TODO:: MESH_REWORK Remove this, should be a property
+ void SetSize( unsigned int size );
+
+ /**
* Get the property buffer data
* @return the property buffer's data array
*/
void DisconnectFromSceneGraph( SceneController& sceneController, BufferIndex bufferIndex );
private:
+ OwnerPointer<PropertyBufferMetadata::Format> mFormat; ///< Format of the buffer
+ OwnerPointer<BufferType> mBufferData; ///< Data
+ BufferType* mRenderBufferData;
- // @todo MESH_REWORK - TEMPORARY TYPES - REMOVE WHEN WE HAVE WORKING BUFFERS
- typedef Dali::Vector< char > CharBuffer;
- CharBuffer mData;
- std::size_t mElementSize;
+ //TODO: MESH_REWORK should be double buffered property
+ unsigned int mSize; ///< Size of the buffer
};
+inline void SetFormatMessage( EventThreadServices& eventThreadServices,
+ const PropertyBuffer& propertyBuffer,
+ PropertyBufferMetadata::Format* format )
+{
+ typedef MessageValue1< PropertyBuffer, OwnerPointer<PropertyBufferMetadata::Format> > 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( &propertyBuffer, &PropertyBuffer::SetFormat, format );
+}
+
+//TODO:: MESH_REWORK Remove this, should be a property
+inline void SetSizeMessage( EventThreadServices& eventThreadServices,
+ const PropertyBuffer& propertyBuffer,
+ unsigned int size )
+{
+ typedef MessageValue1< PropertyBuffer, unsigned int > 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( &propertyBuffer, &PropertyBuffer::SetSize, size );
+}
+
+inline void SetDataMessage( EventThreadServices& eventThreadServices,
+ const PropertyBuffer& propertyBuffer,
+ PropertyBuffer::BufferType* data )
+{
+ typedef MessageValue1< PropertyBuffer, OwnerPointer<PropertyBuffer::BufferType> > 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( &propertyBuffer, &PropertyBuffer::SetData, data );
+}
+
} // namespace SceneGraph
} // namespace Internal
} // namespace Dali
mGeometryType(Dali::Geometry::TRIANGLES),
mRequiresDepthTest(false)
{
- // @todo MESH_REWORK Remove this code when we have working property buffers
- // @todo It's also the wrong place to do this temporary work
- PropertyBuffer* vertexPropertyBuffer = PropertyBuffer::NewQuadVertices();
- mVertexBuffers.PushBack( vertexPropertyBuffer );
-
- mIndexBuffer = PropertyBuffer::NewQuadIndices();
// Observe our own PropertyOwner's uniform map
AddUniformMapObserver( *this );
namespace Dali
{
-PropertyBuffer PropertyBuffer::New( Type type, Dali::Property::Map bufferFormat, std::size_t size )
+PropertyBuffer PropertyBuffer::New( Type type, Dali::Property::Map& bufferFormat, std::size_t size )
{
- Internal::PropertyBufferPtr renderer = Internal::PropertyBuffer::New();
- return PropertyBuffer( renderer.Get() );
+ Internal::PropertyBufferPtr propertyBuffer = Internal::PropertyBuffer::New();
+
+ propertyBuffer->SetType( type );
+ propertyBuffer->SetFormat( bufferFormat );
+ propertyBuffer->SetSize( size );
+
+ return PropertyBuffer( propertyBuffer.Get() );
}
PropertyBuffer::PropertyBuffer()
* @param[in] size The number of elements in the property buffer
* @return Handle to a newly allocated PropertyBuffer
*/
- static PropertyBuffer New( Type type, Dali::Property::Map bufferFormat, std::size_t size );
+ static PropertyBuffer New( Type type, Dali::Property::Map& bufferFormat, std::size_t size );
/**
* @brief Default constructor, creates an empty handle