Merge "New parameter for FrameBufferImage creation" into devel/master
[platform/core/uifw/dali-core.git] / dali / internal / update / manager / update-manager.cpp
1 /*
2  * Copyright (c) 2014 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/manager/update-manager.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/public-api/common/stage.h>
23 #include <dali/devel-api/common/set-wrapper.h>
24
25 #include <dali/integration-api/core.h>
26 #include <dali/integration-api/render-controller.h>
27 #include <dali/integration-api/shader-data.h>
28 #include <dali/integration-api/debug.h>
29
30 #include <dali/internal/common/core-impl.h>
31 #include <dali/internal/common/owner-container.h>
32 #include <dali/internal/common/message.h>
33
34 #include <dali/internal/event/common/notification-manager.h>
35 #include <dali/internal/event/common/property-notification-impl.h>
36 #include <dali/internal/event/common/property-notifier.h>
37
38 #include <dali/internal/update/animation/scene-graph-animator.h>
39 #include <dali/internal/update/animation/scene-graph-animation.h>
40 #include <dali/internal/update/common/discard-queue.h>
41 #include <dali/internal/update/common/scene-graph-buffers.h>
42 #include <dali/internal/update/common/scene-graph-property-buffer.h>
43 #include <dali/internal/update/controllers/render-message-dispatcher.h>
44 #include <dali/internal/update/controllers/scene-controller-impl.h>
45 #include <dali/internal/update/gestures/scene-graph-pan-gesture.h>
46 #include <dali/internal/update/manager/object-owner-container.h>
47 #include <dali/internal/update/manager/prepare-render-algorithms.h>
48 #include <dali/internal/update/manager/process-render-tasks.h>
49 #include <dali/internal/update/manager/sorted-layers.h>
50 #include <dali/internal/update/manager/update-algorithms.h>
51 #include <dali/internal/update/manager/update-manager-debug.h>
52 #include <dali/internal/update/node-attachments/scene-graph-camera-attachment.h>
53 #include <dali/internal/update/node-attachments/scene-graph-renderer-attachment.h>
54 #include <dali/internal/update/node-attachments/scene-graph-image-attachment.h>
55 #include <dali/internal/update/nodes/node.h>
56 #include <dali/internal/update/nodes/scene-graph-layer.h>
57 #include <dali/internal/update/queue/update-message-queue.h>
58 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
59 #include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
60 #include <dali/internal/update/rendering/scene-graph-material.h>
61 #include <dali/internal/update/rendering/scene-graph-sampler.h>
62 #include <dali/internal/update/rendering/scene-graph-geometry.h>
63 #include <dali/internal/update/resources/resource-manager.h>
64 #include <dali/internal/update/resources/complete-status-manager.h>
65 #include <dali/internal/update/touch/touch-resampler.h>
66
67 #include <dali/internal/render/common/render-instruction-container.h>
68 #include <dali/internal/render/common/render-manager.h>
69 #include <dali/internal/render/queue/render-queue.h>
70 #include <dali/internal/render/common/performance-monitor.h>
71 #include <dali/internal/render/gl-resources/texture-cache.h>
72 #include <dali/internal/render/shaders/scene-graph-shader.h>
73
74 // Un-comment to enable node tree debug logging
75 //#define NODE_TREE_LOGGING 1
76
77 #if ( defined( DEBUG_ENABLED ) && defined( NODE_TREE_LOGGING ) )
78 #define SNAPSHOT_NODE_LOGGING \
79 const int FRAME_COUNT_TRIGGER = 16;\
80 if( mImpl->frameCounter >= FRAME_COUNT_TRIGGER )\
81   {\
82     if ( NULL != mImpl->root )\
83     {\
84       mImpl->frameCounter = 0;\
85       PrintNodeTree( *mImpl->root, mSceneGraphBuffers.GetUpdateBufferIndex(), "" );\
86     }\
87   }\
88 mImpl->frameCounter++;
89 #else
90 #define SNAPSHOT_NODE_LOGGING
91 #endif
92
93 #if defined(DEBUG_ENABLED)
94 extern Debug::Filter* gRenderTaskLogFilter;
95 #endif
96
97
98 using namespace Dali::Integration;
99 using Dali::Internal::Update::MessageQueue;
100
101 namespace Dali
102 {
103
104 namespace Internal
105 {
106
107 namespace SceneGraph
108 {
109
110 namespace
111 {
112
113 void DestroyNodeSet( std::set<Node*>& nodeSet )
114 {
115   for( std::set<Node*>::iterator iter = nodeSet.begin(); iter != nodeSet.end(); ++iter )
116   {
117     Node* node( *iter );
118
119     // Call Node::OnDestroy as each node is destroyed
120     node->OnDestroy();
121
122     delete node;
123   }
124   nodeSet.clear();
125 }
126
127 } //namespace
128
129 typedef OwnerContainer< Shader* >              ShaderContainer;
130 typedef ShaderContainer::Iterator              ShaderIter;
131 typedef ShaderContainer::ConstIterator         ShaderConstIter;
132
133 typedef OwnerContainer<PanGesture*>            GestureContainer;
134 typedef GestureContainer::Iterator             GestureIter;
135 typedef GestureContainer::ConstIterator        GestureConstIter;
136
137
138 /**
139  * Structure to contain UpdateManager internal data
140  */
141 struct UpdateManager::Impl
142 {
143   Impl( NotificationManager& notificationManager,
144         GlSyncAbstraction& glSyncAbstraction,
145         CompleteNotificationInterface& animationFinishedNotifier,
146         PropertyNotifier& propertyNotifier,
147         ResourceManager& resourceManager,
148         DiscardQueue& discardQueue,
149         RenderController& renderController,
150         RenderManager& renderManager,
151         RenderQueue& renderQueue,
152         TextureCache& textureCache,
153         TouchResampler& touchResampler,
154         SceneGraphBuffers& sceneGraphBuffers )
155   :
156     renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ),
157     notificationManager( notificationManager ),
158     animationFinishedNotifier( animationFinishedNotifier ),
159     propertyNotifier( propertyNotifier ),
160     resourceManager( resourceManager ),
161     discardQueue( discardQueue ),
162     renderController( renderController ),
163     sceneController( NULL ),
164     renderManager( renderManager ),
165     renderQueue( renderQueue ),
166     renderInstructions( renderManager.GetRenderInstructionContainer() ),
167     completeStatusManager( glSyncAbstraction, renderMessageDispatcher, resourceManager ),
168     touchResampler( touchResampler ),
169     backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
170     taskList ( completeStatusManager ),
171     systemLevelTaskList ( completeStatusManager ),
172     root( NULL ),
173     systemLevelRoot( NULL ),
174     geometries(  sceneGraphBuffers, discardQueue ),
175     materials( sceneGraphBuffers, discardQueue ),
176     samplers( sceneGraphBuffers, discardQueue ),
177     propertyBuffers( sceneGraphBuffers, discardQueue ),
178     messageQueue( renderController, sceneGraphBuffers ),
179     keepRenderingSeconds( 0.0f ),
180     animationFinishedDuringUpdate( false ),
181     nodeDirtyFlags( TransformFlag ), // set to TransformFlag to ensure full update the first time through Update()
182     previousUpdateScene( false ),
183     frameCounter( 0 ),
184     renderSortingHelper(),
185     renderTaskWaiting( false )
186   {
187     sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue, textureCache, completeStatusManager );
188
189     geometries.SetSceneController( *sceneController );
190     materials.SetSceneController( *sceneController );
191     propertyBuffers.SetSceneController( *sceneController );
192     samplers.SetSceneController( *sceneController );
193   }
194
195   ~Impl()
196   {
197     // Disconnect render tasks from nodes, before destroying the nodes
198     RenderTaskList::RenderTaskContainer& tasks = taskList.GetTasks();
199     for (RenderTaskList::RenderTaskContainer::Iterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
200     {
201       (*iter)->SetSourceNode( NULL );
202     }
203     // ..repeat for system level RenderTasks
204     RenderTaskList::RenderTaskContainer& systemLevelTasks = systemLevelTaskList.GetTasks();
205     for (RenderTaskList::RenderTaskContainer::Iterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
206     {
207       (*iter)->SetSourceNode( NULL );
208     }
209
210     // UpdateManager owns the Nodes
211     DestroyNodeSet( activeDisconnectedNodes );
212     DestroyNodeSet( connectedNodes );
213     DestroyNodeSet( disconnectedNodes );
214
215     // If there is root, reset it, otherwise do nothing as rendering was never started
216     if( root )
217     {
218       root->OnDestroy();
219
220       delete root;
221       root = NULL;
222     }
223
224     if( systemLevelRoot )
225     {
226       systemLevelRoot->OnDestroy();
227
228       delete systemLevelRoot;
229       systemLevelRoot = NULL;
230     }
231
232     sceneController->GetTextureCache().SetBufferIndices(NULL); // TODO - Remove
233     delete sceneController;
234   }
235
236   SceneGraphBuffers                   sceneGraphBuffers;             ///< Used to keep track of which buffers are being written or read
237   RenderMessageDispatcher             renderMessageDispatcher;       ///< Used for passing messages to the render-thread
238   NotificationManager&                notificationManager;           ///< Queues notification messages for the event-thread.
239   CompleteNotificationInterface&      animationFinishedNotifier;     ///< Provides notification to applications when animations are finished.
240   PropertyNotifier&                   propertyNotifier;              ///< Provides notification to applications when properties are modified.
241   ResourceManager&                    resourceManager;               ///< resource manager
242   DiscardQueue&                       discardQueue;                  ///< Nodes are added here when disconnected from the scene-graph.
243   RenderController&                   renderController;              ///< render controller
244   SceneControllerImpl*                sceneController;               ///< scene controller
245   RenderManager&                      renderManager;                 ///< This is responsible for rendering the results of each "update"
246   RenderQueue&                        renderQueue;                   ///< Used to queue messages for the next render
247   RenderInstructionContainer&         renderInstructions;            ///< Used to prepare the render instructions
248   CompleteStatusManager               completeStatusManager;         ///< Complete Status Manager
249   TouchResampler&                     touchResampler;                ///< Used to resample touch events on every update.
250
251   Vector4                             backgroundColor;               ///< The glClear color used at the beginning of each frame.
252
253   RenderTaskList                      taskList;                      ///< The list of scene graph render-tasks
254   RenderTaskList                      systemLevelTaskList;           ///< Separate render-tasks for system-level content
255
256   Layer*                              root;                          ///< The root node (root is a layer)
257   Layer*                              systemLevelRoot;               ///< A separate root-node for system-level content
258   std::set< Node* >                   activeDisconnectedNodes;       ///< A container of new or modified nodes (without parent) owned by UpdateManager
259   std::set< Node* >                   connectedNodes;                ///< A container of connected (with parent) nodes owned by UpdateManager
260   std::set< Node* >                   disconnectedNodes;             ///< A container of inactive disconnected nodes (without parent) owned by UpdateManager
261
262   SortedLayerPointers                 sortedLayers;                  ///< A container of Layer pointers sorted by depth
263   SortedLayerPointers                 systemLevelSortedLayers;       ///< A separate container of system-level Layers
264
265   OwnerContainer< PropertyOwner* >    customObjects;                 ///< A container of owned objects (with custom properties)
266
267   AnimationContainer                  animations;                    ///< A container of owned animations
268   PropertyNotificationContainer       propertyNotifications;         ///< A container of owner property notifications.
269
270   ObjectOwnerContainer<Geometry>      geometries;                    ///< A container of geometries
271   ObjectOwnerContainer<Material>      materials;                     ///< A container of materials
272   ObjectOwnerContainer<Sampler>       samplers;                      ///< A container of samplers
273   ObjectOwnerContainer<PropertyBuffer> propertyBuffers;             ///< A container of property buffers
274
275   ShaderContainer                     shaders;                       ///< A container of owned shaders
276
277   MessageQueue                        messageQueue;                  ///< The messages queued from the event-thread
278
279   float                               keepRenderingSeconds;          ///< Set via Dali::Stage::KeepRendering
280   bool                                animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
281
282   int                                 nodeDirtyFlags;                ///< cumulative node dirty flags from previous frame
283   bool                                previousUpdateScene;           ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
284
285   int                                 frameCounter;                  ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
286   RendererSortingHelper               renderSortingHelper;           ///< helper used to sort transparent renderers
287
288   GestureContainer                    gestures;                      ///< A container of owned gesture detectors
289   bool                                renderTaskWaiting;             ///< A REFRESH_ONCE render task is waiting to be rendered
290 };
291
292 UpdateManager::UpdateManager( NotificationManager& notificationManager,
293                               GlSyncAbstraction& glSyncAbstraction,
294                               CompleteNotificationInterface& animationFinishedNotifier,
295                               PropertyNotifier& propertyNotifier,
296                               ResourceManager& resourceManager,
297                               DiscardQueue& discardQueue,
298                               RenderController& controller,
299                               RenderManager& renderManager,
300                               RenderQueue& renderQueue,
301                               TextureCache& textureCache,
302                               TouchResampler& touchResampler )
303   : mImpl(NULL)
304 {
305   mImpl = new Impl( notificationManager,
306                     glSyncAbstraction,
307                     animationFinishedNotifier,
308                     propertyNotifier,
309                     resourceManager,
310                     discardQueue,
311                     controller,
312                     renderManager,
313                     renderQueue,
314                     textureCache,
315                     touchResampler,
316                     mSceneGraphBuffers );
317
318   textureCache.SetBufferIndices( &mSceneGraphBuffers );
319 }
320
321 UpdateManager::~UpdateManager()
322 {
323   delete mImpl;
324 }
325
326 void UpdateManager::InstallRoot( SceneGraph::Layer* layer, bool systemLevel )
327 {
328   DALI_ASSERT_DEBUG( layer->IsLayer() );
329   DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
330
331   if ( !systemLevel )
332   {
333     DALI_ASSERT_DEBUG( mImpl->root == NULL && "Root Node already installed" );
334     mImpl->root = layer;
335   }
336   else
337   {
338     DALI_ASSERT_DEBUG( mImpl->systemLevelRoot == NULL && "System-level Root Node already installed" );
339     mImpl->systemLevelRoot = layer;
340   }
341
342   layer->SetRoot(true);
343 }
344
345 void UpdateManager::AddNode( Node* node )
346 {
347   DALI_ASSERT_ALWAYS( NULL != node );
348   DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
349
350   mImpl->activeDisconnectedNodes.insert( node ); // Takes ownership of node
351 }
352
353 void UpdateManager::ConnectNode( Node* parent, Node* node, int index )
354 {
355   DALI_ASSERT_ALWAYS( NULL != parent );
356   DALI_ASSERT_ALWAYS( NULL != node );
357   DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
358
359   // Move from active/disconnectedNodes to connectedNodes
360   std::set<Node*>::size_type removed = mImpl->activeDisconnectedNodes.erase( node );
361   if( !removed )
362   {
363     removed = mImpl->disconnectedNodes.erase( node );
364     DALI_ASSERT_ALWAYS( removed );
365   }
366   mImpl->connectedNodes.insert( node );
367
368   node->SetActive( true );
369
370   parent->ConnectChild( node, index );
371 }
372
373 void UpdateManager::DisconnectNode( Node* node )
374 {
375   Node* parent = node->GetParent();
376   DALI_ASSERT_ALWAYS( NULL != parent );
377   parent->SetDirtyFlag( ChildDeletedFlag ); // make parent dirty so that render items dont get reused
378
379   // Move from connectedNodes to activeDisconnectedNodes (reset properties next frame)
380   parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node, mImpl->connectedNodes, mImpl->activeDisconnectedNodes );
381 }
382
383 void UpdateManager::SetNodeActive( Node* node )
384 {
385   DALI_ASSERT_ALWAYS( NULL != node );
386   DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
387
388   // Move from disconnectedNodes to activeDisconnectedNodes (reset properties next frame)
389   std::set<Node*>::size_type removed = mImpl->disconnectedNodes.erase( node );
390   DALI_ASSERT_ALWAYS( removed );
391   mImpl->activeDisconnectedNodes.insert( node );
392
393   node->SetActive( true );
394 }
395
396 void UpdateManager::DestroyNode( Node* node )
397 {
398   DALI_ASSERT_ALWAYS( NULL != node );
399   DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
400
401   // Transfer ownership from new/disconnectedNodes to the discard queue
402   // This keeps the nodes alive, until the render-thread has finished with them
403   std::set<Node*>::size_type removed = mImpl->activeDisconnectedNodes.erase( node );
404   if( !removed )
405   {
406     removed = mImpl->disconnectedNodes.erase( node );
407     DALI_ASSERT_ALWAYS( removed );
408   }
409   mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
410
411   // Notify the Node about impending destruction
412   node->OnDestroy();
413 }
414
415 //@todo MESH_REWORK Extend to allow arbitrary scene objects to connect to each other
416 void UpdateManager::AttachToNode( Node* node, NodeAttachment* attachment )
417 {
418   DALI_ASSERT_DEBUG( node != NULL );
419   DALI_ASSERT_DEBUG( attachment != NULL );
420
421   // attach node to attachment first so that parent is known by the time attachment is connected
422   node->Attach( *attachment ); // node takes ownership
423
424   // @todo MESH_REWORK Remove after merge of SceneGraph::RenderableAttachment and SceneGraph::RendererAttachment
425   if( dynamic_cast<SceneGraph::ImageAttachment*>( attachment ) != NULL )
426   {
427     attachment->Initialize( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
428   }
429 }
430
431 void UpdateManager::AttachToSceneGraph( RendererAttachment* renderer )
432 {
433   // @todo MESH_REWORK Take ownership of this object after merge with SceneGraph::RenderableAttachment
434
435   SceneGraph::NodeAttachment* attachment = static_cast<SceneGraph::NodeAttachment*>(renderer);
436   attachment->Initialize( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
437 }
438
439 void UpdateManager::AddObject( PropertyOwner* object )
440 {
441   DALI_ASSERT_DEBUG( NULL != object );
442
443   mImpl->customObjects.PushBack( object );
444 }
445
446 void UpdateManager::RemoveObject( PropertyOwner* object )
447 {
448   DALI_ASSERT_DEBUG( NULL != object );
449
450   OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
451
452   // Find the object and destroy it
453   for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); iter != customObjects.End(); ++iter )
454   {
455     PropertyOwner* current = *iter;
456     if ( current == object )
457     {
458       customObjects.Erase( iter );
459       return;
460     }
461   }
462
463   // Should not reach here
464   DALI_ASSERT_DEBUG(false);
465 }
466
467 void UpdateManager::AddAnimation( Animation* animation )
468 {
469   mImpl->animations.PushBack( animation );
470 }
471
472 void UpdateManager::StopAnimation( Animation* animation )
473 {
474   DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
475
476   bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
477
478   mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
479 }
480
481 void UpdateManager::RemoveAnimation( Animation* animation )
482 {
483   DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
484
485   animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
486
487   DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
488 }
489
490 bool UpdateManager::IsAnimationRunning() const
491 {
492   bool isRunning(false);
493   AnimationContainer& animations = mImpl->animations;
494
495   // Find any animation that isn't stopped or paused
496
497   const AnimationIter endIter = animations.End();
498   for ( AnimationIter iter = animations.Begin(); !isRunning && iter != endIter; ++iter )
499   {
500     const Animation::State state = (*iter)->GetState();
501
502     if (state != Animation::Stopped &&
503         state != Animation::Paused)
504     {
505       isRunning = true;
506     }
507   }
508
509   return isRunning;
510 }
511
512 void UpdateManager::AddPropertyNotification( PropertyNotification* propertyNotification )
513 {
514   mImpl->propertyNotifications.PushBack( propertyNotification );
515 }
516
517 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
518 {
519   PropertyNotificationContainer &propertyNotifications = mImpl->propertyNotifications;
520   PropertyNotificationIter iter = propertyNotifications.Begin();
521
522   while ( iter != propertyNotifications.End() )
523   {
524     if( *iter == propertyNotification )
525     {
526       propertyNotifications.Erase(iter);
527       break;
528     }
529     ++iter;
530   }
531 }
532
533 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
534 {
535   DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
536   propertyNotification->SetNotifyMode( notifyMode );
537 }
538
539 ObjectOwnerContainer<Geometry>& UpdateManager::GetGeometryOwner()
540 {
541   return mImpl->geometries;
542 }
543
544 ObjectOwnerContainer<Material>& UpdateManager::GetMaterialOwner()
545 {
546   return mImpl->materials;
547 }
548
549 ObjectOwnerContainer<Sampler>& UpdateManager::GetSamplerOwner()
550 {
551   return mImpl->samplers;
552 }
553
554 ObjectOwnerContainer<PropertyBuffer>& UpdateManager::GetPropertyBufferOwner()
555 {
556   return mImpl->propertyBuffers;
557 }
558
559 void UpdateManager::AddShader( Shader* shader )
560 {
561   DALI_ASSERT_DEBUG( NULL != shader );
562
563   if( mImpl->shaders.Count() == 0 )
564   {
565     // the first added shader becomes our default shader
566     // Construct message in the render queue memory; note that delete should not be called on the return value
567     typedef MessageValue1< RenderManager, Shader* > DerivedType;
568
569     // Reserve some memory inside the render queue
570     unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
571
572     // Construct message in the render queue memory; note that delete should not be called on the return value
573     new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultShader, shader );
574   }
575
576   mImpl->shaders.PushBack( shader );
577
578   // Allows the shader to dispatch texture requests to the cache
579   shader->Initialize( mImpl->renderQueue, mImpl->sceneController->GetTextureCache() );
580 }
581
582 void UpdateManager::RemoveShader( Shader* shader )
583 {
584   DALI_ASSERT_DEBUG(shader != NULL);
585
586   ShaderContainer& shaders = mImpl->shaders;
587
588   // Find the shader and destroy it
589   for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
590   {
591     Shader& current = **iter;
592     if ( &current == shader )
593     {
594       // Transfer ownership to the discard queue
595       // This keeps the shader alive, until the render-thread has finished with it
596       mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), shaders.Release( iter ) );
597
598       return;
599     }
600   }
601   // Should not reach here
602   DALI_ASSERT_DEBUG(false);
603 }
604
605 void UpdateManager::SetShaderProgram( Shader* shader,
606                                       ResourceId resourceId, size_t shaderHash, bool modifiesGeometry )
607 {
608   DALI_LOG_TRACE_METHOD_FMT(Debug::Filter::gShader, " - (id:%d hash:%d)\n", resourceId, shaderHash);
609
610   DALI_ASSERT_ALWAYS( NULL != shader && "shader is uninitialized" );
611
612   Integration::ShaderDataPtr shaderData( mImpl->resourceManager.GetShaderData(resourceId) );
613   if( shaderData )
614   {
615     shaderData->SetHashValue( shaderHash );
616     shaderData->SetResourceId( resourceId );
617
618     typedef MessageValue4< Shader, Integration::ResourceId, Integration::ShaderDataPtr, ProgramCache*, bool> DerivedType;
619
620     // Reserve some memory inside the render queue
621     unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
622
623     // Construct message in the render queue memory; note that delete should not be called on the return value
624     new (slot) DerivedType( shader, &Shader::SetProgram, resourceId, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
625   }
626 }
627
628 RenderTaskList* UpdateManager::GetRenderTaskList( bool systemLevel )
629 {
630   if ( !systemLevel )
631   {
632     // copy the list, this is only likely to happen once in application life cycle
633     return &(mImpl->taskList);
634   }
635   else
636   {
637     // copy the list, this is only likely to happen once in application life cycle
638     return &(mImpl->systemLevelTaskList);
639   }
640 }
641
642 void UpdateManager::AddGesture( PanGesture* gesture )
643 {
644   DALI_ASSERT_DEBUG( NULL != gesture );
645
646   mImpl->gestures.PushBack( gesture );
647 }
648
649 void UpdateManager::RemoveGesture( PanGesture* gesture )
650 {
651   DALI_ASSERT_DEBUG( gesture != NULL );
652
653   GestureContainer& gestures = mImpl->gestures;
654
655   // Find the gesture and destroy it
656   for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
657   {
658     PanGesture& current = **iter;
659     if ( &current == gesture )
660     {
661       mImpl->gestures.Erase( iter );
662       return;
663     }
664   }
665   // Should not reach here
666   DALI_ASSERT_DEBUG(false);
667 }
668
669 unsigned int* UpdateManager::ReserveMessageSlot( std::size_t size, bool updateScene )
670 {
671   return mImpl->messageQueue.ReserveMessageSlot( size, updateScene );
672 }
673
674 void UpdateManager::EventProcessingStarted()
675 {
676   mImpl->messageQueue.EventProcessingStarted();
677 }
678
679 bool UpdateManager::FlushQueue()
680 {
681   return mImpl->messageQueue.FlushQueue();
682 }
683
684 void UpdateManager::ResetNodeProperty( Node& node )
685 {
686   BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
687
688   node.ResetToBaseValues( bufferIndex );
689 }
690
691 void UpdateManager::ResetProperties()
692 {
693   PERF_MONITOR_START(PerformanceMonitor::RESET_PROPERTIES);
694
695   BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
696
697   // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
698   mImpl->animationFinishedDuringUpdate = false;
699
700   // Animated properties have to be reset to their original value each frame
701
702   // Reset node properties
703   if ( mImpl->root )
704   {
705     ResetNodeProperty( *mImpl->root );
706   }
707
708   if ( mImpl->systemLevelRoot )
709   {
710     ResetNodeProperty( *mImpl->systemLevelRoot );
711   }
712
713   // Reset the Connected Nodes
714   const std::set<Node*>::iterator endIter = mImpl->connectedNodes.end();
715   for( std::set<Node*>::iterator iter = mImpl->connectedNodes.begin(); endIter != iter; ++iter )
716   {
717     ResetNodeProperty( **iter );
718   }
719
720   // If a Node is disconnected, it may still be "active" (requires a reset in next frame)
721   for( std::set<Node*>::iterator iter = mImpl->activeDisconnectedNodes.begin(); mImpl->activeDisconnectedNodes.end() != iter; iter = mImpl->activeDisconnectedNodes.begin() )
722   {
723     Node* node = *iter;
724     node->ResetToBaseValues( bufferIndex );
725     node->SetActive( false );
726
727     // Move everything from activeDisconnectedNodes to disconnectedNodes (no need to reset again)
728     mImpl->activeDisconnectedNodes.erase( iter );
729     mImpl->disconnectedNodes.insert( node );
730   }
731
732   // Reset system-level render-task list properties to base values
733   const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
734
735   for (RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
736   {
737     (*iter)->ResetToBaseValues( bufferIndex );
738   }
739
740   // Reset render-task list properties to base values.
741   const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
742
743   for (RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
744   {
745     (*iter)->ResetToBaseValues( bufferIndex );
746   }
747
748   // Reset custom object properties to base values
749   for (OwnerContainer<PropertyOwner*>::Iterator iter = mImpl->customObjects.Begin(); iter != mImpl->customObjects.End(); ++iter)
750   {
751     (*iter)->ResetToBaseValues( bufferIndex );
752   }
753
754   mImpl->materials.ResetToBaseValues( bufferIndex );
755   mImpl->geometries.ResetToBaseValues( bufferIndex );
756   mImpl->propertyBuffers.ResetToBaseValues( bufferIndex );
757   mImpl->samplers.ResetToBaseValues( bufferIndex );
758
759
760   // Reset animatable shader properties to base values
761   for (ShaderIter iter = mImpl->shaders.Begin(); iter != mImpl->shaders.End(); ++iter)
762   {
763     (*iter)->ResetToBaseValues( bufferIndex );
764   }
765
766   PERF_MONITOR_END(PerformanceMonitor::RESET_PROPERTIES);
767 }
768
769 bool UpdateManager::ProcessGestures( unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds )
770 {
771   bool gestureUpdated( false );
772
773   // constrain gestures... (in construction order)
774   GestureContainer& gestures = mImpl->gestures;
775
776   for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
777   {
778     PanGesture& gesture = **iter;
779     gesture.ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() ); // Needs to be done every time as gesture data is written directly to an update-buffer rather than via a message
780     gestureUpdated |= gesture.UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
781   }
782
783   return gestureUpdated;
784 }
785
786 void UpdateManager::Animate( float elapsedSeconds )
787 {
788   PERF_MONITOR_START(PerformanceMonitor::ANIMATE_NODES);
789
790   AnimationContainer &animations = mImpl->animations;
791   AnimationIter iter = animations.Begin();
792   while ( iter != animations.End() )
793   {
794     Animation* animation = *iter;
795     bool finished = animation->Update(mSceneGraphBuffers.GetUpdateBufferIndex(), elapsedSeconds);
796
797     mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
798
799     // Remove animations that had been destroyed but were still waiting for an update
800     if (animation->GetState() == Animation::Destroyed)
801     {
802       iter = animations.Erase(iter);
803     }
804     else
805     {
806       ++iter;
807     }
808   }
809
810   if ( mImpl->animationFinishedDuringUpdate )
811   {
812     // The application should be notified by NotificationManager, in another thread
813     mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationFinishedNotifier );
814   }
815
816   PERF_MONITOR_END(PerformanceMonitor::ANIMATE_NODES);
817 }
818
819 void UpdateManager::ApplyConstraints()
820 {
821   PERF_MONITOR_START(PerformanceMonitor::APPLY_CONSTRAINTS);
822
823   BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
824
825   // constrain custom objects... (in construction order)
826   OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
827
828   const OwnerContainer< PropertyOwner* >::Iterator endIter = customObjects.End();
829   for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); endIter != iter; ++iter )
830   {
831     PropertyOwner& object = **iter;
832     ConstrainPropertyOwner( object, bufferIndex );
833   }
834
835   // constrain nodes... (in Depth First traversal order)
836   if ( mImpl->root )
837   {
838     ConstrainNodes( *(mImpl->root), bufferIndex );
839   }
840
841   if ( mImpl->systemLevelRoot )
842   {
843     ConstrainNodes( *(mImpl->systemLevelRoot), bufferIndex );
844   }
845
846   // constrain other property-owners after nodes as they are more likely to depend on a node's
847   // current frame property than vice versa. They tend to be final constraints (no further
848   // constraints depend on their properties)
849   // e.g. ShaderEffect uniform a function of Actor's position.
850   // Mesh vertex a function of Actor's position or world position.
851
852   // TODO: refactor this code (and reset nodes) as these are all just lists of property-owners
853   // they can be all processed in a super-list of property-owners.
854
855   // Constrain system-level render-tasks
856   const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
857
858   for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter )
859   {
860     RenderTask& task = **iter;
861     ConstrainPropertyOwner( task, bufferIndex );
862   }
863
864   // Constrain render-tasks
865   const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
866
867   for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter )
868   {
869     RenderTask& task = **iter;
870     ConstrainPropertyOwner( task, bufferIndex );
871   }
872
873   // Constrain Materials and geometries
874   mImpl->materials.ConstrainObjects( bufferIndex );
875   mImpl->geometries.ConstrainObjects( bufferIndex );
876   mImpl->samplers.ConstrainObjects( bufferIndex );
877   mImpl->propertyBuffers.ConstrainObjects( bufferIndex );
878
879   // constrain shaders... (in construction order)
880   ShaderContainer& shaders = mImpl->shaders;
881
882   for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
883   {
884     Shader& shader = **iter;
885     ConstrainPropertyOwner( shader, bufferIndex );
886   }
887
888   PERF_MONITOR_END(PerformanceMonitor::APPLY_CONSTRAINTS);
889 }
890
891 void UpdateManager::ProcessPropertyNotifications()
892 {
893   PropertyNotificationContainer &notifications = mImpl->propertyNotifications;
894   PropertyNotificationIter iter = notifications.Begin();
895
896   BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
897
898   while ( iter != notifications.End() )
899   {
900     PropertyNotification* notification = *iter;
901     bool valid = notification->Check( bufferIndex );
902     if(valid)
903     {
904       mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
905     }
906     ++iter;
907   }
908 }
909
910 void UpdateManager::UpdateNodes()
911 {
912   mImpl->nodeDirtyFlags = NothingFlag;
913
914   if ( !mImpl->root )
915   {
916     return;
917   }
918
919   PERF_MONITOR_START( PerformanceMonitor::UPDATE_NODES );
920
921   // Prepare resources, update shaders, update attachments, for each node
922   // And add the renderers to the sorted layers. Start from root, which is also a layer
923   mImpl->nodeDirtyFlags = UpdateNodesAndAttachments( *( mImpl->root ),
924                                                      mSceneGraphBuffers.GetUpdateBufferIndex(),
925                                                      mImpl->resourceManager,
926                                                      mImpl->renderQueue );
927
928   if ( mImpl->systemLevelRoot )
929   {
930     mImpl->nodeDirtyFlags |= UpdateNodesAndAttachments( *( mImpl->systemLevelRoot ),
931                                                         mSceneGraphBuffers.GetUpdateBufferIndex(),
932                                                         mImpl->resourceManager,
933                                                         mImpl->renderQueue );
934   }
935
936   PERF_MONITOR_END( PerformanceMonitor::UPDATE_NODES );
937 }
938
939 unsigned int UpdateManager::Update( float elapsedSeconds,
940                                     unsigned int lastVSyncTimeMilliseconds,
941                                     unsigned int nextVSyncTimeMilliseconds )
942 {
943   PERF_MONITOR_END(PerformanceMonitor::FRAME_RATE);   // Mark the End of the last frame
944   PERF_MONITOR_NEXT_FRAME();             // Prints out performance info for the last frame (if enabled)
945   PERF_MONITOR_START(PerformanceMonitor::FRAME_RATE); // Mark the start of this current frame
946
947   // Measure the time spent in UpdateManager::Update
948   PERF_MONITOR_START(PerformanceMonitor::UPDATE);
949
950   BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
951
952   // Update the frame time delta on the render thread.
953   mImpl->renderManager.SetFrameDeltaTime(elapsedSeconds);
954
955   // 1) Clear nodes/resources which were previously discarded
956   mImpl->discardQueue.Clear( bufferIndex );
957
958   // 2) Grab any loaded resources
959   bool resourceChanged = mImpl->resourceManager.UpdateCache( bufferIndex );
960
961   // 3) Process Touches & Gestures
962   mImpl->touchResampler.Update();
963   const bool gestureUpdated = ProcessGestures( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
964
965   const bool updateScene =                                            // The scene-graph requires an update if..
966       (mImpl->nodeDirtyFlags & RenderableUpdateFlags) ||              // ..nodes were dirty in previous frame OR
967       IsAnimationRunning() ||                                         // ..at least one animation is running OR
968       mImpl->messageQueue.IsSceneUpdateRequired() ||                  // ..a message that modifies the scene graph node tree is queued OR
969       resourceChanged ||                                              // ..one or more resources were updated/changed OR
970       gestureUpdated;                                                // ..a gesture property was updated
971
972   // Although the scene-graph may not require an update, we still need to synchronize double-buffered
973   // values if the scene was updated in the previous frame.
974   if( updateScene || mImpl->previousUpdateScene )
975   {
976     // 4) Reset properties from the previous update
977     ResetProperties();
978   }
979
980   // 5) Process the queued scene messages
981   mImpl->messageQueue.ProcessMessages();
982
983   // 6) Post Process Ids of resources updated by renderer
984   mImpl->resourceManager.PostProcessResources( bufferIndex );
985
986   // Although the scene-graph may not require an update, we still need to synchronize double-buffered
987   // renderer lists if the scene was updated in the previous frame.
988   // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
989   if( updateScene || mImpl->previousUpdateScene )
990   {
991     // 7) Animate
992     Animate( elapsedSeconds );
993
994     // 8) Apply Constraints
995     ApplyConstraints();
996
997     // 9) Check Property Notifications
998     ProcessPropertyNotifications();
999
1000     // 10) Clear the lists of renderable-attachments from the previous update
1001     ClearRenderables( mImpl->sortedLayers );
1002     ClearRenderables( mImpl->systemLevelSortedLayers );
1003
1004     // 11) Update node hierarchy and perform sorting / culling.
1005     //     This will populate each Layer with a list of renderers which are ready.
1006     UpdateNodes();
1007
1008     // 12) Prepare for the next render
1009     PERF_MONITOR_START(PerformanceMonitor::PREPARE_RENDERABLES);
1010
1011     PrepareRenderables( bufferIndex, mImpl->sortedLayers );
1012     PrepareRenderables( bufferIndex, mImpl->systemLevelSortedLayers );
1013     PERF_MONITOR_END(PerformanceMonitor::PREPARE_RENDERABLES);
1014
1015     PERF_MONITOR_START(PerformanceMonitor::PROCESS_RENDER_TASKS);
1016
1017     // 14) Process the RenderTasks; this creates the instructions for rendering the next frame.
1018     // reset the update buffer index and make sure there is enough room in the instruction container
1019     mImpl->renderInstructions.ResetAndReserve( mSceneGraphBuffers.GetUpdateBufferIndex(),
1020                                                mImpl->taskList.GetTasks().Count() + mImpl->systemLevelTaskList.GetTasks().Count() );
1021
1022     if ( NULL != mImpl->root )
1023     {
1024       ProcessRenderTasks(  bufferIndex,
1025                            mImpl->completeStatusManager,
1026                            mImpl->taskList,
1027                            *mImpl->root,
1028                            mImpl->sortedLayers,
1029                            mImpl->renderSortingHelper,
1030                            mImpl->renderInstructions );
1031
1032       // Process the system-level RenderTasks last
1033       if ( NULL != mImpl->systemLevelRoot )
1034       {
1035         ProcessRenderTasks(  bufferIndex,
1036                              mImpl->completeStatusManager,
1037                              mImpl->systemLevelTaskList,
1038                              *mImpl->systemLevelRoot,
1039                              mImpl->systemLevelSortedLayers,
1040                              mImpl->renderSortingHelper,
1041                              mImpl->renderInstructions );
1042       }
1043     }
1044   }
1045
1046   // check the countdown and notify (note, at the moment this is only done for normal tasks, not for systemlevel tasks)
1047   bool doRenderOnceNotify = false;
1048   mImpl->renderTaskWaiting = false;
1049   const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
1050   for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(), endIter = tasks.End();
1051         endIter != iter; ++iter )
1052   {
1053     RenderTask& renderTask(*(*iter));
1054
1055     renderTask.UpdateState();
1056
1057     if( renderTask.IsWaitingToRender() &&
1058         renderTask.ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
1059     {
1060       mImpl->renderTaskWaiting = true; // keep update/render threads alive
1061     }
1062
1063     if( renderTask.HasRendered() )
1064     {
1065       doRenderOnceNotify = true;
1066     }
1067   }
1068
1069   if( doRenderOnceNotify )
1070   {
1071     DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
1072     mImpl->notificationManager.QueueCompleteNotification( mImpl->taskList.GetCompleteNotificationInterface() );
1073   }
1074
1075   PERF_MONITOR_END(PerformanceMonitor::PROCESS_RENDER_TASKS);
1076
1077   // Macro is undefined in release build.
1078   SNAPSHOT_NODE_LOGGING;
1079
1080   // A ResetProperties() may be required in the next frame
1081   mImpl->previousUpdateScene = updateScene;
1082
1083   // Check whether further updates are required
1084   unsigned int keepUpdating = KeepUpdatingCheck( elapsedSeconds );
1085
1086 #ifdef PERFORMANCE_MONITOR_ENABLED
1087   // Always keep rendering when measuring FPS
1088   keepUpdating |= KeepUpdating::MONITORING_PERFORMANCE;
1089 #endif
1090
1091   // The update has finished; swap the double-buffering indices
1092   mSceneGraphBuffers.Swap();
1093
1094   // tell the update manager that we're done so the queue can be given to event thread
1095   mImpl->notificationManager.UpdateCompleted();
1096
1097   PERF_MONITOR_END(PerformanceMonitor::UPDATE);
1098
1099   return keepUpdating;
1100 }
1101
1102 unsigned int UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
1103 {
1104   // Update the duration set via Stage::KeepRendering()
1105   if ( mImpl->keepRenderingSeconds > 0.0f )
1106   {
1107     mImpl->keepRenderingSeconds -= elapsedSeconds;
1108   }
1109
1110   unsigned int keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
1111
1112   // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
1113   // Keep updating until no messages are received and no animations are running.
1114   // If an animation has just finished, update at least once more for Discard end-actions.
1115   // No need to check for renderQueue as there is always a render after update and if that
1116   // render needs another update it will tell the adaptor to call update again
1117
1118   if ( mImpl->keepRenderingSeconds > 0.0f )
1119   {
1120     keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
1121   }
1122
1123   if ( IsAnimationRunning() ||
1124        mImpl->animationFinishedDuringUpdate )
1125   {
1126     keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
1127   }
1128
1129   if ( mImpl->renderTaskWaiting )
1130   {
1131     keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
1132   }
1133
1134   return keepUpdatingRequest;
1135 }
1136
1137 void UpdateManager::SetBackgroundColor( const Vector4& color )
1138 {
1139   typedef MessageValue1< RenderManager, Vector4 > DerivedType;
1140
1141   // Reserve some memory inside the render queue
1142   unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1143
1144   // Construct message in the render queue memory; note that delete should not be called on the return value
1145   new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
1146 }
1147
1148 void UpdateManager::SetDefaultSurfaceRect( const Rect<int>& rect )
1149 {
1150   typedef MessageValue1< RenderManager, Rect<int> > DerivedType;
1151
1152   // Reserve some memory inside the render queue
1153   unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1154
1155   // Construct message in the render queue memory; note that delete should not be called on the return value
1156   new (slot) DerivedType( &mImpl->renderManager,  &RenderManager::SetDefaultSurfaceRect, rect );
1157 }
1158
1159 void UpdateManager::KeepRendering( float durationSeconds )
1160 {
1161   mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1162 }
1163
1164 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, bool systemLevel )
1165 {
1166   if ( !systemLevel )
1167   {
1168     // just copy the vector of pointers
1169     mImpl->sortedLayers = layers;
1170   }
1171   else
1172   {
1173     mImpl->systemLevelSortedLayers = layers;
1174   }
1175 }
1176
1177 } // namespace SceneGraph
1178
1179 } // namespace Internal
1180
1181 } // namespace Dali