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 nodeDirtyFlags( TransformFlag ), // set to TransformFlag to ensure full update the first time through Update()
183 previousUpdateScene( false ),
185 renderSortingHelper(),
186 renderTaskWaiting( false )
188 sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue, textureCache, completeStatusManager );
193 // Disconnect render tasks from nodes, before destroying the nodes
194 RenderTaskList::RenderTaskContainer& tasks = taskList.GetTasks();
195 for (RenderTaskList::RenderTaskContainer::Iterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
197 (*iter)->SetSourceNode( NULL );
199 // ..repeat for system level RenderTasks
200 RenderTaskList::RenderTaskContainer& systemLevelTasks = systemLevelTaskList.GetTasks();
201 for (RenderTaskList::RenderTaskContainer::Iterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
203 (*iter)->SetSourceNode( NULL );
206 // UpdateManager owns the Nodes
207 DestroyNodeSet( activeDisconnectedNodes );
208 DestroyNodeSet( connectedNodes );
209 DestroyNodeSet( disconnectedNodes );
211 // If there is root, reset it, otherwise do nothing as rendering was never started
220 if( systemLevelRoot )
222 systemLevelRoot->OnDestroy();
224 delete systemLevelRoot;
225 systemLevelRoot = NULL;
228 sceneController->GetTextureCache().SetBufferIndices(NULL); // TODO - Remove
229 delete sceneController;
232 SceneGraphBuffers sceneGraphBuffers; ///< Used to keep track of which buffers are being written or read
233 RenderMessageDispatcher renderMessageDispatcher; ///< Used for passing messages to the render-thread
234 NotificationManager& notificationManager; ///< Queues notification messages for the event-thread.
235 CompleteNotificationInterface& animationFinishedNotifier; ///< Provides notification to applications when animations are finished.
236 PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
237 ResourceManager& resourceManager; ///< resource manager
238 DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
239 RenderController& renderController; ///< render controller
240 SceneControllerImpl* sceneController; ///< scene controller
241 RenderManager& renderManager; ///< This is responsible for rendering the results of each "update"
242 RenderQueue& renderQueue; ///< Used to queue messages for the next render
243 RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions
244 CompleteStatusManager completeStatusManager; ///< Complete Status Manager
245 TouchResampler& touchResampler; ///< Used to resample touch events on every update.
247 Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
249 RenderTaskList taskList; ///< The list of scene graph render-tasks
250 RenderTaskList systemLevelTaskList; ///< Separate render-tasks for system-level content
252 Layer* root; ///< The root node (root is a layer)
253 Layer* systemLevelRoot; ///< A separate root-node for system-level content
254 std::set< Node* > activeDisconnectedNodes; ///< A container of new or modified nodes (without parent) owned by UpdateManager
255 std::set< Node* > connectedNodes; ///< A container of connected (with parent) nodes owned by UpdateManager
256 std::set< Node* > disconnectedNodes; ///< A container of inactive disconnected nodes (without parent) owned by UpdateManager
258 SortedLayerPointers sortedLayers; ///< A container of Layer pointers sorted by depth
259 SortedLayerPointers systemLevelSortedLayers; ///< A separate container of system-level Layers
261 OwnerContainer< PropertyOwner* > customObjects; ///< A container of owned objects (with custom properties)
263 AnimationContainer animations; ///< A container of owned animations
264 PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
266 ShaderContainer shaders; ///< A container of owned shaders
267 AnimatableMeshContainer animatableMeshes; ///< A container of owned animatable meshes
268 MaterialContainer materials; ///< A container of owned materials
270 MessageQueue messageQueue; ///< The messages queued from the event-thread
272 #ifdef DYNAMICS_SUPPORT
273 OwnerPointer<DynamicsWorld> dynamicsWorld; ///< Wrapper for dynamics simulation
275 bool dynamicsChanged; ///< This is set to true if an object is changed in the dynamics simulation tick
277 float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
278 bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
280 int nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
281 bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
283 int frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
284 RendererSortingHelper renderSortingHelper; ///< helper used to sort transparent renderers
286 GestureContainer gestures; ///< A container of owned gesture detectors
287 bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
290 UpdateManager::UpdateManager( NotificationManager& notificationManager,
291 GlSyncAbstraction& glSyncAbstraction,
292 CompleteNotificationInterface& animationFinishedNotifier,
293 PropertyNotifier& propertyNotifier,
294 ResourceManager& resourceManager,
295 DiscardQueue& discardQueue,
296 RenderController& controller,
297 RenderManager& renderManager,
298 RenderQueue& renderQueue,
299 TextureCache& textureCache,
300 TouchResampler& touchResampler )
303 mImpl = new Impl( notificationManager,
305 animationFinishedNotifier,
314 mSceneGraphBuffers );
316 textureCache.SetBufferIndices( &mSceneGraphBuffers );
319 UpdateManager::~UpdateManager()
324 void UpdateManager::InstallRoot( SceneGraph::Layer* layer, bool systemLevel )
326 DALI_ASSERT_DEBUG( layer->IsLayer() );
327 DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
331 DALI_ASSERT_DEBUG( mImpl->root == NULL && "Root Node already installed" );
336 DALI_ASSERT_DEBUG( mImpl->systemLevelRoot == NULL && "System-level Root Node already installed" );
337 mImpl->systemLevelRoot = layer;
340 layer->SetRoot(true);
343 void UpdateManager::AddNode( Node* node )
345 DALI_ASSERT_ALWAYS( NULL != node );
346 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
348 mImpl->activeDisconnectedNodes.insert( node ); // Takes ownership of node
351 void UpdateManager::ConnectNode( Node* parent, Node* node, int index )
353 DALI_ASSERT_ALWAYS( NULL != parent );
354 DALI_ASSERT_ALWAYS( NULL != node );
355 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
357 // Move from active/disconnectedNodes to connectedNodes
358 std::set<Node*>::size_type removed = mImpl->activeDisconnectedNodes.erase( node );
361 removed = mImpl->disconnectedNodes.erase( node );
362 DALI_ASSERT_ALWAYS( removed );
364 mImpl->connectedNodes.insert( node );
366 node->SetActive( true );
368 parent->ConnectChild( node, index );
371 void UpdateManager::DisconnectNode( Node* node )
373 Node* parent = node->GetParent();
374 DALI_ASSERT_ALWAYS( NULL != parent );
375 parent->SetDirtyFlag( ChildDeletedFlag ); // make parent dirty so that render items dont get reused
377 // Move from connectedNodes to activeDisconnectedNodes (reset properties next frame)
378 parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node, mImpl->connectedNodes, mImpl->activeDisconnectedNodes );
381 void UpdateManager::SetNodeActive( Node* node )
383 DALI_ASSERT_ALWAYS( NULL != node );
384 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
386 // Move from disconnectedNodes to activeDisconnectedNodes (reset properties next frame)
387 std::set<Node*>::size_type removed = mImpl->disconnectedNodes.erase( node );
388 DALI_ASSERT_ALWAYS( removed );
389 mImpl->activeDisconnectedNodes.insert( node );
391 node->SetActive( true );
394 void UpdateManager::DestroyNode( Node* node )
396 DALI_ASSERT_ALWAYS( NULL != node );
397 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
399 // Transfer ownership from new/disconnectedNodes to the discard queue
400 // This keeps the nodes alive, until the render-thread has finished with them
401 std::set<Node*>::size_type removed = mImpl->activeDisconnectedNodes.erase( node );
404 removed = mImpl->disconnectedNodes.erase( node );
405 DALI_ASSERT_ALWAYS( removed );
407 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
409 // Notify the Node about impending destruction
413 void UpdateManager::AttachToNode( Node* node, NodeAttachment* attachment )
415 DALI_ASSERT_DEBUG( node != NULL );
416 DALI_ASSERT_DEBUG( attachment != NULL );
418 // attach node to attachment first so that parent is known by the time attachment is connected
419 node->Attach( *attachment ); // node takes ownership
420 attachment->ConnectToSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
423 void UpdateManager::AddObject( PropertyOwner* object )
425 DALI_ASSERT_DEBUG( NULL != object );
427 mImpl->customObjects.PushBack( object );
430 void UpdateManager::RemoveObject( PropertyOwner* object )
432 DALI_ASSERT_DEBUG( NULL != object );
434 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
436 // Find the object and destroy it
437 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); iter != customObjects.End(); ++iter )
439 PropertyOwner* current = *iter;
440 if ( current == object )
442 customObjects.Erase( iter );
447 // Should not reach here
448 DALI_ASSERT_DEBUG(false);
451 void UpdateManager::AddAnimation( Animation* animation )
453 mImpl->animations.PushBack( animation );
456 void UpdateManager::StopAnimation( Animation* animation )
458 DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
460 bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
462 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
465 void UpdateManager::RemoveAnimation( Animation* animation )
467 DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
469 animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
471 DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
474 bool UpdateManager::IsAnimationRunning() const
476 bool isRunning(false);
477 AnimationContainer& animations = mImpl->animations;
479 // Find any animation that isn't stopped or paused
481 const AnimationIter endIter = animations.End();
482 for ( AnimationIter iter = animations.Begin(); !isRunning && iter != endIter; ++iter )
484 const Animation::State state = (*iter)->GetState();
486 if (state != Animation::Stopped &&
487 state != Animation::Paused)
496 void UpdateManager::AddPropertyNotification( PropertyNotification* propertyNotification )
498 mImpl->propertyNotifications.PushBack( propertyNotification );
501 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
503 PropertyNotificationContainer &propertyNotifications = mImpl->propertyNotifications;
504 PropertyNotificationIter iter = propertyNotifications.Begin();
506 while ( iter != propertyNotifications.End() )
508 if( *iter == propertyNotification )
510 propertyNotifications.Erase(iter);
517 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
519 DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
520 propertyNotification->SetNotifyMode( notifyMode );
523 void UpdateManager::AddShader( Shader* shader )
525 DALI_ASSERT_DEBUG( NULL != shader );
527 if( mImpl->shaders.Count() == 0 )
529 // the first added shader becomes our default shader
530 // Construct message in the render queue memory; note that delete should not be called on the return value
531 typedef MessageValue1< RenderManager, Shader* > DerivedType;
533 // Reserve some memory inside the render queue
534 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
536 // Construct message in the render queue memory; note that delete should not be called on the return value
537 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultShader, shader );
540 mImpl->shaders.PushBack( shader );
542 // Allows the shader to dispatch texture requests to the cache
543 shader->Initialize( mImpl->renderQueue, mImpl->sceneController->GetTextureCache() );
546 void UpdateManager::RemoveShader(Shader* shader)
548 DALI_ASSERT_DEBUG(shader != NULL);
550 ShaderContainer& shaders = mImpl->shaders;
552 // Find the shader and destroy it
553 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
555 Shader& current = **iter;
556 if ( ¤t == shader )
558 // Transfer ownership to the discard queue
559 // This keeps the shader alive, until the render-thread has finished with it
560 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), shaders.Release( iter ) );
565 // Should not reach here
566 DALI_ASSERT_DEBUG(false);
569 void UpdateManager::SetShaderProgram( Shader* shader, GeometryType geometryType, ShaderSubTypes subType, ResourceId resourceId, size_t shaderHash, bool modifiesGeometry )
571 DALI_LOG_TRACE_METHOD_FMT(Debug::Filter::gShader, " - (geometryType:%d subType:%d id:%d hash:%d)\n", geometryType, subType, resourceId, shaderHash);
573 DALI_ASSERT_ALWAYS( NULL != shader && "shader is uninitialized" );
575 Integration::ShaderDataPtr shaderData( mImpl->resourceManager.GetShaderData(resourceId) );
578 shaderData->SetHashValue( shaderHash );
579 shaderData->SetResourceId( resourceId );
581 typedef MessageValue6< Shader, GeometryType, Internal::ShaderSubTypes, Integration::ResourceId, Integration::ShaderDataPtr, ProgramCache*, bool> DerivedType;
583 // Reserve some memory inside the render queue
584 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
586 // Construct message in the render queue memory; note that delete should not be called on the return value
587 new (slot) DerivedType( shader, &Shader::SetProgram, geometryType, subType, resourceId, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
591 void UpdateManager::AddAnimatableMesh( AnimatableMesh* animatableMesh )
593 mImpl->animatableMeshes.PushBack(animatableMesh);
596 void UpdateManager::RemoveAnimatableMesh( AnimatableMesh* animatableMesh )
598 DALI_ASSERT_DEBUG(animatableMesh != NULL);
600 AnimatableMeshContainer& animatableMeshes = mImpl->animatableMeshes;
602 // Find the animatableMesh and destroy it
603 for ( AnimatableMeshIter iter = animatableMeshes.Begin(); iter != animatableMeshes.End(); ++iter )
605 AnimatableMesh& current = **iter;
606 if ( ¤t == animatableMesh )
608 animatableMeshes.Erase( iter );
614 void UpdateManager::AddMaterial( Material* material )
616 DALI_ASSERT_DEBUG( NULL != material );
618 mImpl->materials.PushBack( material );
619 RenderMaterial* renderMaterial = new RenderMaterial();
621 typedef MessageValue1< RenderManager, RenderMaterial* > DerivedType;
623 // Reserve some memory inside the render queue
624 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
626 // Construct message in the render queue memory; note that delete should not be called on the return value
627 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddRenderMaterial, renderMaterial );
629 material->SetRenderMaterial( renderMaterial );
630 material->OnStageConnection( *mImpl->sceneController );
633 void UpdateManager::RemoveMaterial( Material* theMaterial )
635 // Caused by last reference to material being released (e.g. app or internal mesh-actor)
637 for ( MaterialIter iter=mImpl->materials.Begin(), end=mImpl->materials.End() ; iter != end ; ++iter )
639 const Material* aMaterial = *iter;
641 if( aMaterial == theMaterial )
643 typedef MessageValue1< RenderManager, RenderMaterial* > DerivedType;
645 // Reserve some memory inside the render queue
646 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
648 // Construct message in the render queue memory; note that delete should not be called on the return value
649 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveRenderMaterial, theMaterial->GetRenderMaterial() );
651 mImpl->materials.Erase( iter );
657 RenderTaskList* UpdateManager::GetRenderTaskList( bool systemLevel )
661 // copy the list, this is only likely to happen once in application life cycle
662 return &(mImpl->taskList);
666 // copy the list, this is only likely to happen once in application life cycle
667 return &(mImpl->systemLevelTaskList);
671 void UpdateManager::AddGesture( PanGesture* gesture )
673 DALI_ASSERT_DEBUG( NULL != gesture );
675 mImpl->gestures.PushBack( gesture );
678 void UpdateManager::RemoveGesture( PanGesture* gesture )
680 DALI_ASSERT_DEBUG( gesture != NULL );
682 GestureContainer& gestures = mImpl->gestures;
684 // Find the gesture and destroy it
685 for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
687 PanGesture& current = **iter;
688 if ( ¤t == gesture )
690 mImpl->gestures.Erase( iter );
694 // Should not reach here
695 DALI_ASSERT_DEBUG(false);
698 unsigned int* UpdateManager::ReserveMessageSlot( std::size_t size, bool updateScene )
700 return mImpl->messageQueue.ReserveMessageSlot( size, updateScene );
703 void UpdateManager::EventProcessingStarted()
705 mImpl->messageQueue.EventProcessingStarted();
708 bool UpdateManager::FlushQueue()
710 return mImpl->messageQueue.FlushQueue();
713 void UpdateManager::ResetNodeProperty( Node& node )
715 node.ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
718 void UpdateManager::ResetProperties()
720 PERF_MONITOR_START(PerformanceMonitor::RESET_PROPERTIES);
722 // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
723 mImpl->animationFinishedDuringUpdate = false;
725 // Animated properties have to be reset to their original value each frame
727 // Reset node properties
730 ResetNodeProperty( *mImpl->root );
733 if ( mImpl->systemLevelRoot )
735 ResetNodeProperty( *mImpl->systemLevelRoot );
738 // Reset the Connected Nodes
739 const std::set<Node*>::iterator endIter = mImpl->connectedNodes.end();
740 for( std::set<Node*>::iterator iter = mImpl->connectedNodes.begin(); endIter != iter; ++iter )
742 ResetNodeProperty( **iter );
745 // If a Node is disconnected, it may still be "active" (requires a reset in next frame)
746 for( std::set<Node*>::iterator iter = mImpl->activeDisconnectedNodes.begin(); mImpl->activeDisconnectedNodes.end() != iter; iter = mImpl->activeDisconnectedNodes.begin() )
749 node->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
750 node->SetActive( false );
752 // Move everything from activeDisconnectedNodes to disconnectedNodes (no need to reset again)
753 mImpl->activeDisconnectedNodes.erase( iter );
754 mImpl->disconnectedNodes.insert( node );
757 // Reset system-level render-task list properties to base values
758 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
760 for (RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
762 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
765 // Reset render-task list properties to base values.
766 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
768 for (RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
770 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
773 // Reset custom object properties to base values
774 for (OwnerContainer<PropertyOwner*>::Iterator iter = mImpl->customObjects.Begin(); iter != mImpl->customObjects.End(); ++iter)
776 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
779 // Reset animatable shader properties to base values
780 for (ShaderIter iter = mImpl->shaders.Begin(); iter != mImpl->shaders.End(); ++iter)
782 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
785 // Reset animatable mesh properties to base values
786 for ( AnimatableMeshIter iter = mImpl->animatableMeshes.Begin(); iter != mImpl->animatableMeshes.End(); ++iter )
788 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
791 PERF_MONITOR_END(PerformanceMonitor::RESET_PROPERTIES);
794 bool UpdateManager::ProcessGestures( unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds )
796 bool gestureUpdated( false );
798 // constrain gestures... (in construction order)
799 GestureContainer& gestures = mImpl->gestures;
801 for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
803 PanGesture& gesture = **iter;
804 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
805 gestureUpdated |= gesture.UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
808 return gestureUpdated;
811 void UpdateManager::Animate( float elapsedSeconds )
813 PERF_MONITOR_START(PerformanceMonitor::ANIMATE_NODES);
815 AnimationContainer &animations = mImpl->animations;
816 AnimationIter iter = animations.Begin();
817 while ( iter != animations.End() )
819 Animation* animation = *iter;
820 bool finished = animation->Update(mSceneGraphBuffers.GetUpdateBufferIndex(), elapsedSeconds);
822 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
824 // Remove animations that had been destroyed but were still waiting for an update
825 if (animation->GetState() == Animation::Destroyed)
827 iter = animations.Erase(iter);
835 if ( mImpl->animationFinishedDuringUpdate )
837 // The application should be notified by NotificationManager, in another thread
838 mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationFinishedNotifier );
841 PERF_MONITOR_END(PerformanceMonitor::ANIMATE_NODES);
844 void UpdateManager::ApplyConstraints()
846 PERF_MONITOR_START(PerformanceMonitor::APPLY_CONSTRAINTS);
848 // constrain custom objects... (in construction order)
849 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
851 const OwnerContainer< PropertyOwner* >::Iterator endIter = customObjects.End();
852 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); endIter != iter; ++iter )
854 PropertyOwner& object = **iter;
855 ConstrainPropertyOwner( object, mSceneGraphBuffers.GetUpdateBufferIndex() );
858 // constrain nodes... (in Depth First traversal order)
861 ConstrainNodes( *(mImpl->root), mSceneGraphBuffers.GetUpdateBufferIndex() );
864 if ( mImpl->systemLevelRoot )
866 ConstrainNodes( *(mImpl->systemLevelRoot), mSceneGraphBuffers.GetUpdateBufferIndex() );
869 // constrain other property-owners after nodes as they are more likely to depend on a node's
870 // current frame property than vice versa. They tend to be final constraints (no further
871 // constraints depend on their properties)
872 // e.g. ShaderEffect uniform a function of Actor's position.
873 // Mesh vertex a function of Actor's position or world position.
875 // TODO: refactor this code (and reset nodes) as these are all just lists of property-owners
876 // they can be all processed in a super-list of property-owners.
878 // Constrain system-level render-tasks
879 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
881 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter )
883 RenderTask& task = **iter;
884 ConstrainPropertyOwner( task, mSceneGraphBuffers.GetUpdateBufferIndex() );
887 // Constrain render-tasks
888 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
890 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter )
892 RenderTask& task = **iter;
893 ConstrainPropertyOwner( task, mSceneGraphBuffers.GetUpdateBufferIndex() );
896 // constrain meshes (in construction order)
897 AnimatableMeshContainer& meshes = mImpl->animatableMeshes;
898 for ( AnimatableMeshIter iter = meshes.Begin(); iter != meshes.End(); ++iter )
900 AnimatableMesh& mesh = **iter;
901 ConstrainPropertyOwner( mesh, mSceneGraphBuffers.GetUpdateBufferIndex() );
904 // constrain shaders... (in construction order)
905 ShaderContainer& shaders = mImpl->shaders;
907 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
909 Shader& shader = **iter;
910 ConstrainPropertyOwner( shader, mSceneGraphBuffers.GetUpdateBufferIndex() );
913 PERF_MONITOR_END(PerformanceMonitor::APPLY_CONSTRAINTS);
916 void UpdateManager::ProcessPropertyNotifications()
918 PropertyNotificationContainer ¬ifications = mImpl->propertyNotifications;
919 PropertyNotificationIter iter = notifications.Begin();
921 while ( iter != notifications.End() )
923 PropertyNotification* notification = *iter;
925 bool valid = notification->Check( mSceneGraphBuffers.GetUpdateBufferIndex() );
929 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
935 void UpdateManager::UpdateNodes()
937 mImpl->nodeDirtyFlags = NothingFlag;
944 PERF_MONITOR_START( PerformanceMonitor::UPDATE_NODES );
946 // Prepare resources, update shaders, update attachments, for each node
947 // And add the renderers to the sorted layers. Start from root, which is also a layer
948 mImpl->nodeDirtyFlags = UpdateNodesAndAttachments( *( mImpl->root ),
949 mSceneGraphBuffers.GetUpdateBufferIndex(),
950 mImpl->resourceManager,
951 mImpl->renderQueue );
953 if ( mImpl->systemLevelRoot )
955 mImpl->nodeDirtyFlags |= UpdateNodesAndAttachments( *( mImpl->systemLevelRoot ),
956 mSceneGraphBuffers.GetUpdateBufferIndex(),
957 mImpl->resourceManager,
958 mImpl->renderQueue );
961 PERF_MONITOR_END( PerformanceMonitor::UPDATE_NODES );
964 void UpdateManager::UpdateMeshes( BufferIndex updateBufferIndex, AnimatableMeshContainer& meshes )
966 for ( AnimatableMeshIter iter = meshes.Begin(); iter != meshes.End(); ++iter )
968 AnimatableMesh& current = **iter;
969 current.UpdateMesh( updateBufferIndex );
973 void UpdateManager::UpdateMaterials( BufferIndex updateBufferIndex, MaterialContainer& materials )
975 for( MaterialIter iter = materials.Begin(), end = materials.End(); iter != end; iter++ )
977 Material* material = *iter;
978 material->PrepareResources( updateBufferIndex, mImpl->resourceManager );
982 void UpdateManager::PrepareMaterials( BufferIndex updateBufferIndex, MaterialContainer& materials )
984 for( MaterialIter iter = materials.Begin(), end = materials.End(); iter != end; iter++ )
986 Material* material = *iter;
987 material->PrepareRender( updateBufferIndex );
991 unsigned int UpdateManager::Update( float elapsedSeconds,
992 unsigned int lastVSyncTimeMilliseconds,
993 unsigned int nextVSyncTimeMilliseconds )
995 PERF_MONITOR_END(PerformanceMonitor::FRAME_RATE); // Mark the End of the last frame
996 PERF_MONITOR_NEXT_FRAME(); // Prints out performance info for the last frame (if enabled)
997 PERF_MONITOR_START(PerformanceMonitor::FRAME_RATE); // Mark the start of this current frame
999 // Measure the time spent in UpdateManager::Update
1000 PERF_MONITOR_START(PerformanceMonitor::UPDATE);
1002 // Update the frame time delta on the render thread.
1003 mImpl->renderManager.SetFrameDeltaTime(elapsedSeconds);
1005 // 1) Clear nodes/resources which were previously discarded
1006 mImpl->discardQueue.Clear( mSceneGraphBuffers.GetUpdateBufferIndex() );
1008 // 2) Grab any loaded resources
1009 bool resourceChanged = mImpl->resourceManager.UpdateCache( mSceneGraphBuffers.GetUpdateBufferIndex() );
1011 // 3) Process Touches & Gestures
1012 mImpl->touchResampler.Update();
1013 const bool gestureUpdated = ProcessGestures( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
1015 const bool updateScene = // The scene-graph requires an update if..
1016 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
1017 IsAnimationRunning() || // ..at least one animation is running OR
1018 mImpl->dynamicsChanged || // ..there was a change in the dynamics simulation OR
1019 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
1020 resourceChanged || // ..one or more resources were updated/changed OR
1021 gestureUpdated; // ..a gesture property was updated
1023 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
1024 // values if the scene was updated in the previous frame.
1025 if( updateScene || mImpl->previousUpdateScene )
1027 // 4) Reset properties from the previous update
1031 // 5) Process the queued scene messages
1032 mImpl->messageQueue.ProcessMessages();
1034 // 6) Post Process Ids of resources updated by renderer
1035 mImpl->resourceManager.PostProcessResources( mSceneGraphBuffers.GetUpdateBufferIndex() );
1037 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
1038 // renderer lists if the scene was updated in the previous frame.
1039 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
1040 if( updateScene || mImpl->previousUpdateScene )
1043 Animate( elapsedSeconds );
1045 // 8) Apply Constraints
1048 #ifdef DYNAMICS_SUPPORT
1049 // 9) Update dynamics simulation
1050 mImpl->dynamicsChanged = false;
1051 if( mImpl->dynamicsWorld )
1053 mImpl->dynamicsChanged = mImpl->dynamicsWorld->Update( elapsedSeconds );
1057 // 10) Check Property Notifications
1058 ProcessPropertyNotifications();
1060 // 11) Clear the lists of renderable-attachments from the previous update
1061 ClearRenderables( mImpl->sortedLayers );
1062 ClearRenderables( mImpl->systemLevelSortedLayers );
1064 // 12) Update animated meshes
1065 UpdateMeshes( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->animatableMeshes );
1067 // 13) Update materials. Prepares image resources
1068 UpdateMaterials( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->materials );
1070 // 14) Update node hierarchy and perform sorting / culling.
1071 // This will populate each Layer with a list of renderers which are ready.
1074 // 15) Prepare for the next render
1075 PERF_MONITOR_START(PerformanceMonitor::PREPARE_RENDERABLES);
1076 PrepareMaterials( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->materials );
1077 PrepareRenderables( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->sortedLayers );
1078 PrepareRenderables( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->systemLevelSortedLayers );
1079 PERF_MONITOR_END(PerformanceMonitor::PREPARE_RENDERABLES);
1081 PERF_MONITOR_START(PerformanceMonitor::PROCESS_RENDER_TASKS);
1083 // 16) Process the RenderTasks; this creates the instructions for rendering the next frame.
1084 // reset the update buffer index and make sure there is enough room in the instruction container
1085 mImpl->renderInstructions.ResetAndReserve( mSceneGraphBuffers.GetUpdateBufferIndex(),
1086 mImpl->taskList.GetTasks().Count() + mImpl->systemLevelTaskList.GetTasks().Count() );
1088 if ( NULL != mImpl->root )
1090 ProcessRenderTasks( mSceneGraphBuffers.GetUpdateBufferIndex(),
1091 mImpl->completeStatusManager,
1094 mImpl->sortedLayers,
1095 mImpl->renderSortingHelper,
1096 mImpl->renderInstructions );
1098 // Process the system-level RenderTasks last
1099 if ( NULL != mImpl->systemLevelRoot )
1101 ProcessRenderTasks( mSceneGraphBuffers.GetUpdateBufferIndex(),
1102 mImpl->completeStatusManager,
1103 mImpl->systemLevelTaskList,
1104 *mImpl->systemLevelRoot,
1105 mImpl->systemLevelSortedLayers,
1106 mImpl->renderSortingHelper,
1107 mImpl->renderInstructions );
1112 // check the countdown and notify (note, at the moment this is only done for normal tasks, not for systemlevel tasks)
1113 bool doRenderOnceNotify = false;
1114 mImpl->renderTaskWaiting = false;
1115 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
1116 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(), endIter = tasks.End();
1117 endIter != iter; ++iter )
1119 RenderTask& renderTask(*(*iter));
1121 renderTask.UpdateState();
1123 if( renderTask.IsWaitingToRender() &&
1124 renderTask.ReadyToRender(mSceneGraphBuffers.GetUpdateBufferIndex()) /*avoid updating forever when source actor is off-stage*/ )
1126 mImpl->renderTaskWaiting = true; // keep update/render threads alive
1129 if( renderTask.HasRendered() )
1131 doRenderOnceNotify = true;
1135 if( doRenderOnceNotify )
1137 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
1138 mImpl->notificationManager.QueueCompleteNotification( mImpl->taskList.GetCompleteNotificationInterface() );
1141 PERF_MONITOR_END(PerformanceMonitor::PROCESS_RENDER_TASKS);
1143 // Macro is undefined in release build.
1144 SNAPSHOT_NODE_LOGGING;
1146 // A ResetProperties() may be required in the next frame
1147 mImpl->previousUpdateScene = updateScene;
1149 // Check whether further updates are required
1150 unsigned int keepUpdating = KeepUpdatingCheck( elapsedSeconds );
1152 #ifdef PERFORMANCE_MONITOR_ENABLED
1153 // Always keep rendering when measuring FPS
1154 keepUpdating |= KeepUpdating::MONITORING_PERFORMANCE;
1157 // The update has finished; swap the double-buffering indices
1158 mSceneGraphBuffers.Swap();
1160 // tell the update manager that we're done so the queue can be given to event thread
1161 mImpl->notificationManager.UpdateCompleted();
1163 PERF_MONITOR_END(PerformanceMonitor::UPDATE);
1165 return keepUpdating;
1168 unsigned int UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
1170 // Update the duration set via Stage::KeepRendering()
1171 if ( mImpl->keepRenderingSeconds > 0.0f )
1173 mImpl->keepRenderingSeconds -= elapsedSeconds;
1176 unsigned int keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
1178 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
1179 // Keep updating until no messages are received and no animations are running.
1180 // If an animation has just finished, update at least once more for Discard end-actions.
1181 // No need to check for renderQueue as there is always a render after update and if that
1182 // render needs another update it will tell the adaptor to call update again
1184 if ( mImpl->keepRenderingSeconds > 0.0f )
1186 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
1189 if ( IsAnimationRunning() ||
1190 mImpl->animationFinishedDuringUpdate )
1192 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
1195 if ( mImpl->dynamicsChanged )
1197 keepUpdatingRequest |= KeepUpdating::DYNAMICS_CHANGED;
1200 if ( mImpl->renderTaskWaiting )
1202 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
1205 return keepUpdatingRequest;
1208 void UpdateManager::SetBackgroundColor( const Vector4& color )
1210 typedef MessageValue1< RenderManager, Vector4 > DerivedType;
1212 // Reserve some memory inside the render queue
1213 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1215 // Construct message in the render queue memory; note that delete should not be called on the return value
1216 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
1219 void UpdateManager::SetDefaultSurfaceRect( const Rect<int>& rect )
1221 typedef MessageValue1< RenderManager, Rect<int> > DerivedType;
1223 // Reserve some memory inside the render queue
1224 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1226 // Construct message in the render queue memory; note that delete should not be called on the return value
1227 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1230 void UpdateManager::KeepRendering( float durationSeconds )
1232 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1235 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, bool systemLevel )
1239 // just copy the vector of pointers
1240 mImpl->sortedLayers = layers;
1244 mImpl->systemLevelSortedLayers = layers;
1248 #ifdef DYNAMICS_SUPPORT
1250 void UpdateManager::InitializeDynamicsWorld( SceneGraph::DynamicsWorld* dynamicsWorld, Integration::DynamicsWorldSettings* worldSettings )
1252 dynamicsWorld->Initialize( mImpl->sceneController, worldSettings, &mSceneGraphBuffers );
1253 mImpl->dynamicsWorld = dynamicsWorld;
1256 void UpdateManager::TerminateDynamicsWorld()
1258 mImpl->dynamicsWorld.Reset();
1261 #endif // DYNAMICS_SUPPORT
1263 } // namespace SceneGraph
1265 } // namespace Internal