[dali_1.3.46] Merge branch 'devel/master'
[platform/core/uifw/dali-core.git] / dali / internal / update / nodes / node.cpp
1 /*
2  * Copyright (c) 2018 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/update/nodes/node.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/internal/common/internal-constants.h>
23 #include <dali/internal/common/memory-pool-object-allocator.h>
24 #include <dali/internal/update/common/discard-queue.h>
25 #include <dali/public-api/common/dali-common.h>
26 #include <dali/public-api/common/constants.h>
27
28 namespace //Unnamed namespace
29 {
30 //Memory pool used to allocate new nodes. Memory used by this pool will be released when process dies
31 // or DALI library is unloaded
32 Dali::Internal::MemoryPoolObjectAllocator<Dali::Internal::SceneGraph::Node> gNodeMemoryPool;
33 #ifdef DEBUG_ENABLED
34 // keep track of nodes created / deleted, to ensure we have 0 when the process exits or DALi library is unloaded
35 int32_t gNodeCount =0;
36
37 // Called when the process is about to exit, Node count should be zero at this point.
38 void __attribute__ ((destructor)) ShutDown(void)
39 {
40 DALI_ASSERT_DEBUG( (gNodeCount == 0) && "Node memory leak");
41 }
42 #endif
43 }
44
45 namespace Dali
46 {
47
48 namespace Internal
49 {
50
51 namespace SceneGraph
52 {
53
54 const PositionInheritanceMode Node::DEFAULT_POSITION_INHERITANCE_MODE( INHERIT_PARENT_POSITION );
55 const ColorMode Node::DEFAULT_COLOR_MODE( USE_OWN_MULTIPLY_PARENT_ALPHA );
56
57 Node* Node::New( uint32_t id )
58 {
59   return new ( gNodeMemoryPool.AllocateRawThreadSafe() ) Node( id );
60 }
61
62 void Node::Delete( Node* node )
63 {
64   // check we have a node not a layer
65   if( !node->mIsLayer )
66   {
67     // Manually call the destructor
68     node->~Node();
69
70     // Mark the memory it used as free in the memory pool
71     gNodeMemoryPool.FreeThreadSafe( node );
72   }
73   else
74   {
75     // not in the pool, just delete it.
76     delete node;
77   }
78 }
79
80 Node::Node( uint32_t id )
81 : mTransformManager( NULL ),
82   mTransformId( INVALID_TRANSFORM_ID ),
83   mParentOrigin( TRANSFORM_PROPERTY_PARENT_ORIGIN ),
84   mAnchorPoint( TRANSFORM_PROPERTY_ANCHOR_POINT ),
85   mSize( TRANSFORM_PROPERTY_SIZE ),                                               // Zero initialized by default
86   mPosition( TRANSFORM_PROPERTY_POSITION ),                                       // Zero initialized by default
87   mOrientation(),                                                                 // Initialized to identity by default
88   mScale( TRANSFORM_PROPERTY_SCALE ),
89   mVisible( true ),
90   mCulled( false ),
91   mColor( Color::WHITE ),
92   mWorldPosition( TRANSFORM_PROPERTY_WORLD_POSITION, Vector3( 0.0f,0.0f,0.0f ) ), // Zero initialized by default
93   mWorldScale( TRANSFORM_PROPERTY_WORLD_SCALE, Vector3( 1.0f,1.0f,1.0f ) ),
94   mWorldOrientation(),                                                            // Initialized to identity by default
95   mWorldMatrix(),
96   mWorldColor( Color::WHITE ),
97   mClippingSortModifier( 0u ),
98   mId( id ),
99   mParent( NULL ),
100   mExclusiveRenderTask( NULL ),
101   mChildren(),
102   mClippingDepth( 0u ),
103   mScissorDepth( 0u ),
104   mDepthIndex( 0u ),
105   mDirtyFlags( NodePropertyFlags::ALL ),
106   mRegenerateUniformMap( 0 ),
107   mDrawMode( DrawMode::NORMAL ),
108   mColorMode( DEFAULT_COLOR_MODE ),
109   mClippingMode( ClippingMode::DISABLED ),
110   mIsRoot( false ),
111   mIsLayer( false ),
112   mPositionUsesAnchorPoint( true )
113 {
114   mUniformMapChanged[0] = 0u;
115   mUniformMapChanged[1] = 0u;
116
117 #ifdef DEBUG_ENABLED
118   gNodeCount++;
119 #endif
120
121 }
122
123 Node::~Node()
124 {
125   if( mTransformId != INVALID_TRANSFORM_ID )
126   {
127     mTransformManager->RemoveTransform(mTransformId);
128   }
129
130 #ifdef DEBUG_ENABLED
131   gNodeCount--;
132 #endif
133 }
134
135 void Node::OnDestroy()
136 {
137   // Animators, Constraints etc. should be disconnected from the child's properties.
138   PropertyOwner::Destroy();
139 }
140
141 void Node::CreateTransform( SceneGraph::TransformManager* transformManager )
142 {
143   //Create a new transform
144   mTransformManager = transformManager;
145   mTransformId = transformManager->CreateTransform();
146
147   //Initialize all the animatable properties
148   mPosition.Initialize( transformManager, mTransformId );
149   mScale.Initialize( transformManager, mTransformId );
150   mOrientation.Initialize( transformManager, mTransformId );
151   mSize.Initialize( transformManager, mTransformId );
152   mParentOrigin.Initialize( transformManager, mTransformId );
153   mAnchorPoint.Initialize( transformManager, mTransformId );
154
155   //Initialize all the input properties
156   mWorldPosition.Initialize( transformManager, mTransformId );
157   mWorldScale.Initialize( transformManager, mTransformId );
158   mWorldOrientation.Initialize( transformManager, mTransformId );
159   mWorldMatrix.Initialize( transformManager, mTransformId );
160
161   //Set whether the position should use the anchor point
162   transformManager->SetPositionUsesAnchorPoint( mTransformId, mPositionUsesAnchorPoint );
163 }
164
165 void Node::SetRoot(bool isRoot)
166 {
167   DALI_ASSERT_DEBUG(!isRoot || mParent == NULL); // Root nodes cannot have a parent
168
169   mIsRoot = isRoot;
170 }
171
172 void Node::AddUniformMapping( OwnerPointer< UniformPropertyMapping >& map )
173 {
174   PropertyOwner::AddUniformMapping( map );
175   mRegenerateUniformMap = 2;
176 }
177
178 void Node::RemoveUniformMapping( const std::string& uniformName )
179 {
180   PropertyOwner::RemoveUniformMapping( uniformName );
181   mRegenerateUniformMap = 2;
182 }
183
184 void Node::PrepareRender( BufferIndex bufferIndex )
185 {
186   if( mRegenerateUniformMap != 0 )
187   {
188     if( mRegenerateUniformMap == 2 )
189     {
190       CollectedUniformMap& localMap = mCollectedUniformMap[ bufferIndex ];
191       localMap.Resize(0);
192
193       for( uint32_t i = 0, count=mUniformMaps.Count(); i<count; ++i )
194       {
195         localMap.PushBack( &mUniformMaps[i] );
196       }
197     }
198     else if( mRegenerateUniformMap == 1 )
199     {
200       CollectedUniformMap& localMap = mCollectedUniformMap[ bufferIndex ];
201       CollectedUniformMap& oldMap = mCollectedUniformMap[ 1-bufferIndex ];
202
203       localMap.Resize( oldMap.Count() );
204
205       CollectedUniformMap::SizeType index = 0;
206       for( CollectedUniformMap::Iterator iter = oldMap.Begin(), end = oldMap.End() ; iter != end ; ++iter, ++index )
207       {
208         localMap[index] = *iter;
209       }
210     }
211     --mRegenerateUniformMap;
212     mUniformMapChanged[bufferIndex] = 1u;
213   }
214 }
215
216 void Node::ConnectChild( Node* childNode )
217 {
218   DALI_ASSERT_ALWAYS( this != childNode );
219   DALI_ASSERT_ALWAYS( IsRoot() || NULL != mParent ); // Parent should be connected first
220   DALI_ASSERT_ALWAYS( !childNode->IsRoot() && NULL == childNode->GetParent() ); // Child should be disconnected
221
222   childNode->SetParent( *this );
223
224   // Everything should be reinherited when reconnected to scene-graph
225   childNode->SetAllDirtyFlags();
226
227   // Add the node to the end of the child list.
228   mChildren.PushBack( childNode );
229
230   // Inform property observers of new connection
231   childNode->ConnectToSceneGraph();
232 }
233
234 void Node::DisconnectChild( BufferIndex updateBufferIndex, Node& childNode )
235 {
236   DALI_ASSERT_ALWAYS( this != &childNode );
237   DALI_ASSERT_ALWAYS( childNode.GetParent() == this );
238
239   // Find the childNode and remove it
240   Node* found( NULL );
241
242   const NodeIter endIter = mChildren.End();
243   for ( NodeIter iter = mChildren.Begin(); iter != endIter; ++iter )
244   {
245     Node* current = *iter;
246     if ( current == &childNode )
247     {
248       found = current;
249       mChildren.Erase( iter ); // order matters here
250       break; // iter is no longer valid
251     }
252   }
253   DALI_ASSERT_ALWAYS( NULL != found );
254
255   found->RecursiveDisconnectFromSceneGraph( updateBufferIndex );
256 }
257
258 void Node::AddRenderer( Renderer* renderer )
259 {
260   // If it is the first renderer added, make sure the world transform will be calculated
261   // in the next update as world transform is not computed if node has no renderers.
262   if( mRenderer.Empty() )
263   {
264     mDirtyFlags |= NodePropertyFlags::TRANSFORM;
265   }
266   else
267   {
268     // Check that it has not been already added.
269     for( auto&& existingRenderer : mRenderer )
270     {
271       if( existingRenderer == renderer )
272       {
273         // Renderer is already in the list.
274         return;
275       }
276     }
277   }
278
279   mRenderer.PushBack( renderer );
280 }
281
282 void Node::RemoveRenderer( Renderer* renderer )
283 {
284   RendererContainer::SizeType rendererCount( mRenderer.Size() );
285   for( RendererContainer::SizeType i = 0; i < rendererCount; ++i )
286   {
287     if( mRenderer[i] == renderer )
288     {
289       mRenderer.Erase( mRenderer.Begin()+i);
290       return;
291     }
292   }
293 }
294
295 NodePropertyFlags Node::GetDirtyFlags() const
296 {
297   // get initial dirty flags, they are reset ResetDefaultProperties, but setters may have made the node dirty already
298   NodePropertyFlags flags = mDirtyFlags;
299
300   // Check whether the visible property has changed
301   if ( !mVisible.IsClean() )
302   {
303     flags |= NodePropertyFlags::VISIBLE;
304   }
305
306   // Check whether the color property has changed
307   if ( !mColor.IsClean() )
308   {
309     flags |= NodePropertyFlags::COLOR;
310   }
311
312   return flags;
313 }
314
315 NodePropertyFlags Node::GetInheritedDirtyFlags( NodePropertyFlags parentFlags ) const
316 {
317   // Size is not inherited. VisibleFlag is inherited
318   static const NodePropertyFlags InheritedDirtyFlags = NodePropertyFlags::TRANSFORM | NodePropertyFlags::VISIBLE | NodePropertyFlags::COLOR;
319   using UnderlyingType = typename std::underlying_type<NodePropertyFlags>::type;
320
321   return static_cast<NodePropertyFlags>( static_cast<UnderlyingType>( mDirtyFlags ) |
322                                          ( static_cast<UnderlyingType>( parentFlags ) & static_cast<UnderlyingType>( InheritedDirtyFlags ) ) );
323 }
324
325 void Node::ResetDirtyFlags( BufferIndex updateBufferIndex )
326 {
327   mDirtyFlags = NodePropertyFlags::NOTHING;
328 }
329
330 void Node::SetParent( Node& parentNode )
331 {
332   DALI_ASSERT_ALWAYS(this != &parentNode);
333   DALI_ASSERT_ALWAYS(!mIsRoot);
334   DALI_ASSERT_ALWAYS(mParent == NULL);
335
336   mParent = &parentNode;
337
338   if( mTransformId != INVALID_TRANSFORM_ID )
339   {
340     mTransformManager->SetParent( mTransformId, parentNode.GetTransformId() );
341   }
342 }
343
344 void Node::RecursiveDisconnectFromSceneGraph( BufferIndex updateBufferIndex )
345 {
346   DALI_ASSERT_ALWAYS(!mIsRoot);
347   DALI_ASSERT_ALWAYS(mParent != NULL);
348
349   const NodeIter endIter = mChildren.End();
350   for ( NodeIter iter = mChildren.Begin(); iter != endIter; ++iter )
351   {
352     (*iter)->RecursiveDisconnectFromSceneGraph( updateBufferIndex );
353   }
354
355   // Animators, Constraints etc. should be disconnected from the child's properties.
356   PropertyOwner::DisconnectFromSceneGraph( updateBufferIndex );
357
358   // Remove back-pointer to parent
359   mParent = NULL;
360
361   // Remove all child pointers
362   mChildren.Clear();
363
364   if( mTransformId != INVALID_TRANSFORM_ID )
365   {
366     mTransformManager->SetParent( mTransformId, INVALID_TRANSFORM_ID );
367   }
368 }
369
370 } // namespace SceneGraph
371
372 } // namespace Internal
373
374 } // namespace Dali