Merge branch 'devel/master' into devel/new_mesh
[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",          UNSIGNED_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( "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::UNSIGNED_INTEGER:
105     {
106       alignment = PropertyImplementationTypeAlignment< Property::UNSIGNED_INTEGER >::VALUE;
107       break;
108     }
109     case Property::FLOAT:
110     {
111       alignment = PropertyImplementationTypeAlignment< Property::FLOAT >::VALUE;
112       break;
113     }
114     case Property::VECTOR2:
115     {
116       alignment = PropertyImplementationTypeAlignment< Property::VECTOR2 >::VALUE;
117       break;
118     }
119     case Property::VECTOR3:
120     {
121       alignment = PropertyImplementationTypeAlignment< Property::VECTOR3 >::VALUE;
122       break;
123     }
124     case Property::VECTOR4:
125     {
126       alignment = PropertyImplementationTypeAlignment< Property::VECTOR4 >::VALUE;
127       break;
128     }
129     case Property::MATRIX3:
130     {
131       alignment = PropertyImplementationTypeAlignment< Property::MATRIX3 >::VALUE;
132       break;
133     }
134     case Property::MATRIX:
135     {
136       alignment = PropertyImplementationTypeAlignment< Property::MATRIX >::VALUE;
137       break;
138     }
139     case Property::RECTANGLE:
140     {
141       alignment = PropertyImplementationTypeAlignment< Property::RECTANGLE >::VALUE;
142       break;
143     }
144     case Property::ROTATION:
145     {
146       alignment = PropertyImplementationTypeAlignment< Property::ROTATION >::VALUE;
147       break;
148     }
149   }
150
151   return alignment;
152 }
153
154 } // unnamed namespace
155
156 PropertyBufferPtr PropertyBuffer::New()
157 {
158   PropertyBufferPtr propertyBuffer( new PropertyBuffer() );
159   propertyBuffer->Initialize();
160
161   return propertyBuffer;
162 }
163
164 void PropertyBuffer::SetSize( std::size_t size )
165 {
166   mSize = size;
167
168   SizeChanged();
169
170   SceneGraph::SetSizeMessage( GetEventThreadServices(),
171                               *mSceneObject,
172                               mSize );
173 }
174
175 std::size_t PropertyBuffer::GetSize() const
176 {
177   return mSize;
178 }
179
180 void PropertyBuffer::SetData( const void* data )
181 {
182   DALI_ASSERT_DEBUG( mFormat.Count() && "Format must be set before setting the data." );
183
184   DALI_ASSERT_ALWAYS( mSize && "Size of the buffer must be set before setting the data." );
185
186   const char* source = static_cast<const char*>( data );
187   std::copy( source, source + mBuffer.Size(), &mBuffer[0] );
188
189   SceneGraph::SetDataMessage( GetEventThreadServices(),
190                               *mSceneObject,
191                               new SceneGraph::PropertyBuffer::BufferType( mBuffer ) );
192 }
193
194 const SceneGraph::PropertyBuffer* PropertyBuffer::GetPropertyBufferSceneObject() const
195 {
196   return mSceneObject;
197 }
198
199 void PropertyBuffer::SetFormat( Dali::Property::Map& format )
200 {
201   DALI_ASSERT_ALWAYS( format.Count() && "Format cannot be empty." );
202
203   DALI_ASSERT_DEBUG( 0 == mFormat.Count() && "Format of property buffer can only be set once." );
204
205   mFormat = format;
206
207   FormatChanged();
208 }
209
210 unsigned int PropertyBuffer::GetDefaultPropertyCount() const
211 {
212   return PROPERTY_BUFFER_IMPL.GetDefaultPropertyCount();
213 }
214
215 void PropertyBuffer::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
216 {
217   PROPERTY_BUFFER_IMPL.GetDefaultPropertyIndices( indices );
218 }
219
220 const char* PropertyBuffer::GetDefaultPropertyName(Property::Index index) const
221 {
222   return PROPERTY_BUFFER_IMPL.GetDefaultPropertyName( index );
223 }
224
225 Property::Index PropertyBuffer::GetDefaultPropertyIndex( const std::string& name ) const
226 {
227   return PROPERTY_BUFFER_IMPL.GetDefaultPropertyIndex( name );
228 }
229
230 bool PropertyBuffer::IsDefaultPropertyWritable( Property::Index index ) const
231 {
232   return PROPERTY_BUFFER_IMPL.IsDefaultPropertyWritable( index );
233 }
234
235 bool PropertyBuffer::IsDefaultPropertyAnimatable( Property::Index index ) const
236 {
237   return PROPERTY_BUFFER_IMPL.IsDefaultPropertyAnimatable( index );
238 }
239
240 bool PropertyBuffer::IsDefaultPropertyAConstraintInput( Property::Index index ) const
241 {
242   return PROPERTY_BUFFER_IMPL.IsDefaultPropertyAConstraintInput( index );
243 }
244
245 Property::Type PropertyBuffer::GetDefaultPropertyType( Property::Index index ) const
246 {
247   return PROPERTY_BUFFER_IMPL.GetDefaultPropertyType( index );
248 }
249
250 void PropertyBuffer::SetDefaultProperty( Property::Index index,
251                                          const Property::Value& propertyValue )
252 {
253   switch( index )
254   {
255     case Dali::PropertyBuffer::Property::SIZE:
256     {
257       SetSize( propertyValue.Get<unsigned int>() );
258       break;
259     }
260     case Dali::PropertyBuffer::Property::BUFFER_FORMAT:
261     {
262       DALI_ASSERT_ALWAYS( 0 && "MESH_REWORK" );
263       break;
264     }
265   }
266 }
267
268 void PropertyBuffer::SetSceneGraphProperty( Property::Index index,
269                                             const PropertyMetadata& entry,
270                                             const Property::Value& value )
271 {
272   PROPERTY_BUFFER_IMPL.SetSceneGraphProperty( GetEventThreadServices(), this, index, entry, value );
273 }
274
275 Property::Value PropertyBuffer::GetDefaultProperty( Property::Index index ) const
276 {
277   Property::Value value;
278
279   switch( index )
280   {
281     case Dali::PropertyBuffer::Property::SIZE:
282     {
283       value = static_cast<unsigned int>( GetSize() ); // @todo MESH_REWORK Add a size_t type to PropertyValue
284       break;
285     }
286     case Dali::PropertyBuffer::Property::BUFFER_FORMAT:
287     {
288       DALI_ASSERT_ALWAYS( 0 && "MESH_REWORK" );
289       break;
290     }
291   }
292   return value;
293 }
294
295 const SceneGraph::PropertyOwner* PropertyBuffer::GetPropertyOwner() const
296 {
297   return mSceneObject;
298 }
299
300 const SceneGraph::PropertyOwner* PropertyBuffer::GetSceneObject() const
301 {
302   return mSceneObject;
303 }
304
305 const SceneGraph::PropertyBase* PropertyBuffer::GetSceneObjectAnimatableProperty( Property::Index index ) const
306 {
307   DALI_ASSERT_ALWAYS( IsPropertyAnimatable(index) && "Property is not animatable" );
308   const SceneGraph::PropertyBase* property = NULL;
309
310   if( OnStage() )
311   {
312     property = PROPERTY_BUFFER_IMPL.GetRegisteredSceneGraphProperty(
313       this,
314       &PropertyBuffer::FindAnimatableProperty,
315       &PropertyBuffer::FindCustomProperty,
316       index );
317
318     if( property == NULL && index < DEFAULT_PROPERTY_MAX_COUNT )
319     {
320       DALI_ASSERT_ALWAYS( 0 && "Property is not animatable" );
321     }
322   }
323
324   return property;
325 }
326
327 const PropertyInputImpl* PropertyBuffer::GetSceneObjectInputProperty( Property::Index index ) const
328 {
329   const PropertyInputImpl* property = NULL;
330
331   if( OnStage() )
332   {
333     const SceneGraph::PropertyBase* baseProperty =
334       PROPERTY_BUFFER_IMPL.GetRegisteredSceneGraphProperty( this,
335                                                             &PropertyBuffer::FindAnimatableProperty,
336                                                             &PropertyBuffer::FindCustomProperty,
337                                                             index );
338     property = static_cast<const PropertyInputImpl*>( baseProperty );
339
340     if( property == NULL && index < DEFAULT_PROPERTY_MAX_COUNT )
341     {
342       if( index == Dali::PropertyBuffer::Property::SIZE )
343       {
344         // @todo MESH_REWORK
345         DALI_ASSERT_ALWAYS( 0 && "MESH_REWORK" );
346       }
347     }
348   }
349
350   return property;
351 }
352
353 int PropertyBuffer::GetPropertyComponentIndex( Property::Index index ) const
354 {
355   return Property::INVALID_COMPONENT_INDEX;
356 }
357
358 bool PropertyBuffer::OnStage() const
359 {
360   return mOnStage;
361 }
362
363 void PropertyBuffer::Connect()
364 {
365   mOnStage = true;
366 }
367
368 void PropertyBuffer::Disconnect()
369 {
370   mOnStage = false;
371 }
372
373 PropertyBuffer::~PropertyBuffer()
374 {
375   if( EventThreadServices::IsCoreRunning() )
376   {
377     EventThreadServices& eventThreadServices = GetEventThreadServices();
378     SceneGraph::UpdateManager& updateManager = eventThreadServices.GetUpdateManager();
379     RemoveMessage( updateManager, updateManager.GetPropertyBufferOwner(), *mSceneObject );
380
381     eventThreadServices.UnregisterObject( this );
382   }
383 }
384
385 PropertyBuffer::PropertyBuffer()
386 : mSceneObject( NULL ),
387   mBufferFormat( NULL ),
388   mSize( 0 ),
389   mOnStage( false )
390 {
391 }
392
393 void PropertyBuffer::Initialize()
394 {
395   EventThreadServices& eventThreadServices = GetEventThreadServices();
396   SceneGraph::UpdateManager& updateManager = eventThreadServices.GetUpdateManager();
397
398   mSceneObject = new SceneGraph::PropertyBuffer();
399   AddMessage( updateManager, updateManager.GetPropertyBufferOwner(), *mSceneObject );
400
401   eventThreadServices.RegisterObject( this );
402 }
403
404 void PropertyBuffer::FormatChanged()
405 {
406   size_t numComponents = mFormat.Count();
407
408   // Create the format
409   DALI_ASSERT_DEBUG( mBufferFormat == NULL && "PropertyFormat should not be set yet" );
410   Format* bufferFormat = new Format();
411   bufferFormat->components.resize( numComponents );
412
413   unsigned int currentAlignment = 0u;
414   unsigned int maxAlignmentRequired = 0u;
415
416   for( size_t i = 0u; i < numComponents; ++i )
417   {
418     StringValuePair component = mFormat.GetPair( i );
419
420     // Get the name
421     bufferFormat->components[i].name = component.first;
422
423     // enums are stored in the map as int
424     Property::Type type = Property::Type( component.second.Get<int>() );
425
426     // Get the size and alignment
427     unsigned int elementSize = GetPropertyImplementationSize( type );
428     unsigned int elementAlignment = GetPropertyImplementationAlignment( type );
429
430     // check if current alignment is compatible with new member
431     if( unsigned int offset = currentAlignment % elementAlignment )
432     {
433       // Not compatible, realign
434       currentAlignment = currentAlignment + elementSize - offset;
435     }
436
437     // write to the format
438     bufferFormat->components[i].size = elementSize;
439     bufferFormat->components[i].offset = currentAlignment;
440     bufferFormat->components[i].type = type;
441
442     // update offset
443     currentAlignment += elementSize;
444
445     // update max alignment requirement
446     if( elementAlignment > maxAlignmentRequired )
447     {
448       maxAlignmentRequired = elementAlignment;
449     }
450
451   }
452
453   // Check the alignment for the maxAlignment required to calculate the size of the format
454   if( unsigned int offset = currentAlignment % maxAlignmentRequired )
455   {
456     // Not compatible, realign
457     currentAlignment = currentAlignment + maxAlignmentRequired - offset;
458   }
459
460   // Set the format size
461   bufferFormat->size = currentAlignment;
462
463   mBufferFormat = bufferFormat;
464
465   SceneGraph::SetFormatMessage( GetEventThreadServices(),
466                                 *mSceneObject,
467                                 bufferFormat );
468
469   if( mSize )
470   {
471     SizeChanged();
472   }
473 }
474
475 void PropertyBuffer::SizeChanged()
476 {
477   // Check if format and size have been set yet
478   if( mBufferFormat != NULL )
479   {
480     unsigned int bufferSize = mBufferFormat->size * mSize;
481     mBuffer.Resize( bufferSize );
482   }
483 }
484
485 unsigned int GetPropertyImplementationSize( Property::Type& propertyType )
486 {
487   unsigned int size = 0u;
488
489   switch( propertyType )
490   {
491     case Property::NONE:
492     case Property::STRING:
493     case Property::ARRAY:
494     case Property::MAP:
495     {
496       DALI_ASSERT_ALWAYS( "No size for properties with no type, or dynamic sizes" );
497       break;
498     }
499     case Property::BOOLEAN:
500     {
501       size = sizeof( PropertyImplementationType< Property::BOOLEAN >::Type );
502       break;
503     }
504     case Property::INTEGER:
505     {
506       size = sizeof( PropertyImplementationType< Property::INTEGER >::Type );
507       break;
508     }
509     case Property::UNSIGNED_INTEGER:
510     {
511       size = sizeof( PropertyImplementationType< Property::UNSIGNED_INTEGER >::Type );
512       break;
513     }
514     case Property::FLOAT:
515     {
516       size = sizeof( PropertyImplementationType< Property::FLOAT >::Type );
517       break;
518     }
519     case Property::VECTOR2:
520     {
521       size = sizeof( PropertyImplementationType< Property::VECTOR2 >::Type );
522       break;
523     }
524     case Property::VECTOR3:
525     {
526       size = sizeof( PropertyImplementationType< Property::VECTOR3 >::Type );
527       break;
528     }
529     case Property::VECTOR4:
530     {
531       size = sizeof( PropertyImplementationType< Property::VECTOR4 >::Type );
532       break;
533     }
534     case Property::MATRIX3:
535     {
536       size = sizeof( PropertyImplementationType< Property::MATRIX3 >::Type );
537       break;
538     }
539     case Property::MATRIX:
540     {
541       size = sizeof( PropertyImplementationType< Property::MATRIX >::Type );
542       break;
543     }
544     case Property::RECTANGLE:
545     {
546       size = sizeof( PropertyImplementationType< Property::RECTANGLE >::Type );
547       break;
548     }
549     case Property::ROTATION:
550     {
551       size = sizeof( PropertyImplementationType< Property::ROTATION >::Type );
552       break;
553     }
554   }
555
556   return size;
557 }
558
559
560 } // namespace Internal
561 } // namespace Dali