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