6c39e87ef5f4724ef459a5bb1de9984e5a0ed1c9
[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 int 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
58 Node* Node::New( unsigned int id )
59 {
60   return new ( gNodeMemoryPool.AllocateRawThreadSafe() ) Node( id );
61 }
62
63 void Node::Delete( Node* node )
64 {
65   // check we have a node not a layer
66   if( !node->mIsLayer )
67   {
68     // Manually call the destructor
69     node->~Node();
70
71     // Mark the memory it used as free in the memory pool
72     gNodeMemoryPool.FreeThreadSafe( node );
73   }
74   else
75   {
76     // not in the pool, just delete it.
77     delete node;
78   }
79 }
80
81 Node::Node( unsigned int id )
82 : mTransformManager( NULL ),
83   mTransformId( INVALID_TRANSFORM_ID ),
84   mParentOrigin( TRANSFORM_PROPERTY_PARENT_ORIGIN ),
85   mAnchorPoint( TRANSFORM_PROPERTY_ANCHOR_POINT ),
86   mSize( TRANSFORM_PROPERTY_SIZE ),                                               // Zero initialized by default
87   mPosition( TRANSFORM_PROPERTY_POSITION ),                                       // Zero initialized by default
88   mOrientation(),                                                                 // Initialized to identity by default
89   mScale( TRANSFORM_PROPERTY_SCALE ),
90   mVisible( true ),
91   mCulled( false ),
92   mColor( Color::WHITE ),
93   mWorldPosition( TRANSFORM_PROPERTY_WORLD_POSITION, Vector3( 0.0f,0.0f,0.0f ) ), // Zero initialized by default
94   mWorldScale( TRANSFORM_PROPERTY_WORLD_SCALE, Vector3( 1.0f,1.0f,1.0f ) ),
95   mWorldOrientation(),                                                            // Initialized to identity by default
96   mWorldMatrix(),
97   mWorldColor( Color::WHITE ),
98   mClippingSortModifier( 0u ),
99   mId( id ),
100   mParent( NULL ),
101   mExclusiveRenderTask( NULL ),
102   mChildren(),
103   mClippingDepth( 0u ),
104   mScissorDepth( 0u ),
105   mDepthIndex( 0u ),
106   mRegenerateUniformMap( 0 ),
107   mDirtyFlags( AllFlags ),
108   mDrawMode( DrawMode::NORMAL ),
109   mColorMode( DEFAULT_COLOR_MODE ),
110   mClippingMode( ClippingMode::DISABLED ),
111   mIsRoot( false ),
112   mIsLayer( false ),
113   mPositionUsesAnchorPoint( true )
114 {
115   mUniformMapChanged[0] = 0u;
116   mUniformMapChanged[1] = 0u;
117
118 #ifdef DEBUG_ENABLED
119   gNodeCount++;
120 #endif
121
122 }
123
124 Node::~Node()
125 {
126   if( mTransformId != INVALID_TRANSFORM_ID )
127   {
128     mTransformManager->RemoveTransform(mTransformId);
129   }
130
131 #ifdef DEBUG_ENABLED
132   gNodeCount--;
133 #endif
134 }
135
136 void Node::OnDestroy()
137 {
138   // Animators, Constraints etc. should be disconnected from the child's properties.
139   PropertyOwner::Destroy();
140 }
141
142 void Node::CreateTransform( SceneGraph::TransformManager* transformManager )
143 {
144   //Create a new transform
145   mTransformManager = transformManager;
146   mTransformId = transformManager->CreateTransform();
147
148   //Initialize all the animatable properties
149   mPosition.Initialize( transformManager, mTransformId );
150   mScale.Initialize( transformManager, mTransformId );
151   mOrientation.Initialize( transformManager, mTransformId );
152   mSize.Initialize( transformManager, mTransformId );
153   mParentOrigin.Initialize( transformManager, mTransformId );
154   mAnchorPoint.Initialize( transformManager, mTransformId );
155
156   //Initialize all the input properties
157   mWorldPosition.Initialize( transformManager, mTransformId );
158   mWorldScale.Initialize( transformManager, mTransformId );
159   mWorldOrientation.Initialize( transformManager, mTransformId );
160   mWorldMatrix.Initialize( transformManager, mTransformId );
161
162   //Set whether the position should use the anchor point
163   transformManager->SetPositionUsesAnchorPoint( mTransformId, mPositionUsesAnchorPoint );
164 }
165
166 void Node::SetRoot(bool isRoot)
167 {
168   DALI_ASSERT_DEBUG(!isRoot || mParent == NULL); // Root nodes cannot have a parent
169
170   mIsRoot = isRoot;
171 }
172
173 void Node::AddUniformMapping( OwnerPointer< UniformPropertyMapping >& map )
174 {
175   PropertyOwner::AddUniformMapping( map );
176   mRegenerateUniformMap = 2;
177 }
178
179 void Node::RemoveUniformMapping( const std::string& uniformName )
180 {
181   PropertyOwner::RemoveUniformMapping( uniformName );
182   mRegenerateUniformMap = 2;
183 }
184
185 void Node::PrepareRender( BufferIndex bufferIndex )
186 {
187   if(mRegenerateUniformMap != 0 )
188   {
189     if( mRegenerateUniformMap == 2 )
190     {
191       CollectedUniformMap& localMap = mCollectedUniformMap[ bufferIndex ];
192       localMap.Resize(0);
193
194       for( unsigned int i=0, count=mUniformMaps.Count(); i<count; ++i )
195       {
196         localMap.PushBack( &mUniformMaps[i] );
197       }
198     }
199     else if( mRegenerateUniformMap == 1 )
200     {
201       CollectedUniformMap& localMap = mCollectedUniformMap[ bufferIndex ];
202       CollectedUniformMap& oldMap = mCollectedUniformMap[ 1-bufferIndex ];
203
204       localMap.Resize( oldMap.Count() );
205
206       unsigned int index=0;
207       for( CollectedUniformMap::Iterator iter = oldMap.Begin(), end = oldMap.End() ; iter != end ; ++iter, ++index )
208       {
209         localMap[index] = *iter;
210       }
211     }
212     --mRegenerateUniformMap;
213     mUniformMapChanged[bufferIndex] = 1u;
214   }
215 }
216
217 void Node::ConnectChild( Node* childNode )
218 {
219   DALI_ASSERT_ALWAYS( this != childNode );
220   DALI_ASSERT_ALWAYS( IsRoot() || NULL != mParent ); // Parent should be connected first
221   DALI_ASSERT_ALWAYS( !childNode->IsRoot() && NULL == childNode->GetParent() ); // Child should be disconnected
222
223   childNode->SetParent( *this );
224
225   // Everything should be reinherited when reconnected to scene-graph
226   childNode->SetAllDirtyFlags();
227
228   // Add the node to the end of the child list.
229   mChildren.PushBack( childNode );
230
231   // Inform property observers of new connection
232   childNode->ConnectToSceneGraph();
233 }
234
235 void Node::DisconnectChild( BufferIndex updateBufferIndex, Node& childNode )
236 {
237   DALI_ASSERT_ALWAYS( this != &childNode );
238   DALI_ASSERT_ALWAYS( childNode.GetParent() == this );
239
240   // Find the childNode and remove it
241   Node* found( NULL );
242
243   const NodeIter endIter = mChildren.End();
244   for ( NodeIter iter = mChildren.Begin(); iter != endIter; ++iter )
245   {
246     Node* current = *iter;
247     if ( current == &childNode )
248     {
249       found = current;
250       mChildren.Erase( iter ); // order matters here
251       break; // iter is no longer valid
252     }
253   }
254   DALI_ASSERT_ALWAYS( NULL != found );
255
256   found->RecursiveDisconnectFromSceneGraph( updateBufferIndex );
257 }
258
259 void Node::AddRenderer( Renderer* renderer )
260 {
261   // Check that it has not been already added.
262   unsigned int rendererCount( mRenderer.Size() );
263   for( unsigned int i(0); i < rendererCount; ++i )
264   {
265     if( mRenderer[i] == renderer )
266     {
267       // Renderer is already in the list.
268       return;
269     }
270   }
271
272   // If it is the first renderer added, make sure the world transform will be calculated
273   // in the next update as world transform is not computed if node has no renderers.
274   if( rendererCount == 0 )
275   {
276     mDirtyFlags |= TransformFlag;
277   }
278
279   mRenderer.PushBack( renderer );
280 }
281
282 void Node::RemoveRenderer( Renderer* renderer )
283 {
284   unsigned int rendererCount( mRenderer.Size() );
285   for( unsigned int 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 int Node::GetDirtyFlags() const
296 {
297   // get initial dirty flags, they are reset ResetDefaultProperties, but setters may have made the node dirty already
298   int flags = mDirtyFlags;
299
300   // Check whether the visible property has changed
301   if ( !mVisible.IsClean() )
302   {
303     flags |= VisibleFlag;
304   }
305
306   // Check whether the color property has changed
307   if ( !mColor.IsClean() )
308   {
309     flags |= ColorFlag;
310   }
311
312   return flags;
313 }
314
315 void Node::ResetDirtyFlags( BufferIndex updateBufferIndex )
316 {
317   mDirtyFlags = NothingFlag;
318 }
319
320 void Node::SetParent( Node& parentNode )
321 {
322   DALI_ASSERT_ALWAYS(this != &parentNode);
323   DALI_ASSERT_ALWAYS(!mIsRoot);
324   DALI_ASSERT_ALWAYS(mParent == NULL);
325
326   mParent = &parentNode;
327
328   if( mTransformId != INVALID_TRANSFORM_ID )
329   {
330     mTransformManager->SetParent( mTransformId, parentNode.GetTransformId() );
331   }
332 }
333
334 void Node::RecursiveDisconnectFromSceneGraph( BufferIndex updateBufferIndex )
335 {
336   DALI_ASSERT_ALWAYS(!mIsRoot);
337   DALI_ASSERT_ALWAYS(mParent != NULL);
338
339   const NodeIter endIter = mChildren.End();
340   for ( NodeIter iter = mChildren.Begin(); iter != endIter; ++iter )
341   {
342     (*iter)->RecursiveDisconnectFromSceneGraph( updateBufferIndex );
343   }
344
345   // Animators, Constraints etc. should be disconnected from the child's properties.
346   PropertyOwner::DisconnectFromSceneGraph( updateBufferIndex );
347
348   // Remove back-pointer to parent
349   mParent = NULL;
350
351   // Remove all child pointers
352   mChildren.Clear();
353
354   if( mTransformId != INVALID_TRANSFORM_ID )
355   {
356     mTransformManager->SetParent( mTransformId, INVALID_TRANSFORM_ID );
357   }
358 }
359
360 } // namespace SceneGraph
361
362 } // namespace Internal
363
364 } // namespace Dali