2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/internal/update/manager/update-manager.h>
22 #include <dali/public-api/common/stage.h>
23 #include <dali/public-api/common/set-wrapper.h>
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>
30 #include <dali/internal/common/core-impl.h>
31 #include <dali/internal/common/owner-container.h>
32 #include <dali/internal/common/message.h>
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>
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/manager/prepare-render-algorithms.h>
42 #include <dali/internal/update/manager/process-render-tasks.h>
43 #include <dali/internal/update/resources/resource-manager.h>
44 #include <dali/internal/update/resources/complete-status-manager.h>
45 #include <dali/internal/update/common/scene-graph-buffers.h>
46 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
47 #include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
48 #include <dali/internal/update/manager/sorted-layers.h>
49 #include <dali/internal/update/manager/update-algorithms.h>
50 #include <dali/internal/update/queue/update-message-queue.h>
51 #include <dali/internal/update/manager/update-manager-debug.h>
52 #include <dali/internal/update/controllers/render-message-dispatcher.h>
53 #include <dali/internal/update/controllers/scene-controller-impl.h>
54 #include <dali/internal/update/gestures/scene-graph-pan-gesture.h>
55 #include <dali/internal/update/modeling/scene-graph-material.h>
56 #include <dali/internal/update/node-attachments/scene-graph-camera-attachment.h>
57 #include <dali/internal/update/nodes/node.h>
58 #include <dali/internal/update/nodes/scene-graph-layer.h>
59 #include <dali/internal/update/touch/touch-resampler.h>
61 #include <dali/internal/render/common/render-instruction-container.h>
62 #include <dali/internal/render/common/render-manager.h>
63 #include <dali/internal/render/queue/render-queue.h>
64 #include <dali/internal/render/common/performance-monitor.h>
65 #include <dali/internal/render/gl-resources/texture-cache.h>
66 #include <dali/internal/render/renderers/render-material.h>
67 #include <dali/internal/render/shaders/shader.h>
69 #ifdef DYNAMICS_SUPPORT
70 #include <dali/integration-api/dynamics/dynamics-world-settings.h>
71 #include <dali/internal/update/dynamics/scene-graph-dynamics-world.h>
74 // Un-comment to enable node tree debug logging
75 //#define NODE_TREE_LOGGING 1
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 )\
82 if ( NULL != mImpl->root )\
84 mImpl->frameCounter = 0;\
85 PrintNodeTree( *mImpl->root, mSceneGraphBuffers.GetUpdateBufferIndex(), "" );\
88 mImpl->frameCounter++;
90 #define SNAPSHOT_NODE_LOGGING
93 #if defined(DEBUG_ENABLED)
94 extern Debug::Filter* gRenderTaskLogFilter;
98 using namespace Dali::Integration;
99 using Dali::Internal::Update::MessageQueue;
113 void DestroyNodeSet( std::set<Node*>& nodeSet )
115 for( std::set<Node*>::iterator iter = nodeSet.begin(); iter != nodeSet.end(); ++iter )
119 // Call Node::OnDestroy as each node is destroyed
129 typedef OwnerContainer< Shader* > ShaderContainer;
130 typedef ShaderContainer::Iterator ShaderIter;
131 typedef ShaderContainer::ConstIterator ShaderConstIter;
133 typedef AnimatableMeshContainer::Iterator AnimatableMeshIter;
134 typedef AnimatableMeshContainer::ConstIterator AnimatableMeshConstIter;
135 typedef MaterialContainer::Iterator MaterialIter;
137 typedef OwnerContainer<PanGesture*> GestureContainer;
138 typedef GestureContainer::Iterator GestureIter;
139 typedef GestureContainer::ConstIterator GestureConstIter;
143 * Structure to contain UpdateManager internal data
145 struct UpdateManager::Impl
147 Impl( NotificationManager& notificationManager,
148 GlSyncAbstraction& glSyncAbstraction,
149 CompleteNotificationInterface& animationFinishedNotifier,
150 PropertyNotifier& propertyNotifier,
151 ResourceManager& resourceManager,
152 DiscardQueue& discardQueue,
153 RenderController& renderController,
154 RenderManager& renderManager,
155 RenderQueue& renderQueue,
156 TextureCache& textureCache,
157 TouchResampler& touchResampler,
158 SceneGraphBuffers& sceneGraphBuffers )
160 renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ),
161 notificationManager( notificationManager ),
162 animationFinishedNotifier( animationFinishedNotifier ),
163 propertyNotifier( propertyNotifier ),
164 resourceManager( resourceManager ),
165 discardQueue( discardQueue ),
166 renderController( renderController ),
167 sceneController( NULL ),
168 renderManager( renderManager ),
169 renderQueue( renderQueue ),
170 renderInstructions( renderManager.GetRenderInstructionContainer() ),
171 completeStatusManager( glSyncAbstraction, renderMessageDispatcher, resourceManager ),
172 touchResampler( touchResampler ),
173 backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
174 taskList ( completeStatusManager ),
175 systemLevelTaskList ( completeStatusManager ),
177 systemLevelRoot( NULL ),
178 messageQueue( renderController, sceneGraphBuffers ),
179 dynamicsChanged( false ),
180 keepRenderingSeconds( 0.0f ),
181 animationFinishedDuringUpdate( false ),
182 activeConstraints( 0 ),
183 nodeDirtyFlags( TransformFlag ), // set to TransformFlag to ensure full update the first time through Update()
184 previousUpdateScene( false ),
186 renderSortingHelper(),
187 renderTaskWaiting( false )
189 sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue, textureCache, completeStatusManager );
194 // Disconnect render tasks from nodes, before destroying the nodes
195 RenderTaskList::RenderTaskContainer& tasks = taskList.GetTasks();
196 for (RenderTaskList::RenderTaskContainer::Iterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
198 (*iter)->SetSourceNode( NULL );
200 // ..repeat for system level RenderTasks
201 RenderTaskList::RenderTaskContainer& systemLevelTasks = systemLevelTaskList.GetTasks();
202 for (RenderTaskList::RenderTaskContainer::Iterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
204 (*iter)->SetSourceNode( NULL );
207 // UpdateManager owns the Nodes
208 DestroyNodeSet( activeDisconnectedNodes );
209 DestroyNodeSet( connectedNodes );
210 DestroyNodeSet( disconnectedNodes );
212 // If there is root, reset it, otherwise do nothing as rendering was never started
221 if( systemLevelRoot )
223 systemLevelRoot->OnDestroy();
225 delete systemLevelRoot;
226 systemLevelRoot = NULL;
229 sceneController->GetTextureCache().SetBufferIndices(NULL); // TODO - Remove
230 delete sceneController;
233 SceneGraphBuffers sceneGraphBuffers; ///< Used to keep track of which buffers are being written or read
234 RenderMessageDispatcher renderMessageDispatcher; ///< Used for passing messages to the render-thread
235 NotificationManager& notificationManager; ///< Queues notification messages for the event-thread.
236 CompleteNotificationInterface& animationFinishedNotifier; ///< Provides notification to applications when animations are finished.
237 PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
238 ResourceManager& resourceManager; ///< resource manager
239 DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
240 RenderController& renderController; ///< render controller
241 SceneControllerImpl* sceneController; ///< scene controller
242 RenderManager& renderManager; ///< This is responsible for rendering the results of each "update"
243 RenderQueue& renderQueue; ///< Used to queue messages for the next render
244 RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions
245 CompleteStatusManager completeStatusManager; ///< Complete Status Manager
246 TouchResampler& touchResampler; ///< Used to resample touch events on every update.
248 Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
250 RenderTaskList taskList; ///< The list of scene graph render-tasks
251 RenderTaskList systemLevelTaskList; ///< Separate render-tasks for system-level content
253 Layer* root; ///< The root node (root is a layer)
254 Layer* systemLevelRoot; ///< A separate root-node for system-level content
255 std::set< Node* > activeDisconnectedNodes; ///< A container of new or modified nodes (without parent) owned by UpdateManager
256 std::set< Node* > connectedNodes; ///< A container of connected (with parent) nodes owned by UpdateManager
257 std::set< Node* > disconnectedNodes; ///< A container of inactive disconnected nodes (without parent) owned by UpdateManager
259 SortedLayerPointers sortedLayers; ///< A container of Layer pointers sorted by depth
260 SortedLayerPointers systemLevelSortedLayers; ///< A separate container of system-level Layers
262 OwnerContainer< PropertyOwner* > customObjects; ///< A container of owned objects (with custom properties)
264 AnimationContainer animations; ///< A container of owned animations
265 PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
267 ShaderContainer shaders; ///< A container of owned shaders
268 AnimatableMeshContainer animatableMeshes; ///< A container of owned animatable meshes
269 MaterialContainer materials; ///< A container of owned materials
271 MessageQueue messageQueue; ///< The messages queued from the event-thread
273 #ifdef DYNAMICS_SUPPORT
274 OwnerPointer<DynamicsWorld> dynamicsWorld; ///< Wrapper for dynamics simulation
276 bool dynamicsChanged; ///< This is set to true if an object is changed in the dynamics simulation tick
278 float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
279 bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
281 unsigned int activeConstraints; ///< number of active constraints from previous frame
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)
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
288 GestureContainer gestures; ///< A container of owned gesture detectors
289 bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
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 )
305 mImpl = new Impl( notificationManager,
307 animationFinishedNotifier,
316 mSceneGraphBuffers );
318 textureCache.SetBufferIndices( &mSceneGraphBuffers );
321 UpdateManager::~UpdateManager()
326 void UpdateManager::InstallRoot( SceneGraph::Layer* layer, bool systemLevel )
328 DALI_ASSERT_DEBUG( layer->IsLayer() );
329 DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
333 DALI_ASSERT_DEBUG( mImpl->root == NULL && "Root Node already installed" );
338 DALI_ASSERT_DEBUG( mImpl->systemLevelRoot == NULL && "System-level Root Node already installed" );
339 mImpl->systemLevelRoot = layer;
342 layer->SetRoot(true);
345 void UpdateManager::AddNode( Node* node )
347 DALI_ASSERT_ALWAYS( NULL != node );
348 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
350 mImpl->activeDisconnectedNodes.insert( node ); // Takes ownership of node
353 void UpdateManager::ConnectNode( Node* parent, Node* node, int index )
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
359 // Move from active/disconnectedNodes to connectedNodes
360 std::set<Node*>::size_type removed = mImpl->activeDisconnectedNodes.erase( node );
363 removed = mImpl->disconnectedNodes.erase( node );
364 DALI_ASSERT_ALWAYS( removed );
366 mImpl->connectedNodes.insert( node );
368 node->SetActive( true );
370 parent->ConnectChild( node, index );
373 void UpdateManager::DisconnectNode( Node* node )
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
379 // Move from connectedNodes to activeDisconnectedNodes (reset properties next frame)
380 parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node, mImpl->connectedNodes, mImpl->activeDisconnectedNodes );
383 void UpdateManager::SetNodeActive( Node* node )
385 DALI_ASSERT_ALWAYS( NULL != node );
386 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
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 );
393 node->SetActive( true );
396 void UpdateManager::DestroyNode( Node* node )
398 DALI_ASSERT_ALWAYS( NULL != node );
399 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
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 );
406 removed = mImpl->disconnectedNodes.erase( node );
407 DALI_ASSERT_ALWAYS( removed );
409 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
411 // Notify the Node about impending destruction
415 void UpdateManager::AttachToNode( Node* node, NodeAttachment* attachment )
417 DALI_ASSERT_DEBUG( node != NULL );
418 DALI_ASSERT_DEBUG( attachment != NULL );
420 // attach node to attachment first so that parent is known by the time attachment is connected
421 node->Attach( *attachment ); // node takes ownership
422 attachment->ConnectToSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
425 void UpdateManager::AddObject( PropertyOwner* object )
427 DALI_ASSERT_DEBUG( NULL != object );
429 mImpl->customObjects.PushBack( object );
432 void UpdateManager::RemoveObject( PropertyOwner* object )
434 DALI_ASSERT_DEBUG( NULL != object );
436 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
438 // Find the object and destroy it
439 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); iter != customObjects.End(); ++iter )
441 PropertyOwner* current = *iter;
442 if ( current == object )
444 customObjects.Erase( iter );
449 // Should not reach here
450 DALI_ASSERT_DEBUG(false);
453 void UpdateManager::AddAnimation( Animation* animation )
455 mImpl->animations.PushBack( animation );
458 void UpdateManager::StopAnimation( Animation* animation )
460 DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
462 bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
464 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
467 void UpdateManager::RemoveAnimation( Animation* animation )
469 DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
471 animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
473 DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
476 bool UpdateManager::IsAnimationRunning() const
478 bool isRunning(false);
479 AnimationContainer& animations = mImpl->animations;
481 // Find any animation that isn't stopped or paused
483 const AnimationIter endIter = animations.End();
484 for ( AnimationIter iter = animations.Begin(); !isRunning && iter != endIter; ++iter )
486 const Animation::State state = (*iter)->GetState();
488 if (state != Animation::Stopped &&
489 state != Animation::Paused)
498 void UpdateManager::AddPropertyNotification( PropertyNotification* propertyNotification )
500 mImpl->propertyNotifications.PushBack( propertyNotification );
503 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
505 PropertyNotificationContainer &propertyNotifications = mImpl->propertyNotifications;
506 PropertyNotificationIter iter = propertyNotifications.Begin();
508 while ( iter != propertyNotifications.End() )
510 if( *iter == propertyNotification )
512 propertyNotifications.Erase(iter);
519 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
521 DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
522 propertyNotification->SetNotifyMode( notifyMode );
525 void UpdateManager::AddShader( Shader* shader )
527 DALI_ASSERT_DEBUG( NULL != shader );
529 if( mImpl->shaders.Count() == 0 )
531 // the first added shader becomes our default shader
532 // Construct message in the render queue memory; note that delete should not be called on the return value
533 typedef MessageValue1< RenderManager, Shader* > DerivedType;
535 // Reserve some memory inside the render queue
536 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
538 // Construct message in the render queue memory; note that delete should not be called on the return value
539 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultShader, shader );
542 mImpl->shaders.PushBack( shader );
544 // Allows the shader to dispatch texture requests to the cache
545 shader->Initialize( mImpl->renderQueue, mImpl->sceneController->GetTextureCache() );
548 void UpdateManager::RemoveShader(Shader* shader)
550 DALI_ASSERT_DEBUG(shader != NULL);
552 ShaderContainer& shaders = mImpl->shaders;
554 // Find the shader and destroy it
555 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
557 Shader& current = **iter;
558 if ( ¤t == shader )
560 // Transfer ownership to the discard queue
561 // This keeps the shader alive, until the render-thread has finished with it
562 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), shaders.Release( iter ) );
567 // Should not reach here
568 DALI_ASSERT_DEBUG(false);
571 void UpdateManager::SetShaderProgram( Shader* shader, GeometryType geometryType, ShaderSubTypes subType, ResourceId resourceId, size_t shaderHash, bool modifiesGeometry )
573 DALI_LOG_TRACE_METHOD_FMT(Debug::Filter::gShader, " - (geometryType:%d subType:%d id:%d hash:%d)\n", geometryType, subType, resourceId, shaderHash);
575 DALI_ASSERT_ALWAYS( NULL != shader && "shader is uninitialized" );
577 Integration::ShaderDataPtr shaderData( mImpl->resourceManager.GetShaderData(resourceId) );
580 shaderData->SetHashValue( shaderHash );
581 shaderData->SetResourceId( resourceId );
583 typedef MessageValue6< Shader, GeometryType, Internal::ShaderSubTypes, Integration::ResourceId, Integration::ShaderDataPtr, ProgramCache*, bool> DerivedType;
585 // Reserve some memory inside the render queue
586 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
588 // Construct message in the render queue memory; note that delete should not be called on the return value
589 new (slot) DerivedType( shader, &Shader::SetProgram, geometryType, subType, resourceId, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
593 void UpdateManager::AddAnimatableMesh( AnimatableMesh* animatableMesh )
595 mImpl->animatableMeshes.PushBack(animatableMesh);
598 void UpdateManager::RemoveAnimatableMesh( AnimatableMesh* animatableMesh )
600 DALI_ASSERT_DEBUG(animatableMesh != NULL);
602 AnimatableMeshContainer& animatableMeshes = mImpl->animatableMeshes;
604 // Find the animatableMesh and destroy it
605 for ( AnimatableMeshIter iter = animatableMeshes.Begin(); iter != animatableMeshes.End(); ++iter )
607 AnimatableMesh& current = **iter;
608 if ( ¤t == animatableMesh )
610 animatableMeshes.Erase( iter );
616 void UpdateManager::AddMaterial( Material* material )
618 DALI_ASSERT_DEBUG( NULL != material );
620 mImpl->materials.PushBack( material );
621 RenderMaterial* renderMaterial = new RenderMaterial();
623 typedef MessageValue1< RenderManager, RenderMaterial* > DerivedType;
625 // Reserve some memory inside the render queue
626 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
628 // Construct message in the render queue memory; note that delete should not be called on the return value
629 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddRenderMaterial, renderMaterial );
631 material->SetRenderMaterial( renderMaterial );
632 material->OnStageConnection( *mImpl->sceneController );
635 void UpdateManager::RemoveMaterial( Material* theMaterial )
637 // Caused by last reference to material being released (e.g. app or internal mesh-actor)
639 for ( MaterialIter iter=mImpl->materials.Begin(), end=mImpl->materials.End() ; iter != end ; ++iter )
641 const Material* aMaterial = *iter;
643 if( aMaterial == theMaterial )
645 typedef MessageValue1< RenderManager, RenderMaterial* > DerivedType;
647 // Reserve some memory inside the render queue
648 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
650 // Construct message in the render queue memory; note that delete should not be called on the return value
651 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveRenderMaterial, theMaterial->GetRenderMaterial() );
653 mImpl->materials.Erase( iter );
659 RenderTaskList* UpdateManager::GetRenderTaskList( bool systemLevel )
663 // copy the list, this is only likely to happen once in application life cycle
664 return &(mImpl->taskList);
668 // copy the list, this is only likely to happen once in application life cycle
669 return &(mImpl->systemLevelTaskList);
673 void UpdateManager::AddGesture( PanGesture* gesture )
675 DALI_ASSERT_DEBUG( NULL != gesture );
677 mImpl->gestures.PushBack( gesture );
680 void UpdateManager::RemoveGesture( PanGesture* gesture )
682 DALI_ASSERT_DEBUG( gesture != NULL );
684 GestureContainer& gestures = mImpl->gestures;
686 // Find the gesture and destroy it
687 for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
689 PanGesture& current = **iter;
690 if ( ¤t == gesture )
692 mImpl->gestures.Erase( iter );
696 // Should not reach here
697 DALI_ASSERT_DEBUG(false);
700 unsigned int* UpdateManager::ReserveMessageSlot( std::size_t size, bool updateScene )
702 return mImpl->messageQueue.ReserveMessageSlot( size, updateScene );
705 void UpdateManager::EventProcessingStarted()
707 mImpl->messageQueue.EventProcessingStarted();
710 bool UpdateManager::FlushQueue()
712 return mImpl->messageQueue.FlushQueue();
715 void UpdateManager::ResetNodeProperty( Node& node )
717 node.ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
720 void UpdateManager::ResetProperties()
722 PERF_MONITOR_START(PerformanceMonitor::RESET_PROPERTIES);
724 // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
725 mImpl->animationFinishedDuringUpdate = false;
727 // Animated properties have to be reset to their original value each frame
729 // Reset node properties
732 ResetNodeProperty( *mImpl->root );
735 if ( mImpl->systemLevelRoot )
737 ResetNodeProperty( *mImpl->systemLevelRoot );
740 // Reset the Connected Nodes
741 const std::set<Node*>::iterator endIter = mImpl->connectedNodes.end();
742 for( std::set<Node*>::iterator iter = mImpl->connectedNodes.begin(); endIter != iter; ++iter )
744 ResetNodeProperty( **iter );
747 // If a Node is disconnected, it may still be "active" (requires a reset in next frame)
748 for( std::set<Node*>::iterator iter = mImpl->activeDisconnectedNodes.begin(); mImpl->activeDisconnectedNodes.end() != iter; iter = mImpl->activeDisconnectedNodes.begin() )
751 node->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
752 node->SetActive( false );
754 // Move everything from activeDisconnectedNodes to disconnectedNodes (no need to reset again)
755 mImpl->activeDisconnectedNodes.erase( iter );
756 mImpl->disconnectedNodes.insert( node );
759 // Reset system-level render-task list properties to base values
760 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
762 for (RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
764 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
767 // Reset render-task list properties to base values.
768 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
770 for (RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
772 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
775 // Reset custom object properties to base values
776 for (OwnerContainer<PropertyOwner*>::Iterator iter = mImpl->customObjects.Begin(); iter != mImpl->customObjects.End(); ++iter)
778 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
781 // Reset animatable shader properties to base values
782 for (ShaderIter iter = mImpl->shaders.Begin(); iter != mImpl->shaders.End(); ++iter)
784 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
787 // Reset animatable mesh properties to base values
788 for ( AnimatableMeshIter iter = mImpl->animatableMeshes.Begin(); iter != mImpl->animatableMeshes.End(); ++iter )
790 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
793 PERF_MONITOR_END(PerformanceMonitor::RESET_PROPERTIES);
796 bool UpdateManager::ProcessGestures( unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds )
798 bool gestureUpdated( false );
800 // constrain gestures... (in construction order)
801 GestureContainer& gestures = mImpl->gestures;
803 for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
805 PanGesture& gesture = **iter;
806 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
807 gestureUpdated |= gesture.UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
810 return gestureUpdated;
813 void UpdateManager::Animate( float elapsedSeconds )
815 PERF_MONITOR_START(PerformanceMonitor::ANIMATE_NODES);
817 AnimationContainer &animations = mImpl->animations;
818 AnimationIter iter = animations.Begin();
819 while ( iter != animations.End() )
821 Animation* animation = *iter;
822 bool finished = animation->Update(mSceneGraphBuffers.GetUpdateBufferIndex(), elapsedSeconds);
824 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
826 // Remove animations that had been destroyed but were still waiting for an update
827 if (animation->GetState() == Animation::Destroyed)
829 iter = animations.Erase(iter);
837 if ( mImpl->animationFinishedDuringUpdate )
839 // The application should be notified by NotificationManager, in another thread
840 mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationFinishedNotifier );
843 PERF_MONITOR_END(PerformanceMonitor::ANIMATE_NODES);
846 void UpdateManager::ApplyConstraints()
848 PERF_MONITOR_START(PerformanceMonitor::APPLY_CONSTRAINTS);
850 mImpl->activeConstraints = 0;
852 // constrain custom objects... (in construction order)
853 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
855 const OwnerContainer< PropertyOwner* >::Iterator endIter = customObjects.End();
856 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); endIter != iter; ++iter )
858 PropertyOwner& object = **iter;
859 mImpl->activeConstraints += ConstrainPropertyOwner( object, mSceneGraphBuffers.GetUpdateBufferIndex() );
862 // constrain nodes... (in Depth First traversal order)
865 mImpl->activeConstraints += ConstrainNodes( *(mImpl->root), mSceneGraphBuffers.GetUpdateBufferIndex() );
868 if ( mImpl->systemLevelRoot )
870 mImpl->activeConstraints += ConstrainNodes( *(mImpl->systemLevelRoot), mSceneGraphBuffers.GetUpdateBufferIndex() );
873 // constrain other property-owners after nodes as they are more likely to depend on a node's
874 // current frame property than vice versa. They tend to be final constraints (no further
875 // constraints depend on their properties)
876 // e.g. ShaderEffect uniform a function of Actor's position.
877 // Mesh vertex a function of Actor's position or world position.
879 // TODO: refactor this code (and reset nodes) as these are all just lists of property-owners
880 // they can be all processed in a super-list of property-owners.
882 // Constrain system-level render-tasks
883 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
885 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter )
887 RenderTask& task = **iter;
888 mImpl->activeConstraints += ConstrainPropertyOwner( task, mSceneGraphBuffers.GetUpdateBufferIndex() );
891 // Constrain render-tasks
892 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
894 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter )
896 RenderTask& task = **iter;
897 mImpl->activeConstraints += ConstrainPropertyOwner( task, mSceneGraphBuffers.GetUpdateBufferIndex() );
900 // constrain meshes (in construction order)
901 AnimatableMeshContainer& meshes = mImpl->animatableMeshes;
902 for ( AnimatableMeshIter iter = meshes.Begin(); iter != meshes.End(); ++iter )
904 AnimatableMesh& mesh = **iter;
905 mImpl->activeConstraints += ConstrainPropertyOwner( mesh, mSceneGraphBuffers.GetUpdateBufferIndex() );
908 // constrain shaders... (in construction order)
909 ShaderContainer& shaders = mImpl->shaders;
911 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
913 Shader& shader = **iter;
914 mImpl->activeConstraints += ConstrainPropertyOwner( shader, mSceneGraphBuffers.GetUpdateBufferIndex() );
917 PERF_MONITOR_END(PerformanceMonitor::APPLY_CONSTRAINTS);
920 void UpdateManager::ProcessPropertyNotifications()
922 PropertyNotificationContainer ¬ifications = mImpl->propertyNotifications;
923 PropertyNotificationIter iter = notifications.Begin();
925 while ( iter != notifications.End() )
927 PropertyNotification* notification = *iter;
929 bool valid = notification->Check( mSceneGraphBuffers.GetUpdateBufferIndex() );
933 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
939 void UpdateManager::UpdateNodes()
941 mImpl->nodeDirtyFlags = NothingFlag;
948 PERF_MONITOR_START( PerformanceMonitor::UPDATE_NODES );
950 // Prepare resources, update shaders, update attachments, for each node
951 // And add the renderers to the sorted layers. Start from root, which is also a layer
952 mImpl->nodeDirtyFlags = UpdateNodesAndAttachments( *( mImpl->root ),
953 mSceneGraphBuffers.GetUpdateBufferIndex(),
954 mImpl->resourceManager,
955 mImpl->renderQueue );
957 if ( mImpl->systemLevelRoot )
959 mImpl->nodeDirtyFlags |= UpdateNodesAndAttachments( *( mImpl->systemLevelRoot ),
960 mSceneGraphBuffers.GetUpdateBufferIndex(),
961 mImpl->resourceManager,
962 mImpl->renderQueue );
965 PERF_MONITOR_END( PerformanceMonitor::UPDATE_NODES );
968 void UpdateManager::UpdateMeshes( BufferIndex updateBufferIndex, AnimatableMeshContainer& meshes )
970 for ( AnimatableMeshIter iter = meshes.Begin(); iter != meshes.End(); ++iter )
972 AnimatableMesh& current = **iter;
973 current.UpdateMesh( updateBufferIndex );
977 void UpdateManager::UpdateMaterials( BufferIndex updateBufferIndex, MaterialContainer& materials )
979 for( MaterialIter iter = materials.Begin(), end = materials.End(); iter != end; iter++ )
981 Material* material = *iter;
982 material->PrepareResources( updateBufferIndex, mImpl->resourceManager );
986 void UpdateManager::PrepareMaterials( BufferIndex updateBufferIndex, MaterialContainer& materials )
988 for( MaterialIter iter = materials.Begin(), end = materials.End(); iter != end; iter++ )
990 Material* material = *iter;
991 material->PrepareRender( updateBufferIndex );
995 unsigned int UpdateManager::Update( float elapsedSeconds,
996 unsigned int lastVSyncTimeMilliseconds,
997 unsigned int nextVSyncTimeMilliseconds )
999 PERF_MONITOR_END(PerformanceMonitor::FRAME_RATE); // Mark the End of the last frame
1000 PERF_MONITOR_NEXT_FRAME(); // Prints out performance info for the last frame (if enabled)
1001 PERF_MONITOR_START(PerformanceMonitor::FRAME_RATE); // Mark the start of this current frame
1003 // Measure the time spent in UpdateManager::Update
1004 PERF_MONITOR_START(PerformanceMonitor::UPDATE);
1006 // Update the frame time delta on the render thread.
1007 mImpl->renderManager.SetFrameDeltaTime(elapsedSeconds);
1009 // 1) Clear nodes/resources which were previously discarded
1010 mImpl->discardQueue.Clear( mSceneGraphBuffers.GetUpdateBufferIndex() );
1012 // 2) Grab any loaded resources
1013 bool resourceChanged = mImpl->resourceManager.UpdateCache( mSceneGraphBuffers.GetUpdateBufferIndex() );
1015 // 3) Process Touches & Gestures
1016 mImpl->touchResampler.Update();
1017 const bool gestureUpdated = ProcessGestures( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
1019 const bool updateScene = // The scene-graph requires an update if..
1020 mImpl->activeConstraints != 0 || // ..constraints were active in previous frame OR
1021 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
1022 IsAnimationRunning() || // ..at least one animation is running OR
1023 mImpl->dynamicsChanged || // ..there was a change in the dynamics simulation OR
1024 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
1025 resourceChanged || // ..one or more resources were updated/changed OR
1026 gestureUpdated; // ..a gesture property was updated
1028 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
1029 // values if the scene was updated in the previous frame.
1030 if( updateScene || mImpl->previousUpdateScene )
1032 // 4) Reset properties from the previous update
1036 // 5) Process the queued scene messages
1037 mImpl->messageQueue.ProcessMessages();
1039 // 6) Post Process Ids of resources updated by renderer
1040 mImpl->resourceManager.PostProcessResources( mSceneGraphBuffers.GetUpdateBufferIndex() );
1042 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
1043 // renderer lists if the scene was updated in the previous frame.
1044 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
1045 if( updateScene || mImpl->previousUpdateScene )
1048 Animate( elapsedSeconds );
1050 // 8) Apply Constraints
1053 #ifdef DYNAMICS_SUPPORT
1054 // 9) Update dynamics simulation
1055 mImpl->dynamicsChanged = false;
1056 if( mImpl->dynamicsWorld )
1058 mImpl->dynamicsChanged = mImpl->dynamicsWorld->Update( elapsedSeconds );
1062 // 10) Check Property Notifications
1063 ProcessPropertyNotifications();
1065 // 11) Clear the lists of renderable-attachments from the previous update
1066 ClearRenderables( mImpl->sortedLayers );
1067 ClearRenderables( mImpl->systemLevelSortedLayers );
1069 // 12) Update animated meshes
1070 UpdateMeshes( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->animatableMeshes );
1072 // 13) Update materials. Prepares image resources
1073 UpdateMaterials( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->materials );
1075 // 14) Update node hierarchy and perform sorting / culling.
1076 // This will populate each Layer with a list of renderers which are ready.
1079 // 15) Prepare for the next render
1080 PERF_MONITOR_START(PerformanceMonitor::PREPARE_RENDERABLES);
1081 PrepareMaterials( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->materials );
1082 PrepareRenderables( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->sortedLayers );
1083 PrepareRenderables( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->systemLevelSortedLayers );
1084 PERF_MONITOR_END(PerformanceMonitor::PREPARE_RENDERABLES);
1086 PERF_MONITOR_START(PerformanceMonitor::PROCESS_RENDER_TASKS);
1088 // 16) Process the RenderTasks; this creates the instructions for rendering the next frame.
1089 // reset the update buffer index and make sure there is enough room in the instruction container
1090 mImpl->renderInstructions.ResetAndReserve( mSceneGraphBuffers.GetUpdateBufferIndex(),
1091 mImpl->taskList.GetTasks().Count() + mImpl->systemLevelTaskList.GetTasks().Count() );
1093 if ( NULL != mImpl->root )
1095 ProcessRenderTasks( mSceneGraphBuffers.GetUpdateBufferIndex(),
1096 mImpl->completeStatusManager,
1099 mImpl->sortedLayers,
1100 mImpl->renderSortingHelper,
1101 mImpl->renderInstructions );
1103 // Process the system-level RenderTasks last
1104 if ( NULL != mImpl->systemLevelRoot )
1106 ProcessRenderTasks( mSceneGraphBuffers.GetUpdateBufferIndex(),
1107 mImpl->completeStatusManager,
1108 mImpl->systemLevelTaskList,
1109 *mImpl->systemLevelRoot,
1110 mImpl->systemLevelSortedLayers,
1111 mImpl->renderSortingHelper,
1112 mImpl->renderInstructions );
1117 // check the countdown and notify (note, at the moment this is only done for normal tasks, not for systemlevel tasks)
1118 bool doRenderOnceNotify = false;
1119 mImpl->renderTaskWaiting = false;
1120 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
1121 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(), endIter = tasks.End();
1122 endIter != iter; ++iter )
1124 RenderTask& renderTask(*(*iter));
1126 renderTask.UpdateState();
1128 if( renderTask.IsWaitingToRender() &&
1129 renderTask.ReadyToRender(mSceneGraphBuffers.GetUpdateBufferIndex()) /*avoid updating forever when source actor is off-stage*/ )
1131 mImpl->renderTaskWaiting = true; // keep update/render threads alive
1134 if( renderTask.HasRendered() )
1136 doRenderOnceNotify = true;
1140 if( doRenderOnceNotify )
1142 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
1143 mImpl->notificationManager.QueueCompleteNotification( mImpl->taskList.GetCompleteNotificationInterface() );
1146 PERF_MONITOR_END(PerformanceMonitor::PROCESS_RENDER_TASKS);
1148 // Macro is undefined in release build.
1149 SNAPSHOT_NODE_LOGGING;
1151 // A ResetProperties() may be required in the next frame
1152 mImpl->previousUpdateScene = updateScene;
1154 // Check whether further updates are required
1155 unsigned int keepUpdating = KeepUpdatingCheck( elapsedSeconds );
1157 #ifdef PERFORMANCE_MONITOR_ENABLED
1158 // Always keep rendering when measuring FPS
1159 keepUpdating |= KeepUpdating::MONITORING_PERFORMANCE;
1162 // The update has finished; swap the double-buffering indices
1163 mSceneGraphBuffers.Swap();
1165 // tell the update manager that we're done so the queue can be given to event thread
1166 mImpl->notificationManager.UpdateCompleted();
1168 PERF_MONITOR_END(PerformanceMonitor::UPDATE);
1170 return keepUpdating;
1173 unsigned int UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
1175 // Update the duration set via Stage::KeepRendering()
1176 if ( mImpl->keepRenderingSeconds > 0.0f )
1178 mImpl->keepRenderingSeconds -= elapsedSeconds;
1181 unsigned int keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
1183 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
1184 // Keep updating until no messages are received and no animations are running.
1185 // If an animation has just finished, update at least once more for Discard end-actions.
1186 // No need to check for renderQueue as there is always a render after update and if that
1187 // render needs another update it will tell the adaptor to call update again
1189 if ( mImpl->keepRenderingSeconds > 0.0f )
1191 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
1194 if ( IsAnimationRunning() ||
1195 mImpl->animationFinishedDuringUpdate )
1197 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
1200 if ( mImpl->dynamicsChanged )
1202 keepUpdatingRequest |= KeepUpdating::DYNAMICS_CHANGED;
1205 if ( mImpl->renderTaskWaiting )
1207 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
1210 return keepUpdatingRequest;
1213 void UpdateManager::SetBackgroundColor( const Vector4& color )
1215 typedef MessageValue1< RenderManager, Vector4 > DerivedType;
1217 // Reserve some memory inside the render queue
1218 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1220 // Construct message in the render queue memory; note that delete should not be called on the return value
1221 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
1224 void UpdateManager::SetDefaultSurfaceRect( const Rect<int>& rect )
1226 typedef MessageValue1< RenderManager, Rect<int> > DerivedType;
1228 // Reserve some memory inside the render queue
1229 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1231 // Construct message in the render queue memory; note that delete should not be called on the return value
1232 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1235 void UpdateManager::KeepRendering( float durationSeconds )
1237 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1240 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, bool systemLevel )
1244 // just copy the vector of pointers
1245 mImpl->sortedLayers = layers;
1249 mImpl->systemLevelSortedLayers = layers;
1253 #ifdef DYNAMICS_SUPPORT
1255 void UpdateManager::InitializeDynamicsWorld( SceneGraph::DynamicsWorld* dynamicsWorld, Integration::DynamicsWorldSettings* worldSettings )
1257 dynamicsWorld->Initialize( mImpl->sceneController, worldSettings, &mSceneGraphBuffers );
1258 mImpl->dynamicsWorld = dynamicsWorld;
1261 void UpdateManager::TerminateDynamicsWorld()
1263 mImpl->dynamicsWorld.Reset();
1266 #endif // DYNAMICS_SUPPORT
1268 } // namespace SceneGraph
1270 } // namespace Internal