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