52f443a5b7503072384a7fe6116153cb4a64e8fd
[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   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   mRegenerateUniformMap( 0 ),
106   mDirtyFlags( AllFlags ),
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( unsigned int 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       unsigned int 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   // Check that it has not been already added.
261   unsigned int rendererCount( mRenderer.Size() );
262   for( unsigned int i(0); i < rendererCount; ++i )
263   {
264     if( mRenderer[i] == renderer )
265     {
266       // Renderer is already in the list.
267       return;
268     }
269   }
270
271   // If it is the first renderer added, make sure the world transform will be calculated
272   // in the next update as world transform is not computed if node has no renderers.
273   if( rendererCount == 0 )
274   {
275     mDirtyFlags |= TransformFlag;
276   }
277
278   mRenderer.PushBack( renderer );
279 }
280
281 void Node::RemoveRenderer( Renderer* renderer )
282 {
283   unsigned int rendererCount( mRenderer.Size() );
284   for( unsigned int i(0); i<rendererCount; ++i )
285   {
286     if( mRenderer[i] == renderer )
287     {
288       mRenderer.Erase( mRenderer.Begin()+i);
289       return;
290     }
291   }
292 }
293
294 int Node::GetDirtyFlags() const
295 {
296   // get initial dirty flags, they are reset ResetDefaultProperties, but setters may have made the node dirty already
297   int flags = mDirtyFlags;
298
299   // Check whether the visible property has changed
300   if ( !mVisible.IsClean() )
301   {
302     flags |= VisibleFlag;
303   }
304
305   // Check whether the color property has changed
306   if ( !mColor.IsClean() )
307   {
308     flags |= ColorFlag;
309   }
310
311   return flags;
312 }
313
314 void Node::ResetDirtyFlags( BufferIndex updateBufferIndex )
315 {
316   mDirtyFlags = NothingFlag;
317 }
318
319 void Node::SetParent( Node& parentNode )
320 {
321   DALI_ASSERT_ALWAYS(this != &parentNode);
322   DALI_ASSERT_ALWAYS(!mIsRoot);
323   DALI_ASSERT_ALWAYS(mParent == NULL);
324
325   mParent = &parentNode;
326
327   if( mTransformId != INVALID_TRANSFORM_ID )
328   {
329     mTransformManager->SetParent( mTransformId, parentNode.GetTransformId() );
330   }
331 }
332
333 void Node::RecursiveDisconnectFromSceneGraph( BufferIndex updateBufferIndex )
334 {
335   DALI_ASSERT_ALWAYS(!mIsRoot);
336   DALI_ASSERT_ALWAYS(mParent != NULL);
337
338   const NodeIter endIter = mChildren.End();
339   for ( NodeIter iter = mChildren.Begin(); iter != endIter; ++iter )
340   {
341     (*iter)->RecursiveDisconnectFromSceneGraph( updateBufferIndex );
342   }
343
344   // Animators, Constraints etc. should be disconnected from the child's properties.
345   PropertyOwner::DisconnectFromSceneGraph( updateBufferIndex );
346
347   // Remove back-pointer to parent
348   mParent = NULL;
349
350   // Remove all child pointers
351   mChildren.Clear();
352
353   if( mTransformId != INVALID_TRANSFORM_ID )
354   {
355     mTransformManager->SetParent( mTransformId, INVALID_TRANSFORM_ID );
356   }
357 }
358
359 } // namespace SceneGraph
360
361 template <>
362 void OwnerPointer<Dali::Internal::SceneGraph::Node>::Reset()
363 {
364   if( mObject != NULL )
365   {
366     Dali::Internal::SceneGraph::Node::Delete( mObject );
367     mObject = NULL;
368   }
369 }
370
371 } // namespace Internal
372
373 template <>
374 void OwnerContainer<Dali::Internal::SceneGraph::Node*>::Delete(Dali::Internal::SceneGraph::Node* pointer)
375 {
376   Dali::Internal::SceneGraph::Node::Delete( pointer );
377 }
378
379 } // namespace Dali