2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 // Licensed under the Flora License, Version 1.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
8 // http://floralicense.org/license/
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.
18 #include <dali/internal/update/manager/update-manager.h>
24 #include <dali/public-api/common/stage.h>
26 #include <dali/integration-api/core.h>
27 #include <dali/integration-api/render-controller.h>
28 #include <dali/integration-api/shader-data.h>
29 #include <dali/integration-api/debug.h>
30 #include <dali/integration-api/dynamics/dynamics-world-settings.h>
32 #include <dali/internal/common/core-impl.h>
33 #include <dali/internal/common/owner-container.h>
34 #include <dali/internal/common/message.h>
36 #include <dali/internal/event/common/notification-manager.h>
37 #include <dali/internal/event/common/property-notification-impl.h>
38 #include <dali/internal/event/common/property-notifier.h>
39 #include <dali/internal/event/animation/animation-finished-notifier.h>
40 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
42 #include <dali/internal/update/animation/scene-graph-animator.h>
43 #include <dali/internal/update/animation/scene-graph-animation.h>
44 #include <dali/internal/update/common/discard-queue.h>
45 #include <dali/internal/update/common/double-buffered.h>
46 #include <dali/internal/update/manager/prepare-render-algorithms.h>
47 #include <dali/internal/update/manager/process-render-tasks.h>
48 #include <dali/internal/update/resources/resource-manager.h>
49 #include <dali/internal/update/resources/complete-status-manager.h>
50 #include <dali/internal/update/common/scene-graph-buffers.h>
51 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
52 #include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
53 #include <dali/internal/update/manager/sorted-layers.h>
54 #include <dali/internal/update/manager/update-algorithms.h>
55 #include <dali/internal/update/queue/update-message-queue.h>
56 #include <dali/internal/update/manager/update-manager-debug.h>
57 #include <dali/internal/update/controllers/render-message-dispatcher.h>
58 #include <dali/internal/update/controllers/scene-controller-impl.h>
59 #include <dali/internal/update/gestures/scene-graph-pan-gesture.h>
60 #include <dali/internal/update/modeling/scene-graph-material.h>
61 #include <dali/internal/update/node-attachments/scene-graph-camera-attachment.h>
62 #include <dali/internal/update/nodes/node.h>
63 #include <dali/internal/update/nodes/scene-graph-layer.h>
64 #include <dali/internal/update/dynamics/scene-graph-dynamics-world.h>
65 #include <dali/internal/update/touch/touch-resampler.h>
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/renderers/render-material.h>
73 #include <dali/internal/render/shaders/shader.h>
75 // Un-comment to enable node tree debug logging
76 //#define NODE_TREE_LOGGING 1
78 #if ( defined( DEBUG_ENABLED ) && defined( NODE_TREE_LOGGING ) )
79 #define SNAPSHOT_NODE_LOGGING \
80 const int FRAME_COUNT_TRIGGER = 16;\
81 if( mImpl->frameCounter >= FRAME_COUNT_TRIGGER )\
83 if ( NULL != mImpl->root )\
85 mImpl->frameCounter = 0;\
86 PrintNodeTree( *mImpl->root, mSceneGraphBuffers.GetUpdateBufferIndex(), "" );\
89 mImpl->frameCounter++;
91 #define SNAPSHOT_NODE_LOGGING
94 #if defined(DEBUG_ENABLED)
95 extern Debug::Filter* gRenderTaskLogFilter;
99 using namespace Dali::Integration;
100 using Dali::Internal::Update::MessageQueue;
114 const int DEFAULT_CAMERA_INDEX = -1;
116 void DestroyNodeSet( std::set<Node*>& nodeSet )
118 for( std::set<Node*>::iterator iter = nodeSet.begin(); iter != nodeSet.end(); ++iter )
122 // Call Node::OnDestroy as each node is destroyed
132 typedef OwnerContainer< Shader* > ShaderContainer;
133 typedef ShaderContainer::Iterator ShaderIter;
134 typedef ShaderContainer::ConstIterator ShaderConstIter;
136 typedef AnimatableMeshContainer::Iterator AnimatableMeshIter;
137 typedef AnimatableMeshContainer::ConstIterator AnimatableMeshConstIter;
138 typedef MaterialContainer::Iterator MaterialIter;
140 typedef OwnerContainer<PanGesture*> GestureContainer;
141 typedef GestureContainer::Iterator GestureIter;
142 typedef GestureContainer::ConstIterator GestureConstIter;
146 * Structure to contain UpdateManager internal data
148 struct UpdateManager::Impl
150 Impl( NotificationManager& notificationManager,
151 GlSyncAbstraction& glSyncAbstraction,
152 AnimationFinishedNotifier& animationFinishedNotifier,
153 PropertyNotifier& propertyNotifier,
154 ResourceManager& resourceManager,
155 DiscardQueue& discardQueue,
156 RenderController& renderController,
157 RenderManager& renderManager,
158 RenderQueue& renderQueue,
159 TextureCache& textureCache,
160 TouchResampler& touchResampler,
161 SceneGraphBuffers& sceneGraphBuffers )
163 renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ),
164 notificationManager( notificationManager ),
165 animationFinishedNotifier( animationFinishedNotifier ),
166 propertyNotifier( propertyNotifier ),
167 resourceManager( resourceManager ),
168 discardQueue( discardQueue ),
169 renderController( renderController ),
170 sceneController( NULL ),
171 renderManager( renderManager ),
172 renderQueue( renderQueue ),
173 renderInstructions( renderManager.GetRenderInstructionContainer() ),
174 completeStatusManager( glSyncAbstraction, renderMessageDispatcher, resourceManager ),
175 touchResampler( touchResampler ),
176 backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
177 taskList ( completeStatusManager ),
178 systemLevelTaskList ( completeStatusManager ),
180 systemLevelRoot( NULL ),
181 defaultShader( NULL ),
182 messageQueue( renderController, sceneGraphBuffers ),
183 dynamicsWorld( NULL ),
184 dynamicsChanged( false ),
185 keepRenderingSeconds( 0.0f ),
186 animationFinishedDuringUpdate( false ),
187 activeConstraints( 0 ),
188 nodeDirtyFlags( TransformFlag ), // set to TransformFlag to ensure full update the first time through Update()
189 previousUpdateScene( false ),
191 renderSortingHelper(),
192 renderTaskList( NULL ),
193 renderTaskWaiting( false )
195 sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue, textureCache, completeStatusManager );
200 // Disconnect render tasks from nodes, before destroying the nodes
201 RenderTaskList::RenderTaskContainer& tasks = taskList.GetTasks();
202 for (RenderTaskList::RenderTaskContainer::Iterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
204 (*iter)->SetSourceNode( NULL );
206 // ..repeat for system level RenderTasks
207 RenderTaskList::RenderTaskContainer& systemLevelTasks = systemLevelTaskList.GetTasks();
208 for (RenderTaskList::RenderTaskContainer::Iterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
210 (*iter)->SetSourceNode( NULL );
213 // UpdateManager owns the Nodes
214 DestroyNodeSet( activeDisconnectedNodes );
215 DestroyNodeSet( connectedNodes );
216 DestroyNodeSet( disconnectedNodes );
218 // If there is root, reset it, otherwise do nothing as rendering was never started
227 if( systemLevelRoot )
229 systemLevelRoot->OnDestroy();
231 delete systemLevelRoot;
232 systemLevelRoot = NULL;
235 sceneController->GetTextureCache().SetBufferIndices(NULL); // TODO - Remove
236 delete sceneController;
239 SceneGraphBuffers sceneGraphBuffers; ///< Used to keep track of which buffers are being written or read
240 RenderMessageDispatcher renderMessageDispatcher; ///< Used for passing messages to the render-thread
241 NotificationManager& notificationManager; ///< Queues notification messages for the event-thread.
242 AnimationFinishedNotifier& animationFinishedNotifier; ///< Provides notification to applications when animations are finished.
243 PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
244 ResourceManager& resourceManager; ///< resource manager
245 DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
246 RenderController& renderController; ///< render controller
247 SceneControllerImpl* sceneController; ///< scene controller
248 RenderManager& renderManager; ///< This is responsible for rendering the results of each "update"
249 RenderQueue& renderQueue; ///< Used to queue messages for the next render
250 RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions
251 CompleteStatusManager completeStatusManager; ///< Complete Status Manager
252 TouchResampler& touchResampler; ///< Used to resample touch events on every update.
254 Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
256 RenderTaskList taskList; ///< The list of scene graph render-tasks
257 RenderTaskList systemLevelTaskList; ///< Separate render-tasks for system-level content
259 Layer* root; ///< The root node (root is a layer)
260 Layer* systemLevelRoot; ///< A separate root-node for system-level content
261 std::set< Node* > activeDisconnectedNodes; ///< A container of new or modified nodes (without parent) owned by UpdateManager
262 std::set< Node* > connectedNodes; ///< A container of connected (with parent) nodes owned by UpdateManager
263 std::set< Node* > disconnectedNodes; ///< A container of inactive disconnected nodes (without parent) owned by UpdateManager
265 SortedLayerPointers sortedLayers; ///< A container of Layer pointers sorted by depth
266 SortedLayerPointers systemLevelSortedLayers; ///< A separate container of system-level Layers
268 OwnerContainer< PropertyOwner* > customObjects; ///< A container of owned objects (with custom properties)
270 AnimationContainer animations; ///< A container of owned animations
271 PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
273 Shader* defaultShader; ///< The default shader; owned by ShaderContainer
274 ShaderContainer shaders; ///< A container of owned shaders
275 AnimatableMeshContainer animatableMeshes; ///< A container of owned animatable meshes
276 MaterialContainer materials; ///< A container of owned materials
278 MessageQueue messageQueue; ///< The messages queued from the event-thread
280 OwnerPointer<DynamicsWorld> dynamicsWorld; ///< Wrapper for dynamics simulation
281 bool dynamicsChanged; ///< This is set to true if an object is changed in the dynamics simulation tick
283 float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
284 bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
286 unsigned int activeConstraints; ///< number of active constraints from previous frame
287 int nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
288 bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
290 int frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
291 RendererSortingHelper renderSortingHelper; ///< helper used to sort transparent renderers
293 Internal::RenderTaskList* renderTaskList; ///< Stores a pointer to the internal implementation to the render task list.
294 GestureContainer gestures; ///< A container of owned gesture detectors
295 bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
298 UpdateManager::UpdateManager( NotificationManager& notificationManager,
299 GlSyncAbstraction& glSyncAbstraction,
300 AnimationFinishedNotifier& animationFinishedNotifier,
301 PropertyNotifier& propertyNotifier,
302 ResourceManager& resourceManager,
303 DiscardQueue& discardQueue,
304 RenderController& controller,
305 RenderManager& renderManager,
306 RenderQueue& renderQueue,
307 TextureCache& textureCache,
308 TouchResampler& touchResampler )
311 mImpl = new Impl( notificationManager,
313 animationFinishedNotifier,
322 mSceneGraphBuffers );
324 textureCache.SetBufferIndices( &mSceneGraphBuffers );
327 UpdateManager::~UpdateManager()
332 void UpdateManager::SetRenderTaskList( Internal::RenderTaskList* renderTaskList )
334 mImpl->renderTaskList = renderTaskList;
337 EventToUpdate& UpdateManager::GetEventToUpdate()
339 return mImpl->messageQueue;
342 void UpdateManager::InstallRoot( SceneGraph::Layer* layer, bool systemLevel )
344 DALI_ASSERT_DEBUG( layer->IsLayer() );
345 DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
349 DALI_ASSERT_DEBUG( mImpl->root == NULL && "Root Node already installed" );
354 DALI_ASSERT_DEBUG( mImpl->systemLevelRoot == NULL && "System-level Root Node already installed" );
355 mImpl->systemLevelRoot = layer;
358 layer->SetRoot(true);
361 void UpdateManager::AddNode( Node* node )
363 DALI_ASSERT_ALWAYS( NULL != node );
364 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
366 mImpl->activeDisconnectedNodes.insert( node ); // Takes ownership of node
369 void UpdateManager::ConnectNode( Node* parent, Node* node )
371 DALI_ASSERT_ALWAYS( NULL != parent );
372 DALI_ASSERT_ALWAYS( NULL != node );
373 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
375 // Move from active/disconnectedNodes to connectedNodes
376 std::set<Node*>::size_type removed = mImpl->activeDisconnectedNodes.erase( node );
379 removed = mImpl->disconnectedNodes.erase( node );
380 DALI_ASSERT_ALWAYS( removed );
382 mImpl->connectedNodes.insert( node );
384 node->SetActive( true );
386 parent->ConnectChild( node );
389 void UpdateManager::DisconnectNode( Node* node )
391 Node* parent = node->GetParent();
392 DALI_ASSERT_ALWAYS( NULL != parent );
393 parent->SetDirtyFlag( ChildDeletedFlag ); // make parent dirty so that render items dont get reused
395 // Move from connectedNodes to activeDisconnectedNodes (reset properties next frame)
396 parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node, mImpl->connectedNodes, mImpl->activeDisconnectedNodes );
399 void UpdateManager::SetNodeActive( Node* node )
401 DALI_ASSERT_ALWAYS( NULL != node );
402 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
404 // Move from disconnectedNodes to activeDisconnectedNodes (reset properties next frame)
405 std::set<Node*>::size_type removed = mImpl->disconnectedNodes.erase( node );
406 DALI_ASSERT_ALWAYS( removed );
407 mImpl->activeDisconnectedNodes.insert( node );
409 node->SetActive( true );
412 void UpdateManager::DestroyNode( Node* node )
414 DALI_ASSERT_ALWAYS( NULL != node );
415 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
417 // Transfer ownership from new/disconnectedNodes to the discard queue
418 // This keeps the nodes alive, until the render-thread has finished with them
419 std::set<Node*>::size_type removed = mImpl->activeDisconnectedNodes.erase( node );
422 removed = mImpl->disconnectedNodes.erase( node );
423 DALI_ASSERT_ALWAYS( removed );
425 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
427 // Notify the Node about impending destruction
431 void UpdateManager::AttachToNode( Node* node, NodeAttachment* attachment )
433 DALI_ASSERT_DEBUG( node != NULL );
434 DALI_ASSERT_DEBUG( attachment != NULL );
436 // attach node to attachment first so that parent is known by the time attachment is connected
437 node->Attach( *attachment ); // node takes ownership
438 attachment->ConnectToSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
441 void UpdateManager::AddObject( PropertyOwner* object )
443 DALI_ASSERT_DEBUG( NULL != object );
445 mImpl->customObjects.PushBack( object );
448 void UpdateManager::RemoveObject( PropertyOwner* object )
450 DALI_ASSERT_DEBUG( NULL != object );
452 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
454 // Find the object and destroy it
455 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); iter != customObjects.End(); ++iter )
457 PropertyOwner* current = *iter;
458 if ( current == object )
460 customObjects.Erase( iter );
465 // Should not reach here
466 DALI_ASSERT_DEBUG(false);
469 void UpdateManager::AddAnimation( Animation* animation )
471 mImpl->animations.PushBack( animation );
474 void UpdateManager::StopAnimation( Animation* animation )
476 DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
478 bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
480 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
483 void UpdateManager::RemoveAnimation( Animation* animation )
485 DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
487 animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
489 DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
492 bool UpdateManager::IsAnimationRunning() const
494 bool isRunning(false);
495 AnimationContainer& animations = mImpl->animations;
497 // Find any animation that isn't stopped or paused
499 const AnimationIter endIter = animations.End();
500 for ( AnimationIter iter = animations.Begin(); !isRunning && iter != endIter; ++iter )
502 const Animation::State state = (*iter)->GetState();
504 if (state != Animation::Stopped &&
505 state != Animation::Paused)
514 void UpdateManager::AddPropertyNotification( PropertyNotification* propertyNotification )
516 mImpl->propertyNotifications.PushBack( propertyNotification );
519 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
521 PropertyNotificationContainer &propertyNotifications = mImpl->propertyNotifications;
522 PropertyNotificationIter iter = propertyNotifications.Begin();
524 while ( iter != propertyNotifications.End() )
526 if( *iter == propertyNotification )
528 propertyNotifications.Erase(iter);
535 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
537 DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
538 propertyNotification->SetNotifyMode( notifyMode );
541 Shader* UpdateManager::GetDefaultShader()
543 return mImpl->defaultShader;
546 void UpdateManager::AddShader( Shader* shader )
548 DALI_ASSERT_DEBUG( NULL != shader );
550 // Note: The first shader added becomes the default shader
551 if( NULL == mImpl->defaultShader )
553 mImpl->defaultShader = shader;
556 mImpl->shaders.PushBack( shader );
558 // Allows the shader to dispatch texture requests to the cache and "save shader"
559 // requests to the resource manager from the render thread.
560 shader->Initialize( mImpl->renderManager, mImpl->renderQueue, mImpl->sceneController->GetTextureCache() );
563 void UpdateManager::RemoveShader(Shader* shader)
565 DALI_ASSERT_DEBUG(shader != NULL);
567 ShaderContainer& shaders = mImpl->shaders;
569 // Find the shader and destroy it
570 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
572 Shader& current = **iter;
573 if ( ¤t == shader )
575 // Transfer ownership to the discard queue
576 // This keeps the shader alive, until the render-thread has finished with it
577 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), shaders.Release( iter ) );
582 // Should not reach here
583 DALI_ASSERT_DEBUG(false);
586 void UpdateManager::SetShaderProgram( Shader* shader, GeometryType geometryType, ShaderSubTypes subType, ResourceId resourceId, size_t shaderHash )
588 DALI_LOG_TRACE_METHOD_FMT(Debug::Filter::gShader, " - (geometryType:%d subType:%d id:%d hash:%d)\n", geometryType, subType, resourceId, shaderHash);
590 DALI_ASSERT_ALWAYS( NULL != shader && "shader is uninitialized" );
592 Integration::ShaderDataPtr shaderData( mImpl->resourceManager.GetShaderData(resourceId) );
593 shaderData->SetHashValue( shaderHash );
597 // This is done in the render thread, to allow GL program compilation
598 // Will trigger a NotifySaveRequest back to updateManager to forward onto ResourceClient
599 typedef MessageValue5< Shader, GeometryType, Internal::ShaderSubTypes, Integration::ResourceId, Integration::ShaderDataPtr, Context* > DerivedType;
601 // Reserve some memory inside the render queue
602 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
604 // Construct message in the render queue memory; note that delete should not be called on the return value
605 new (slot) DerivedType( shader, &Shader::SetProgram, geometryType, subType, resourceId, shaderData, &(mImpl->renderManager.GetContext()) );
609 void UpdateManager::AddAnimatableMesh( AnimatableMesh* animatableMesh )
611 mImpl->animatableMeshes.PushBack(animatableMesh);
614 void UpdateManager::RemoveAnimatableMesh( AnimatableMesh* animatableMesh )
616 DALI_ASSERT_DEBUG(animatableMesh != NULL);
618 AnimatableMeshContainer& animatableMeshes = mImpl->animatableMeshes;
620 // Find the animatableMesh and destroy it
621 for ( AnimatableMeshIter iter = animatableMeshes.Begin(); iter != animatableMeshes.End(); ++iter )
623 AnimatableMesh& current = **iter;
624 if ( ¤t == animatableMesh )
626 animatableMeshes.Erase( iter );
632 void UpdateManager::AddMaterial( Material* material )
634 DALI_ASSERT_DEBUG( NULL != material );
636 mImpl->materials.PushBack( material );
637 RenderMaterial* renderMaterial = new RenderMaterial();
639 typedef MessageValue1< RenderManager, RenderMaterial* > DerivedType;
641 // Reserve some memory inside the render queue
642 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
644 // Construct message in the render queue memory; note that delete should not be called on the return value
645 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddRenderMaterial, renderMaterial );
647 material->SetRenderMaterial( renderMaterial );
648 material->OnStageConnection( *mImpl->sceneController );
651 void UpdateManager::RemoveMaterial( Material* theMaterial )
653 // Caused by last reference to material being released (e.g. app or internal mesh-actor)
655 for ( MaterialIter iter=mImpl->materials.Begin(), end=mImpl->materials.End() ; iter != end ; ++iter )
657 const Material* aMaterial = *iter;
659 if( aMaterial == theMaterial )
661 typedef MessageValue1< RenderManager, RenderMaterial* > DerivedType;
663 // Reserve some memory inside the render queue
664 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
666 // Construct message in the render queue memory; note that delete should not be called on the return value
667 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveRenderMaterial, theMaterial->GetRenderMaterial() );
669 mImpl->materials.Erase( iter );
675 RenderTaskList* UpdateManager::GetRenderTaskList( bool systemLevel )
679 // copy the list, this is only likely to happen once in application life cycle
680 return &(mImpl->taskList);
684 // copy the list, this is only likely to happen once in application life cycle
685 return &(mImpl->systemLevelTaskList);
689 void UpdateManager::AddGesture( PanGesture* gesture )
691 DALI_ASSERT_DEBUG( NULL != gesture );
693 mImpl->gestures.PushBack( gesture );
696 void UpdateManager::RemoveGesture( PanGesture* gesture )
698 DALI_ASSERT_DEBUG( gesture != NULL );
700 GestureContainer& gestures = mImpl->gestures;
702 // Find the gesture and destroy it
703 for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
705 PanGesture& current = **iter;
706 if ( ¤t == gesture )
708 mImpl->gestures.Erase( iter );
712 // Should not reach here
713 DALI_ASSERT_DEBUG(false);
716 void UpdateManager::ResetNodeProperty( Node& node )
718 node.ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
721 void UpdateManager::ResetProperties()
723 PERF_MONITOR_START(PerformanceMonitor::RESET_PROPERTIES);
725 // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
726 mImpl->animationFinishedDuringUpdate = false;
728 // Animated properties have to be reset to their original value each frame
730 // Reset node properties
733 ResetNodeProperty( *mImpl->root );
736 if ( mImpl->systemLevelRoot )
738 ResetNodeProperty( *mImpl->systemLevelRoot );
741 // Reset the Connected Nodes
742 const std::set<Node*>::iterator endIter = mImpl->connectedNodes.end();
743 for( std::set<Node*>::iterator iter = mImpl->connectedNodes.begin(); endIter != iter; ++iter )
745 ResetNodeProperty( **iter );
748 // If a Node is disconnected, it may still be "active" (requires a reset in next frame)
749 for( std::set<Node*>::iterator iter = mImpl->activeDisconnectedNodes.begin(); mImpl->activeDisconnectedNodes.end() != iter; iter = mImpl->activeDisconnectedNodes.begin() )
752 node->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
753 node->SetActive( false );
755 // Move everything from activeDisconnectedNodes to disconnectedNodes (no need to reset again)
756 mImpl->activeDisconnectedNodes.erase( iter );
757 mImpl->disconnectedNodes.insert( node );
760 // Reset system-level render-task list properties to base values
761 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
763 for (RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
765 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
768 // Reset render-task list properties to base values.
769 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
771 for (RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
773 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
776 // Reset custom object properties to base values
777 for (OwnerContainer<PropertyOwner*>::Iterator iter = mImpl->customObjects.Begin(); iter != mImpl->customObjects.End(); ++iter)
779 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
782 // Reset animatable shader properties to base values
783 for (ShaderIter iter = mImpl->shaders.Begin(); iter != mImpl->shaders.End(); ++iter)
785 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
788 // Reset animatable mesh properties to base values
789 for ( AnimatableMeshIter iter = mImpl->animatableMeshes.Begin(); iter != mImpl->animatableMeshes.End(); ++iter )
791 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
794 // Reset gesture properties to base values
795 for ( GestureIter iter = mImpl->gestures.Begin(); iter != mImpl->gestures.End(); ++iter )
797 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
800 PERF_MONITOR_END(PerformanceMonitor::RESET_PROPERTIES);
803 void UpdateManager::ProcessGestures( unsigned int lastVSyncTime, unsigned int nextVSyncTime )
805 // constrain gestures... (in construction order)
806 GestureContainer& gestures = mImpl->gestures;
808 for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
810 PanGesture& gesture = **iter;
811 gesture.UpdateProperties( lastVSyncTime, nextVSyncTime );
815 void UpdateManager::Animate( float elapsedSeconds )
817 PERF_MONITOR_START(PerformanceMonitor::ANIMATE_NODES);
819 AnimationContainer &animations = mImpl->animations;
820 AnimationIter iter = animations.Begin();
821 while ( iter != animations.End() )
823 Animation* animation = *iter;
824 bool finished = animation->Update(mSceneGraphBuffers.GetUpdateBufferIndex(), elapsedSeconds);
826 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
828 // Remove animations that had been destroyed but were still waiting for an update
829 if (animation->GetState() == Animation::Destroyed)
831 iter = animations.Erase(iter);
839 if ( mImpl->animationFinishedDuringUpdate )
841 // The application should be notified by NotificationManager, in another thread
842 mImpl->notificationManager.QueueMessage( AnimationFinishedMessage( mImpl->animationFinishedNotifier ) );
845 PERF_MONITOR_END(PerformanceMonitor::ANIMATE_NODES);
848 void UpdateManager::ApplyConstraints()
850 PERF_MONITOR_START(PerformanceMonitor::APPLY_CONSTRAINTS);
852 mImpl->activeConstraints = 0;
854 // constrain custom objects... (in construction order)
855 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
857 const OwnerContainer< PropertyOwner* >::Iterator endIter = customObjects.End();
858 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); endIter != iter; ++iter )
860 PropertyOwner& object = **iter;
861 mImpl->activeConstraints += ConstrainPropertyOwner( object, mSceneGraphBuffers.GetUpdateBufferIndex() );
864 // constrain nodes... (in Depth First traversal order)
867 mImpl->activeConstraints += ConstrainNodes( *(mImpl->root), mSceneGraphBuffers.GetUpdateBufferIndex() );
870 if ( mImpl->systemLevelRoot )
872 mImpl->activeConstraints += ConstrainNodes( *(mImpl->systemLevelRoot), mSceneGraphBuffers.GetUpdateBufferIndex() );
875 // constrain other property-owners after nodes as they are more likely to depend on a node's
876 // current frame property than vice versa. They tend to be final constraints (no further
877 // constraints depend on their properties)
878 // e.g. ShaderEffect uniform a function of Actor's position.
879 // Mesh vertex a function of Actor's position or world position.
881 // TODO: refactor this code (and reset nodes) as these are all just lists of property-owners
882 // they can be all processed in a super-list of property-owners.
884 // Constrain system-level render-tasks
885 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
887 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter )
889 RenderTask& task = **iter;
890 mImpl->activeConstraints += ConstrainPropertyOwner( task, mSceneGraphBuffers.GetUpdateBufferIndex() );
893 // Constrain render-tasks
894 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
896 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter )
898 RenderTask& task = **iter;
899 mImpl->activeConstraints += ConstrainPropertyOwner( task, mSceneGraphBuffers.GetUpdateBufferIndex() );
902 // constrain meshes (in construction order)
903 AnimatableMeshContainer& meshes = mImpl->animatableMeshes;
904 for ( AnimatableMeshIter iter = meshes.Begin(); iter != meshes.End(); ++iter )
906 AnimatableMesh& mesh = **iter;
907 mImpl->activeConstraints += ConstrainPropertyOwner( mesh, mSceneGraphBuffers.GetUpdateBufferIndex() );
910 // constrain shaders... (in construction order)
911 ShaderContainer& shaders = mImpl->shaders;
913 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
915 Shader& shader = **iter;
916 mImpl->activeConstraints += ConstrainPropertyOwner( shader, mSceneGraphBuffers.GetUpdateBufferIndex() );
919 PERF_MONITOR_END(PerformanceMonitor::APPLY_CONSTRAINTS);
922 void UpdateManager::ProcessPropertyNotifications()
924 PropertyNotificationContainer ¬ifications = mImpl->propertyNotifications;
925 PropertyNotificationIter iter = notifications.Begin();
927 while ( iter != notifications.End() )
929 PropertyNotification* notification = *iter;
931 bool valid = notification->Check( mSceneGraphBuffers.GetUpdateBufferIndex() );
935 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
941 void UpdateManager::UpdateNodes()
943 mImpl->nodeDirtyFlags = NothingFlag;
950 PERF_MONITOR_START( PerformanceMonitor::UPDATE_NODES );
952 Shader* defaultShader = GetDefaultShader();
954 if ( NULL != defaultShader )
956 // Prepare resources, update shaders, update attachments, for each node
957 // And add the renderers to the sorted layers. Start from root, which is also a layer
958 mImpl->nodeDirtyFlags = UpdateNodesAndAttachments( *( mImpl->root ),
959 mSceneGraphBuffers.GetUpdateBufferIndex(),
960 mImpl->resourceManager,
964 if ( mImpl->systemLevelRoot )
966 mImpl->nodeDirtyFlags |= UpdateNodesAndAttachments( *( mImpl->systemLevelRoot ),
967 mSceneGraphBuffers.GetUpdateBufferIndex(),
968 mImpl->resourceManager,
974 PERF_MONITOR_END( PerformanceMonitor::UPDATE_NODES );
977 void UpdateManager::UpdateMeshes( BufferIndex updateBufferIndex, AnimatableMeshContainer& meshes )
979 for ( AnimatableMeshIter iter = meshes.Begin(); iter != meshes.End(); ++iter )
981 AnimatableMesh& current = **iter;
982 current.UpdateMesh( updateBufferIndex );
986 void UpdateManager::UpdateMaterials( BufferIndex updateBufferIndex, MaterialContainer& materials )
988 for( MaterialIter iter = materials.Begin(), end = materials.End(); iter != end; iter++ )
990 Material* material = *iter;
991 material->PrepareResources( updateBufferIndex, mImpl->resourceManager );
995 void UpdateManager::PrepareMaterials( BufferIndex updateBufferIndex, MaterialContainer& materials )
997 for( MaterialIter iter = materials.Begin(), end = materials.End(); iter != end; iter++ )
999 Material* material = *iter;
1000 material->PrepareRender( updateBufferIndex );
1004 unsigned int UpdateManager::Update( float elapsedSeconds, unsigned int lastVSyncTime, unsigned int nextVSyncTime )
1006 PERF_MONITOR_END(PerformanceMonitor::FRAME_RATE); // Mark the End of the last frame
1007 PERF_MONITOR_NEXT_FRAME(); // Prints out performance info for the last frame (if enabled)
1008 PERF_MONITOR_START(PerformanceMonitor::FRAME_RATE); // Mark the start of this current frame
1010 // Measure the time spent in UpdateManager::Update
1011 PERF_MONITOR_START(PerformanceMonitor::UPDATE);
1013 // Update the frame time delta on the render thread.
1014 mImpl->renderManager.SetFrameDeltaTime(elapsedSeconds);
1016 // 1) Clear nodes/resources which were previously discarded
1017 mImpl->discardQueue.Clear( mSceneGraphBuffers.GetUpdateBufferIndex() );
1019 // 2) Grab any loaded resources
1020 bool resourceChanged = mImpl->resourceManager.UpdateCache( mSceneGraphBuffers.GetUpdateBufferIndex() );
1022 const bool updateScene = // The scene-graph requires an update if..
1023 mImpl->activeConstraints != 0 || // ..constraints were active in previous frame OR
1024 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
1025 IsAnimationRunning() || // ..at least one animation is running OR
1026 mImpl->dynamicsChanged || // ..there was a change in the dynamics simulation OR
1027 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued
1028 resourceChanged; // one or more resources were updated/changed
1030 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
1031 // values if the scene was updated in the previous frame.
1032 if( updateScene || mImpl->previousUpdateScene )
1034 // 3) Reset properties from the previous update
1038 // 4) Process the queued scene messages
1039 mImpl->messageQueue.ProcessMessages();
1041 // 5) Post Process Ids of resources updated by renderer
1042 mImpl->resourceManager.PostProcessResources( mSceneGraphBuffers.GetUpdateBufferIndex() );
1044 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
1045 // renderer lists if the scene was updated in the previous frame.
1046 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
1047 if( updateScene || mImpl->previousUpdateScene )
1049 // 6) Process Touches & Gestures
1050 mImpl->touchResampler.Update();
1051 ProcessGestures( lastVSyncTime, nextVSyncTime );
1054 Animate( elapsedSeconds );
1056 // 8) Apply Constraints
1059 // 9) Update dynamics simulation
1060 mImpl->dynamicsChanged = false;
1061 if( mImpl->dynamicsWorld )
1063 mImpl->dynamicsChanged = mImpl->dynamicsWorld->Update( elapsedSeconds );
1066 // 10) Check Property Notifications
1067 ProcessPropertyNotifications();
1069 // 11) Clear the lists of renderable-attachments from the previous update
1070 ClearRenderables( mImpl->sortedLayers );
1071 ClearRenderables( mImpl->systemLevelSortedLayers );
1073 // 12) Update animated meshes
1074 UpdateMeshes( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->animatableMeshes );
1076 // 13) Update materials. Prepares image resources
1077 UpdateMaterials( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->materials );
1079 // 14) Update node hierarchy and perform sorting / culling.
1080 // This will populate each Layer with a list of renderers which are ready.
1083 // 15) Prepare for the next render
1084 PERF_MONITOR_START(PerformanceMonitor::PREPARE_RENDERABLES);
1085 PrepareMaterials( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->materials );
1086 PrepareRenderables( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->sortedLayers );
1087 PrepareRenderables( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->systemLevelSortedLayers );
1088 PERF_MONITOR_END(PerformanceMonitor::PREPARE_RENDERABLES);
1090 PERF_MONITOR_START(PerformanceMonitor::PROCESS_RENDER_TASKS);
1092 // 16) Process the RenderTasks; this creates the instructions for rendering the next frame.
1093 // reset the update buffer index and make sure there is enough room in the instruction container
1094 mImpl->renderInstructions.ResetAndReserve( mSceneGraphBuffers.GetUpdateBufferIndex(),
1095 mImpl->taskList.GetTasks().Count() + mImpl->systemLevelTaskList.GetTasks().Count() );
1097 if ( NULL != mImpl->root )
1099 ProcessRenderTasks( mSceneGraphBuffers.GetUpdateBufferIndex(),
1100 mImpl->completeStatusManager,
1103 mImpl->sortedLayers,
1104 mImpl->renderSortingHelper,
1105 mImpl->renderInstructions );
1107 // Process the system-level RenderTasks last
1108 if ( NULL != mImpl->systemLevelRoot )
1110 ProcessRenderTasks( mSceneGraphBuffers.GetUpdateBufferIndex(),
1111 mImpl->completeStatusManager,
1112 mImpl->systemLevelTaskList,
1113 *mImpl->systemLevelRoot,
1114 mImpl->systemLevelSortedLayers,
1115 mImpl->renderSortingHelper,
1116 mImpl->renderInstructions );
1119 // if dynamics enabled and active...update matrices for debug drawing
1120 if( mImpl->dynamicsWorld && mImpl->dynamicsChanged )
1122 RenderTask* task(mImpl->taskList.GetTasks()[0]);
1125 mImpl->dynamicsWorld->UpdateMatrices( task->GetProjectionMatrix(mSceneGraphBuffers.GetUpdateBufferIndex()),
1126 task->GetViewMatrix(mSceneGraphBuffers.GetUpdateBufferIndex()) );
1132 // check the countdown and notify
1133 bool doRenderOnceNotify = false;
1134 mImpl->renderTaskWaiting = false;
1135 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
1136 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(), endIter = tasks.End();
1137 endIter != iter; ++iter )
1139 RenderTask& renderTask(*(*iter));
1141 if( renderTask.IsWaitingToRender() )
1143 mImpl->renderTaskWaiting = true; // keep update/render threads alive
1146 if( renderTask.HasRendered() )
1148 doRenderOnceNotify = true;
1152 if( doRenderOnceNotify )
1154 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
1155 mImpl->notificationManager.QueueMessage( NotifyFinishedMessage( *mImpl->renderTaskList ) );
1158 PERF_MONITOR_END(PerformanceMonitor::PROCESS_RENDER_TASKS);
1160 // Macro is undefined in release build.
1161 SNAPSHOT_NODE_LOGGING;
1163 // A ResetProperties() may be required in the next frame
1164 mImpl->previousUpdateScene = updateScene;
1166 // Check whether further updates are required
1167 unsigned int keepUpdating = KeepUpdatingCheck( elapsedSeconds );
1169 #ifdef PERFORMANCE_MONITOR_ENABLED
1170 // Always keep rendering when measuring FPS
1171 keepUpdating |= KeepUpdating::MONITORING_PERFORMANCE;
1174 // The update has finished; swap the double-buffering indices
1175 mSceneGraphBuffers.Swap();
1177 PERF_MONITOR_END(PerformanceMonitor::UPDATE);
1179 return keepUpdating;
1182 unsigned int UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
1184 // Update the duration set via Stage::KeepRendering()
1185 if ( mImpl->keepRenderingSeconds > 0.0f )
1187 mImpl->keepRenderingSeconds -= elapsedSeconds;
1190 unsigned int keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
1192 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
1193 // Keep updating until no messages are received and no animations are running.
1194 // If an animation has just finished, update at least once more for Discard end-actions.
1195 // No need to check for renderQueue as there is always a render after update and if that
1196 // render needs another update it will tell the adaptor to call update again
1198 if ( mImpl->keepRenderingSeconds > 0.0f )
1200 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
1203 if ( !mImpl->messageQueue.WasEmpty() )
1205 keepUpdatingRequest |= KeepUpdating::INCOMING_MESSAGES;
1208 if ( IsAnimationRunning() ||
1209 mImpl->animationFinishedDuringUpdate )
1211 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
1214 if ( mImpl->dynamicsChanged )
1216 keepUpdatingRequest |= KeepUpdating::DYNAMICS_CHANGED;
1219 if ( mImpl->renderTaskWaiting )
1221 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
1224 return keepUpdatingRequest;
1227 void UpdateManager::SetBackgroundColor( const Vector4& color )
1229 typedef MessageValue1< RenderManager, Vector4 > DerivedType;
1231 // Reserve some memory inside the render queue
1232 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1234 // Construct message in the render queue memory; note that delete should not be called on the return value
1235 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
1238 void UpdateManager::SetDefaultSurfaceRect( const Rect<int>& rect )
1240 typedef MessageValue1< RenderManager, Rect<int> > DerivedType;
1242 // Reserve some memory inside the render queue
1243 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1245 // Construct message in the render queue memory; note that delete should not be called on the return value
1246 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1249 void UpdateManager::KeepRendering( float durationSeconds )
1251 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1254 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, bool systemLevel )
1258 // just copy the vector of pointers
1259 mImpl->sortedLayers = layers;
1263 mImpl->systemLevelSortedLayers = layers;
1267 void UpdateManager::InitializeDynamicsWorld( DynamicsWorld* dynamicsWorld, Integration::DynamicsWorldSettings* worldSettings, Shader* debugShader )
1269 dynamicsWorld->Initialize( mImpl->sceneController, worldSettings, debugShader, &mSceneGraphBuffers );
1270 mImpl->dynamicsWorld = dynamicsWorld;
1272 typedef MessageValue1< RenderManager, DynamicsDebugRenderer* > DerivedType;
1274 // Reserve some memory inside the render queue
1275 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1277 // Construct message in the render queue memory; note that delete should not be called on the return value
1278 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::InitializeDynamicsDebugRenderer, &dynamicsWorld->GetDebugRenderer() );
1281 void UpdateManager::TerminateDynamicsWorld()
1283 mImpl->dynamicsWorld.Reset();
1286 } // namespace SceneGraph
1288 } // namespace Internal