Merge "Fix VD prevent issues - DIVIDE_BY_ZERO" into devel/master
[platform/core/uifw/dali-core.git] / dali / internal / event / common / property-buffer-impl.cpp
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/event/common/property-buffer-impl.h>  // Dali::Internal::PropertyBuffer
20
21 // EXTERNAL INCLUDE
22 #include <algorithm> // std::sort
23
24 // INTERNAL INCLUDES
25 #include <dali/public-api/object/type-registry.h>
26 #include <dali/devel-api/object/property-buffer.h> // Dali::Internal::PropertyBuffer
27
28 #include <dali/internal/event/common/object-impl-helper.h> // Dali::Internal::ObjectHelper
29 #include <dali/internal/event/common/property-helper.h> // DALI_PROPERTY_TABLE_BEGIN, DALI_PROPERTY, DALI_PROPERTY_TABLE_END
30 #include <dali/internal/update/common/scene-graph-property-buffer.h>
31 #include <dali/internal/update/manager/update-manager.h>
32
33 namespace Dali
34 {
35 namespace Internal
36 {
37
38 using SceneGraph::PropertyBufferMetadata::Format;
39 using SceneGraph::PropertyBufferMetadata::Component;
40
41 namespace
42 {
43
44 /**
45  *            |name    |type             |writable|animatable|constraint-input|enum for index-checking|
46  */
47 DALI_PROPERTY_TABLE_BEGIN
48 DALI_PROPERTY( "size",          INTEGER, true,  false, true,   Dali::PropertyBuffer::Property::SIZE )
49 DALI_PROPERTY( "buffer-format", MAP,     false, false, false,  Dali::PropertyBuffer::Property::BUFFER_FORMAT )
50 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
51
52 const ObjectImplHelper<DEFAULT_PROPERTY_COUNT> PROPERTY_BUFFER_IMPL = { DEFAULT_PROPERTY_DETAILS };
53
54 BaseHandle Create()
55 {
56   return Dali::BaseHandle();
57 }
58
59 TypeRegistration mType( typeid( Dali::PropertyBuffer ), typeid( Dali::Handle ), Create );
60
61 /**
62  * Calculate the alignment requirements of a type
63  *
64  * This is used to calculate the memory alignment requirements of a type
65  * It creates a structure with a dummy char and a member of the type we want to check
66  * this will cause the second member to be aligned by it's alignment requirement.
67  */
68 template<Property::Type type>
69 struct PropertyImplementationTypeAlignment
70 {
71   // Create a structure that forces alignment of the data type
72   struct TestStructure
73   {
74     char oneChar;  ///< Member with sizeof() == 1
75     typename PropertyImplementationType<type>::Type data;
76   };
77   enum { VALUE = offsetof( TestStructure, data ) };
78 };
79
80 unsigned int GetPropertyImplementationAlignment( Property::Type& propertyType )
81 {
82   unsigned int alignment = 0u;
83
84   switch( propertyType )
85   {
86     case Property::NONE:
87     case Property::STRING:
88     case Property::ARRAY:
89     case Property::MAP:
90     {
91       DALI_ASSERT_ALWAYS( false && "No size for properties with no type, or dynamic sizes" );
92       break;
93     }
94     case Property::BOOLEAN:
95     {
96       alignment = PropertyImplementationTypeAlignment< Property::BOOLEAN >::VALUE;
97       break;
98     }
99     case Property::INTEGER:
100     {
101       alignment = PropertyImplementationTypeAlignment< Property::INTEGER >::VALUE;
102       break;
103     }
104     case Property::FLOAT:
105     {
106       alignment = PropertyImplementationTypeAlignment< Property::FLOAT >::VALUE;
107       break;
108     }
109     case Property::VECTOR2:
110     {
111       alignment = PropertyImplementationTypeAlignment< Property::VECTOR2 >::VALUE;
112       break;
113     }
114     case Property::VECTOR3:
115     {
116       alignment = PropertyImplementationTypeAlignment< Property::VECTOR3 >::VALUE;
117       break;
118     }
119     case Property::VECTOR4:
120     {
121       alignment = PropertyImplementationTypeAlignment< Property::VECTOR4 >::VALUE;
122       break;
123     }
124     case Property::MATRIX3:
125     {
126       alignment = PropertyImplementationTypeAlignment< Property::MATRIX3 >::VALUE;
127       break;
128     }
129     case Property::MATRIX:
130     {
131       alignment = PropertyImplementationTypeAlignment< Property::MATRIX >::VALUE;
132       break;
133     }
134     case Property::RECTANGLE:
135     {
136       alignment = PropertyImplementationTypeAlignment< Property::RECTANGLE >::VALUE;
137       break;
138     }
139     case Property::ROTATION:
140     {
141       alignment = PropertyImplementationTypeAlignment< Property::ROTATION >::VALUE;
142       break;
143     }
144   }
145
146   return alignment;
147 }
148
149 } // unnamed namespace
150
151 PropertyBufferPtr PropertyBuffer::New()
152 {
153   PropertyBufferPtr propertyBuffer( new PropertyBuffer() );
154   propertyBuffer->Initialize();
155
156   return propertyBuffer;
157 }
158
159 void PropertyBuffer::SetSize( std::size_t size )
160 {
161   mSize = size;
162
163   SizeChanged();
164
165   SceneGraph::SetSizeMessage( GetEventThreadServices(),
166                               *mSceneObject,
167                               mSize );
168 }
169
170 std::size_t PropertyBuffer::GetSize() const
171 {
172   return mSize;
173 }
174
175 void PropertyBuffer::SetData( const void* data )
176 {
177   DALI_ASSERT_DEBUG( mFormat.Count() && "Format must be set before setting the data." );
178
179   DALI_ASSERT_ALWAYS( mSize && "Size of the buffer must be set before setting the data." );
180
181   const char* source = static_cast<const char*>( data );
182   std::copy( source, source + mBuffer.Size(), &mBuffer[0] );
183
184   SceneGraph::SetDataMessage( GetEventThreadServices(),
185                               *mSceneObject,
186                               new SceneGraph::PropertyBuffer::BufferType( mBuffer ) );
187 }
188
189 const SceneGraph::PropertyBuffer* PropertyBuffer::GetPropertyBufferSceneObject() const
190 {
191   return mSceneObject;
192 }
193
194 void PropertyBuffer::SetFormat( Dali::Property::Map& format )
195 {
196   DALI_ASSERT_ALWAYS( format.Count() && "Format cannot be empty." );
197
198   DALI_ASSERT_DEBUG( 0 == mFormat.Count() && "Format of property buffer can only be set once." );
199
200   mFormat = format;
201
202   FormatChanged();
203 }
204
205 unsigned int PropertyBuffer::GetDefaultPropertyCount() const
206 {
207   return PROPERTY_BUFFER_IMPL.GetDefaultPropertyCount();
208 }
209
210 void PropertyBuffer::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
211 {
212   PROPERTY_BUFFER_IMPL.GetDefaultPropertyIndices( indices );
213 }
214
215 const char* PropertyBuffer::GetDefaultPropertyName(Property::Index index) const
216 {
217   return PROPERTY_BUFFER_IMPL.GetDefaultPropertyName( index );
218 }
219
220 Property::Index PropertyBuffer::GetDefaultPropertyIndex( const std::string& name ) const
221 {
222   return PROPERTY_BUFFER_IMPL.GetDefaultPropertyIndex( name );
223 }
224
225 bool PropertyBuffer::IsDefaultPropertyWritable( Property::Index index ) const
226 {
227   return PROPERTY_BUFFER_IMPL.IsDefaultPropertyWritable( index );
228 }
229
230 bool PropertyBuffer::IsDefaultPropertyAnimatable( Property::Index index ) const
231 {
232   return PROPERTY_BUFFER_IMPL.IsDefaultPropertyAnimatable( index );
233 }
234
235 bool PropertyBuffer::IsDefaultPropertyAConstraintInput( Property::Index index ) const
236 {
237   return PROPERTY_BUFFER_IMPL.IsDefaultPropertyAConstraintInput( index );
238 }
239
240 Property::Type PropertyBuffer::GetDefaultPropertyType( Property::Index index ) const
241 {
242   return PROPERTY_BUFFER_IMPL.GetDefaultPropertyType( index );
243 }
244
245 void PropertyBuffer::SetDefaultProperty( Property::Index index,
246                                          const Property::Value& propertyValue )
247 {
248   switch( index )
249   {
250     case Dali::PropertyBuffer::Property::SIZE:
251     {
252       SetSize( propertyValue.Get<int>() );
253       break;
254     }
255     case Dali::PropertyBuffer::Property::BUFFER_FORMAT:
256     {
257       DALI_ASSERT_ALWAYS( 0 && "MESH_REWORK" );
258       break;
259     }
260   }
261 }
262
263 void PropertyBuffer::SetSceneGraphProperty( Property::Index index,
264                                             const PropertyMetadata& entry,
265                                             const Property::Value& value )
266 {
267   PROPERTY_BUFFER_IMPL.SetSceneGraphProperty( GetEventThreadServices(), this, index, entry, value );
268 }
269
270 Property::Value PropertyBuffer::GetDefaultProperty( Property::Index index ) const
271 {
272   Property::Value value;
273
274   switch( index )
275   {
276     case Dali::PropertyBuffer::Property::SIZE:
277     {
278       value = static_cast<int>( GetSize() );
279       break;
280     }
281     case Dali::PropertyBuffer::Property::BUFFER_FORMAT:
282     {
283       DALI_ASSERT_ALWAYS( 0 && "MESH_REWORK" );
284       break;
285     }
286   }
287   return value;
288 }
289
290 const SceneGraph::PropertyOwner* PropertyBuffer::GetPropertyOwner() const
291 {
292   return mSceneObject;
293 }
294
295 const SceneGraph::PropertyOwner* PropertyBuffer::GetSceneObject() const
296 {
297   return mSceneObject;
298 }
299
300 const SceneGraph::PropertyBase* PropertyBuffer::GetSceneObjectAnimatableProperty( Property::Index index ) const
301 {
302   DALI_ASSERT_ALWAYS( IsPropertyAnimatable(index) && "Property is not animatable" );
303   const SceneGraph::PropertyBase* property = NULL;
304
305   if( OnStage() )
306   {
307     property = PROPERTY_BUFFER_IMPL.GetRegisteredSceneGraphProperty(
308       this,
309       &PropertyBuffer::FindAnimatableProperty,
310       &PropertyBuffer::FindCustomProperty,
311       index );
312
313     if( property == NULL && index < DEFAULT_PROPERTY_MAX_COUNT )
314     {
315       DALI_ASSERT_ALWAYS( 0 && "Property is not animatable" );
316     }
317   }
318
319   return property;
320 }
321
322 const PropertyInputImpl* PropertyBuffer::GetSceneObjectInputProperty( Property::Index index ) const
323 {
324   const PropertyInputImpl* property = NULL;
325
326   if( OnStage() )
327   {
328     const SceneGraph::PropertyBase* baseProperty =
329       PROPERTY_BUFFER_IMPL.GetRegisteredSceneGraphProperty( this,
330                                                             &PropertyBuffer::FindAnimatableProperty,
331                                                             &PropertyBuffer::FindCustomProperty,
332                                                             index );
333     property = static_cast<const PropertyInputImpl*>( baseProperty );
334
335     if( property == NULL && index < DEFAULT_PROPERTY_MAX_COUNT )
336     {
337       if( index == Dali::PropertyBuffer::Property::SIZE )
338       {
339         // @todo MESH_REWORK
340         DALI_ASSERT_ALWAYS( 0 && "MESH_REWORK" );
341       }
342     }
343   }
344
345   return property;
346 }
347
348 int PropertyBuffer::GetPropertyComponentIndex( Property::Index index ) const
349 {
350   return Property::INVALID_COMPONENT_INDEX;
351 }
352
353 bool PropertyBuffer::OnStage() const
354 {
355   return mOnStage;
356 }
357
358 void PropertyBuffer::Connect()
359 {
360   mOnStage = true;
361 }
362
363 void PropertyBuffer::Disconnect()
364 {
365   mOnStage = false;
366 }
367
368 PropertyBuffer::~PropertyBuffer()
369 {
370   if( EventThreadServices::IsCoreRunning() )
371   {
372     EventThreadServices& eventThreadServices = GetEventThreadServices();
373     SceneGraph::UpdateManager& updateManager = eventThreadServices.GetUpdateManager();
374     RemoveMessage( updateManager, updateManager.GetPropertyBufferOwner(), *mSceneObject );
375
376     eventThreadServices.UnregisterObject( this );
377   }
378 }
379
380 PropertyBuffer::PropertyBuffer()
381 : mSceneObject( NULL ),
382   mBufferFormat( NULL ),
383   mSize( 0 ),
384   mOnStage( false )
385 {
386 }
387
388 void PropertyBuffer::Initialize()
389 {
390   EventThreadServices& eventThreadServices = GetEventThreadServices();
391   SceneGraph::UpdateManager& updateManager = eventThreadServices.GetUpdateManager();
392
393   mSceneObject = new SceneGraph::PropertyBuffer();
394   AddMessage( updateManager, updateManager.GetPropertyBufferOwner(), *mSceneObject );
395
396   eventThreadServices.RegisterObject( this );
397 }
398
399 void PropertyBuffer::FormatChanged()
400 {
401   size_t numComponents = mFormat.Count();
402
403   // Create the format
404   DALI_ASSERT_DEBUG( mBufferFormat == NULL && "PropertyFormat should not be set yet" );
405   Format* bufferFormat = new Format();
406   bufferFormat->components.resize( numComponents );
407
408   unsigned int currentAlignment = 0u;
409   unsigned int maxAlignmentRequired = 0u;
410
411   for( size_t i = 0u; i < numComponents; ++i )
412   {
413     StringValuePair component = mFormat.GetPair( i );
414
415     // Get the name
416     bufferFormat->components[i].name = component.first;
417
418     // enums are stored in the map as int
419     Property::Type type = Property::Type( component.second.Get<int>() );
420
421     // Get the size and alignment
422     unsigned int elementSize = GetPropertyImplementationSize( type );
423     unsigned int elementAlignment = GetPropertyImplementationAlignment( type );
424
425     // check if current alignment is compatible with new member
426     if( unsigned int offset = currentAlignment % elementAlignment )
427     {
428       // Not compatible, realign
429       currentAlignment = currentAlignment + elementSize - offset;
430     }
431
432     // write to the format
433     bufferFormat->components[i].size = elementSize;
434     bufferFormat->components[i].offset = currentAlignment;
435     bufferFormat->components[i].type = type;
436
437     // update offset
438     currentAlignment += elementSize;
439
440     // update max alignment requirement
441     if( elementAlignment > maxAlignmentRequired )
442     {
443       maxAlignmentRequired = elementAlignment;
444     }
445
446   }
447
448   // Check the alignment for the maxAlignment required to calculate the size of the format
449   if( maxAlignmentRequired != 0 )
450   {
451     if( unsigned int offset = currentAlignment % maxAlignmentRequired )
452     {
453       // Not compatible, realign
454       currentAlignment = currentAlignment + maxAlignmentRequired - offset;
455     }
456   }
457
458   // Set the format size
459   bufferFormat->size = currentAlignment;
460
461   mBufferFormat = bufferFormat;
462
463   SceneGraph::SetFormatMessage( GetEventThreadServices(),
464                                 *mSceneObject,
465                                 bufferFormat );
466
467   if( mSize )
468   {
469     SizeChanged();
470   }
471 }
472
473 void PropertyBuffer::SizeChanged()
474 {
475   // Check if format and size have been set yet
476   if( mBufferFormat != NULL )
477   {
478     unsigned int bufferSize = mBufferFormat->size * mSize;
479     mBuffer.Resize( bufferSize );
480   }
481 }
482
483 unsigned int GetPropertyImplementationSize( Property::Type& propertyType )
484 {
485   unsigned int size = 0u;
486
487   switch( propertyType )
488   {
489     case Property::NONE:
490     case Property::STRING:
491     case Property::ARRAY:
492     case Property::MAP:
493     {
494       DALI_ASSERT_ALWAYS( "No size for properties with no type, or dynamic sizes" );
495       break;
496     }
497     case Property::BOOLEAN:
498     {
499       size = sizeof( PropertyImplementationType< Property::BOOLEAN >::Type );
500       break;
501     }
502     case Property::INTEGER:
503     {
504       size = sizeof( PropertyImplementationType< Property::INTEGER >::Type );
505       break;
506     }
507     case Property::FLOAT:
508     {
509       size = sizeof( PropertyImplementationType< Property::FLOAT >::Type );
510       break;
511     }
512     case Property::VECTOR2:
513     {
514       size = sizeof( PropertyImplementationType< Property::VECTOR2 >::Type );
515       break;
516     }
517     case Property::VECTOR3:
518     {
519       size = sizeof( PropertyImplementationType< Property::VECTOR3 >::Type );
520       break;
521     }
522     case Property::VECTOR4:
523     {
524       size = sizeof( PropertyImplementationType< Property::VECTOR4 >::Type );
525       break;
526     }
527     case Property::MATRIX3:
528     {
529       size = sizeof( PropertyImplementationType< Property::MATRIX3 >::Type );
530       break;
531     }
532     case Property::MATRIX:
533     {
534       size = sizeof( PropertyImplementationType< Property::MATRIX >::Type );
535       break;
536     }
537     case Property::RECTANGLE:
538     {
539       size = sizeof( PropertyImplementationType< Property::RECTANGLE >::Type );
540       break;
541     }
542     case Property::ROTATION:
543     {
544       size = sizeof( PropertyImplementationType< Property::ROTATION >::Type );
545       break;
546     }
547   }
548
549   return size;
550 }
551
552
553 } // namespace Internal
554 } // namespace Dali