2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/event/common/property-buffer-impl.h> // Dali::Internal::PropertyBuffer
22 #include <algorithm> // std::sort
25 #include <dali/devel-api/object/property-buffer.h> // Dali::Internal::PropertyBuffer
26 #include <dali/internal/event/common/stage-impl.h>
27 #include <dali/internal/update/manager/update-manager.h>
38 * Calculate the alignment requirements of a type
40 * This is used to calculate the memory alignment requirements of a type
41 * It creates a structure with a dummy char and a member of the type we want to check
42 * this will cause the second member to be aligned by it's alignment requirement.
44 template<Property::Type type>
45 struct PropertyImplementationTypeAlignment
47 // Create a structure that forces alignment of the data type
50 char oneChar; ///< Member with sizeof() == 1
51 typename PropertyImplementationType<type>::Type data;
53 enum { VALUE = offsetof( TestStructure, data ) };
56 unsigned int GetPropertyImplementationAlignment( Property::Type& propertyType )
58 unsigned int alignment = 0u;
60 switch( propertyType )
63 case Property::STRING:
67 DALI_ASSERT_ALWAYS( false && "No size for properties with no type, or dynamic sizes" );
70 case Property::BOOLEAN:
72 alignment = PropertyImplementationTypeAlignment< Property::BOOLEAN >::VALUE;
75 case Property::INTEGER:
77 alignment = PropertyImplementationTypeAlignment< Property::INTEGER >::VALUE;
82 alignment = PropertyImplementationTypeAlignment< Property::FLOAT >::VALUE;
85 case Property::VECTOR2:
87 alignment = PropertyImplementationTypeAlignment< Property::VECTOR2 >::VALUE;
90 case Property::VECTOR3:
92 alignment = PropertyImplementationTypeAlignment< Property::VECTOR3 >::VALUE;
95 case Property::VECTOR4:
97 alignment = PropertyImplementationTypeAlignment< Property::VECTOR4 >::VALUE;
100 case Property::MATRIX3:
102 alignment = PropertyImplementationTypeAlignment< Property::MATRIX3 >::VALUE;
105 case Property::MATRIX:
107 alignment = PropertyImplementationTypeAlignment< Property::MATRIX >::VALUE;
110 case Property::RECTANGLE:
112 alignment = PropertyImplementationTypeAlignment< Property::RECTANGLE >::VALUE;
115 case Property::ROTATION:
117 alignment = PropertyImplementationTypeAlignment< Property::ROTATION >::VALUE;
125 } // unnamed namespace
127 PropertyBufferPtr PropertyBuffer::New()
129 PropertyBufferPtr propertyBuffer( new PropertyBuffer() );
130 propertyBuffer->Initialize();
132 return propertyBuffer;
135 void PropertyBuffer::SetSize( std::size_t size )
141 SceneGraph::SetPropertyBufferSize(mEventThreadServices.GetUpdateManager(),*mRenderObject, mSize );
144 std::size_t PropertyBuffer::GetSize() const
149 void PropertyBuffer::SetData( const void* data )
151 DALI_ASSERT_DEBUG( mFormat.Count() && "Format must be set before setting the data." );
153 DALI_ASSERT_ALWAYS( mSize && "Size of the buffer must be set before setting the data." );
155 const char* source = static_cast<const char*>( data );
156 std::copy( source, source + mBuffer.Size(), &mBuffer[0] );
158 SceneGraph::SetPropertyBufferData(mEventThreadServices.GetUpdateManager(),*mRenderObject,new Dali::Vector<char>( mBuffer ));
161 void PropertyBuffer::SetFormat( Dali::Property::Map& format )
163 DALI_ASSERT_ALWAYS( format.Count() && "Format cannot be empty." );
165 DALI_ASSERT_DEBUG( 0 == mFormat.Count() && "Format of property buffer can only be set once." );
172 const Render::PropertyBuffer* PropertyBuffer::GetRenderObject() const
174 return mRenderObject;
177 PropertyBuffer::~PropertyBuffer()
179 if( EventThreadServices::IsCoreRunning() && mRenderObject)
181 SceneGraph::RemovePropertyBuffer( mEventThreadServices.GetUpdateManager(), *mRenderObject );
185 PropertyBuffer::PropertyBuffer()
186 :mEventThreadServices( *Stage::GetCurrent() )
188 ,mBufferFormat( NULL )
193 void PropertyBuffer::Initialize()
195 mRenderObject = new Render::PropertyBuffer();
196 SceneGraph::AddPropertyBuffer(mEventThreadServices.GetUpdateManager(), *mRenderObject );
199 void PropertyBuffer::FormatChanged()
201 size_t numComponents = mFormat.Count();
204 DALI_ASSERT_DEBUG( mBufferFormat == NULL && "PropertyFormat should not be set yet" );
205 Render::PropertyBuffer::Format* format = new Render::PropertyBuffer::Format();
206 format->components.resize( numComponents );
208 unsigned int currentAlignment = 0u;
209 unsigned int maxAlignmentRequired = 0u;
211 for( size_t i = 0u; i < numComponents; ++i )
213 StringValuePair component = mFormat.GetPair( i );
216 format->components[i].name = component.first;
218 // enums are stored in the map as int
219 Property::Type type = Property::Type( component.second.Get<int>() );
221 // Get the size and alignment
222 unsigned int elementSize = GetPropertyImplementationSize( type );
223 unsigned int elementAlignment = GetPropertyImplementationAlignment( type );
225 // check if current alignment is compatible with new member
226 if( unsigned int offset = currentAlignment % elementAlignment )
228 // Not compatible, realign
229 currentAlignment = currentAlignment + elementSize - offset;
232 // write to the format
233 format->components[i].size = elementSize;
234 format->components[i].offset = currentAlignment;
235 format->components[i].type = type;
238 currentAlignment += elementSize;
240 // update max alignment requirement
241 if( elementAlignment > maxAlignmentRequired )
243 maxAlignmentRequired = elementAlignment;
248 // Check the alignment for the maxAlignment required to calculate the size of the format
249 if( maxAlignmentRequired != 0 )
251 if( unsigned int offset = currentAlignment % maxAlignmentRequired )
253 // Not compatible, realign
254 currentAlignment = currentAlignment + maxAlignmentRequired - offset;
258 // Set the format size
259 format->size = currentAlignment;
261 mBufferFormat = format;
263 SceneGraph::SetPropertyBufferFormat(mEventThreadServices.GetUpdateManager(), *mRenderObject, format );
270 void PropertyBuffer::SizeChanged()
272 // Check if format and size have been set yet
273 if( mBufferFormat != NULL )
275 unsigned int bufferSize = mBufferFormat->size * mSize;
276 mBuffer.Resize( bufferSize );
280 unsigned int GetPropertyImplementationSize( Property::Type& propertyType )
282 unsigned int size = 0u;
284 switch( propertyType )
287 case Property::STRING:
288 case Property::ARRAY:
291 DALI_ASSERT_ALWAYS( "No size for properties with no type, or dynamic sizes" );
294 case Property::BOOLEAN:
296 size = sizeof( PropertyImplementationType< Property::BOOLEAN >::Type );
299 case Property::INTEGER:
301 size = sizeof( PropertyImplementationType< Property::INTEGER >::Type );
304 case Property::FLOAT:
306 size = sizeof( PropertyImplementationType< Property::FLOAT >::Type );
309 case Property::VECTOR2:
311 size = sizeof( PropertyImplementationType< Property::VECTOR2 >::Type );
314 case Property::VECTOR3:
316 size = sizeof( PropertyImplementationType< Property::VECTOR3 >::Type );
319 case Property::VECTOR4:
321 size = sizeof( PropertyImplementationType< Property::VECTOR4 >::Type );
324 case Property::MATRIX3:
326 size = sizeof( PropertyImplementationType< Property::MATRIX3 >::Type );
329 case Property::MATRIX:
331 size = sizeof( PropertyImplementationType< Property::MATRIX >::Type );
334 case Property::RECTANGLE:
336 size = sizeof( PropertyImplementationType< Property::RECTANGLE >::Type );
339 case Property::ROTATION:
341 size = sizeof( PropertyImplementationType< Property::ROTATION >::Type );
350 } // namespace Internal