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/common/scene-graph-buffers.h>
42 #include <dali/internal/update/controllers/render-message-dispatcher.h>
43 #include <dali/internal/update/controllers/scene-controller-impl.h>
44 #include <dali/internal/update/effects/scene-graph-material.h>
45 #include <dali/internal/update/geometry/scene-graph-geometry.h>
46 #include <dali/internal/update/gestures/scene-graph-pan-gesture.h>
47 #include <dali/internal/update/manager/prepare-render-algorithms.h>
48 #include <dali/internal/update/manager/process-render-tasks.h>
49 #include <dali/internal/update/manager/sorted-layers.h>
50 #include <dali/internal/update/manager/update-algorithms.h>
51 #include <dali/internal/update/manager/update-manager-debug.h>
52 #include <dali/internal/update/node-attachments/scene-graph-camera-attachment.h>
53 #include <dali/internal/update/nodes/node.h>
54 #include <dali/internal/update/nodes/scene-graph-layer.h>
55 #include <dali/internal/update/queue/update-message-queue.h>
56 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
57 #include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
58 #include <dali/internal/update/resources/resource-manager.h>
59 #include <dali/internal/update/resources/complete-status-manager.h>
60 #include <dali/internal/update/touch/touch-resampler.h>
62 #include <dali/internal/render/common/render-instruction-container.h>
63 #include <dali/internal/render/common/render-manager.h>
64 #include <dali/internal/render/queue/render-queue.h>
65 #include <dali/internal/render/common/performance-monitor.h>
66 #include <dali/internal/render/gl-resources/texture-cache.h>
67 #include <dali/internal/render/shaders/scene-graph-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< Geometry* > GeometryContainer;
130 typedef GeometryContainer::Iterator GeometryIter;
131 typedef GeometryContainer::ConstIterator GeometryConstIter;
133 typedef OwnerContainer< Material* > MaterialContainer;
134 typedef MaterialContainer::Iterator MaterialIter;
135 typedef MaterialContainer::ConstIterator MaterialConstIter;
137 typedef OwnerContainer< Shader* > ShaderContainer;
138 typedef ShaderContainer::Iterator ShaderIter;
139 typedef ShaderContainer::ConstIterator ShaderConstIter;
141 typedef OwnerContainer<PanGesture*> GestureContainer;
142 typedef GestureContainer::Iterator GestureIter;
143 typedef GestureContainer::ConstIterator GestureConstIter;
147 * Structure to contain UpdateManager internal data
149 struct UpdateManager::Impl
151 Impl( NotificationManager& notificationManager,
152 GlSyncAbstraction& glSyncAbstraction,
153 CompleteNotificationInterface& animationFinishedNotifier,
154 PropertyNotifier& propertyNotifier,
155 ResourceManager& resourceManager,
156 DiscardQueue& discardQueue,
157 RenderController& renderController,
158 RenderManager& renderManager,
159 RenderQueue& renderQueue,
160 TextureCache& textureCache,
161 TouchResampler& touchResampler,
162 SceneGraphBuffers& sceneGraphBuffers )
164 renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ),
165 notificationManager( notificationManager ),
166 animationFinishedNotifier( animationFinishedNotifier ),
167 propertyNotifier( propertyNotifier ),
168 resourceManager( resourceManager ),
169 discardQueue( discardQueue ),
170 renderController( renderController ),
171 sceneController( NULL ),
172 renderManager( renderManager ),
173 renderQueue( renderQueue ),
174 renderInstructions( renderManager.GetRenderInstructionContainer() ),
175 completeStatusManager( glSyncAbstraction, renderMessageDispatcher, resourceManager ),
176 touchResampler( touchResampler ),
177 backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
178 taskList ( completeStatusManager ),
179 systemLevelTaskList ( completeStatusManager ),
181 systemLevelRoot( NULL ),
182 messageQueue( renderController, sceneGraphBuffers ),
183 dynamicsChanged( false ),
184 keepRenderingSeconds( 0.0f ),
185 animationFinishedDuringUpdate( false ),
186 activeConstraints( 0 ),
187 nodeDirtyFlags( TransformFlag ), // set to TransformFlag to ensure full update the first time through Update()
188 previousUpdateScene( false ),
190 renderSortingHelper(),
191 renderTaskWaiting( false )
193 sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue, textureCache, completeStatusManager );
198 // Disconnect render tasks from nodes, before destroying the nodes
199 RenderTaskList::RenderTaskContainer& tasks = taskList.GetTasks();
200 for (RenderTaskList::RenderTaskContainer::Iterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
202 (*iter)->SetSourceNode( NULL );
204 // ..repeat for system level RenderTasks
205 RenderTaskList::RenderTaskContainer& systemLevelTasks = systemLevelTaskList.GetTasks();
206 for (RenderTaskList::RenderTaskContainer::Iterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
208 (*iter)->SetSourceNode( NULL );
211 // UpdateManager owns the Nodes
212 DestroyNodeSet( activeDisconnectedNodes );
213 DestroyNodeSet( connectedNodes );
214 DestroyNodeSet( disconnectedNodes );
216 // If there is root, reset it, otherwise do nothing as rendering was never started
225 if( systemLevelRoot )
227 systemLevelRoot->OnDestroy();
229 delete systemLevelRoot;
230 systemLevelRoot = NULL;
233 sceneController->GetTextureCache().SetBufferIndices(NULL); // TODO - Remove
234 delete sceneController;
237 SceneGraphBuffers sceneGraphBuffers; ///< Used to keep track of which buffers are being written or read
238 RenderMessageDispatcher renderMessageDispatcher; ///< Used for passing messages to the render-thread
239 NotificationManager& notificationManager; ///< Queues notification messages for the event-thread.
240 CompleteNotificationInterface& animationFinishedNotifier; ///< Provides notification to applications when animations are finished.
241 PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
242 ResourceManager& resourceManager; ///< resource manager
243 DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
244 RenderController& renderController; ///< render controller
245 SceneControllerImpl* sceneController; ///< scene controller
246 RenderManager& renderManager; ///< This is responsible for rendering the results of each "update"
247 RenderQueue& renderQueue; ///< Used to queue messages for the next render
248 RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions
249 CompleteStatusManager completeStatusManager; ///< Complete Status Manager
250 TouchResampler& touchResampler; ///< Used to resample touch events on every update.
252 Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
254 RenderTaskList taskList; ///< The list of scene graph render-tasks
255 RenderTaskList systemLevelTaskList; ///< Separate render-tasks for system-level content
257 Layer* root; ///< The root node (root is a layer)
258 Layer* systemLevelRoot; ///< A separate root-node for system-level content
259 std::set< Node* > activeDisconnectedNodes; ///< A container of new or modified nodes (without parent) owned by UpdateManager
260 std::set< Node* > connectedNodes; ///< A container of connected (with parent) nodes owned by UpdateManager
261 std::set< Node* > disconnectedNodes; ///< A container of inactive disconnected nodes (without parent) owned by UpdateManager
263 SortedLayerPointers sortedLayers; ///< A container of Layer pointers sorted by depth
264 SortedLayerPointers systemLevelSortedLayers; ///< A separate container of system-level Layers
266 OwnerContainer< PropertyOwner* > customObjects; ///< A container of owned objects (with custom properties)
268 AnimationContainer animations; ///< A container of owned animations
269 PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
271 GeometryContainer geometries; ///< A container of geometries
272 MaterialContainer materials; ///< A container of materials
274 ShaderContainer shaders; ///< A container of owned shaders
276 MessageQueue messageQueue; ///< The messages queued from the event-thread
278 #ifdef DYNAMICS_SUPPORT
279 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 GestureContainer gestures; ///< A container of owned gesture detectors
294 bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
297 UpdateManager::UpdateManager( NotificationManager& notificationManager,
298 GlSyncAbstraction& glSyncAbstraction,
299 CompleteNotificationInterface& animationFinishedNotifier,
300 PropertyNotifier& propertyNotifier,
301 ResourceManager& resourceManager,
302 DiscardQueue& discardQueue,
303 RenderController& controller,
304 RenderManager& renderManager,
305 RenderQueue& renderQueue,
306 TextureCache& textureCache,
307 TouchResampler& touchResampler )
310 mImpl = new Impl( notificationManager,
312 animationFinishedNotifier,
321 mSceneGraphBuffers );
323 textureCache.SetBufferIndices( &mSceneGraphBuffers );
326 UpdateManager::~UpdateManager()
331 EventToUpdate& UpdateManager::GetEventToUpdate()
333 return mImpl->messageQueue;
336 void UpdateManager::InstallRoot( SceneGraph::Layer* layer, bool systemLevel )
338 DALI_ASSERT_DEBUG( layer->IsLayer() );
339 DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
343 DALI_ASSERT_DEBUG( mImpl->root == NULL && "Root Node already installed" );
348 DALI_ASSERT_DEBUG( mImpl->systemLevelRoot == NULL && "System-level Root Node already installed" );
349 mImpl->systemLevelRoot = layer;
352 layer->SetRoot(true);
355 void UpdateManager::AddNode( Node* node )
357 DALI_ASSERT_ALWAYS( NULL != node );
358 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
360 mImpl->activeDisconnectedNodes.insert( node ); // Takes ownership of node
363 void UpdateManager::ConnectNode( Node* parent, Node* node, int index )
365 DALI_ASSERT_ALWAYS( NULL != parent );
366 DALI_ASSERT_ALWAYS( NULL != node );
367 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
369 // Move from active/disconnectedNodes to connectedNodes
370 std::set<Node*>::size_type removed = mImpl->activeDisconnectedNodes.erase( node );
373 removed = mImpl->disconnectedNodes.erase( node );
374 DALI_ASSERT_ALWAYS( removed );
376 mImpl->connectedNodes.insert( node );
378 node->SetActive( true );
380 parent->ConnectChild( node, index );
383 void UpdateManager::DisconnectNode( Node* node )
385 Node* parent = node->GetParent();
386 DALI_ASSERT_ALWAYS( NULL != parent );
387 parent->SetDirtyFlag( ChildDeletedFlag ); // make parent dirty so that render items dont get reused
389 // Move from connectedNodes to activeDisconnectedNodes (reset properties next frame)
390 parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node, mImpl->connectedNodes, mImpl->activeDisconnectedNodes );
393 void UpdateManager::SetNodeActive( Node* node )
395 DALI_ASSERT_ALWAYS( NULL != node );
396 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
398 // Move from disconnectedNodes to activeDisconnectedNodes (reset properties next frame)
399 std::set<Node*>::size_type removed = mImpl->disconnectedNodes.erase( node );
400 DALI_ASSERT_ALWAYS( removed );
401 mImpl->activeDisconnectedNodes.insert( node );
403 node->SetActive( true );
406 void UpdateManager::DestroyNode( Node* node )
408 DALI_ASSERT_ALWAYS( NULL != node );
409 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
411 // Transfer ownership from new/disconnectedNodes to the discard queue
412 // This keeps the nodes alive, until the render-thread has finished with them
413 std::set<Node*>::size_type removed = mImpl->activeDisconnectedNodes.erase( node );
416 removed = mImpl->disconnectedNodes.erase( node );
417 DALI_ASSERT_ALWAYS( removed );
419 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
421 // Notify the Node about impending destruction
425 void UpdateManager::AttachToNode( Node* node, NodeAttachment* attachment )
427 DALI_ASSERT_DEBUG( node != NULL );
428 DALI_ASSERT_DEBUG( attachment != NULL );
430 // attach node to attachment first so that parent is known by the time attachment is connected
431 node->Attach( *attachment ); // node takes ownership
432 attachment->ConnectToSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
435 void UpdateManager::AddObject( PropertyOwner* object )
437 DALI_ASSERT_DEBUG( NULL != object );
439 mImpl->customObjects.PushBack( object );
442 void UpdateManager::RemoveObject( PropertyOwner* object )
444 DALI_ASSERT_DEBUG( NULL != object );
446 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
448 // Find the object and destroy it
449 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); iter != customObjects.End(); ++iter )
451 PropertyOwner* current = *iter;
452 if ( current == object )
454 customObjects.Erase( iter );
459 // Should not reach here
460 DALI_ASSERT_DEBUG(false);
463 void UpdateManager::AddAnimation( Animation* animation )
465 mImpl->animations.PushBack( animation );
468 void UpdateManager::StopAnimation( Animation* animation )
470 DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
472 bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
474 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
477 void UpdateManager::RemoveAnimation( Animation* animation )
479 DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
481 animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
483 DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
486 bool UpdateManager::IsAnimationRunning() const
488 bool isRunning(false);
489 AnimationContainer& animations = mImpl->animations;
491 // Find any animation that isn't stopped or paused
493 const AnimationIter endIter = animations.End();
494 for ( AnimationIter iter = animations.Begin(); !isRunning && iter != endIter; ++iter )
496 const Animation::State state = (*iter)->GetState();
498 if (state != Animation::Stopped &&
499 state != Animation::Paused)
508 void UpdateManager::AddPropertyNotification( PropertyNotification* propertyNotification )
510 mImpl->propertyNotifications.PushBack( propertyNotification );
513 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
515 PropertyNotificationContainer &propertyNotifications = mImpl->propertyNotifications;
516 PropertyNotificationIter iter = propertyNotifications.Begin();
518 while ( iter != propertyNotifications.End() )
520 if( *iter == propertyNotification )
522 propertyNotifications.Erase(iter);
529 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
531 DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
532 propertyNotification->SetNotifyMode( notifyMode );
536 void UpdateManager::AddGeometry( Geometry* geometry )
538 DALI_ASSERT_DEBUG( NULL != geometry );
539 mImpl->geometries.PushBack( geometry );
542 void UpdateManager::RemoveGeometry( Geometry* geometry )
544 DALI_ASSERT_DEBUG(geometry != NULL);
546 GeometryContainer& geometries = mImpl->geometries;
548 // Find the geometry and destroy it
549 for ( GeometryIter iter = geometries.Begin(); iter != geometries.End(); ++iter )
551 Geometry& current = **iter;
552 if ( ¤t == geometry )
554 // Transfer ownership to the discard queue
555 // This keeps the geometry alive, until the render-thread has finished with it
556 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), geometries.Release( iter ) );
562 // Should not reach here
563 DALI_ASSERT_DEBUG(false);
566 void UpdateManager::AddMaterial( Material* material )
568 DALI_ASSERT_DEBUG( NULL != material );
570 mImpl->materials.PushBack( material );
573 void UpdateManager::RemoveMaterial( Material* material )
575 DALI_ASSERT_DEBUG(material != NULL);
577 MaterialContainer& materials = mImpl->materials;
579 // Find the material and destroy it
580 for ( MaterialIter iter = materials.Begin(); iter != materials.End(); ++iter )
582 Material& current = **iter;
583 if ( ¤t == material )
585 // Transfer ownership to the discard queue
586 // This keeps the material alive, until the render-thread has finished with it
587 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), materials.Release( iter ) );
592 // Should not reach here
593 DALI_ASSERT_DEBUG(false);
596 void UpdateManager::AddShader( Shader* shader )
598 DALI_ASSERT_DEBUG( NULL != shader );
600 if( mImpl->shaders.Count() == 0 )
602 // the first added shader becomes our default shader
603 // Construct message in the render queue memory; note that delete should not be called on the return value
604 typedef MessageValue1< RenderManager, Shader* > DerivedType;
606 // Reserve some memory inside the render queue
607 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
609 // Construct message in the render queue memory; note that delete should not be called on the return value
610 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultShader, shader );
613 mImpl->shaders.PushBack( shader );
615 // Allows the shader to dispatch texture requests to the cache
616 shader->Initialize( mImpl->renderQueue, mImpl->sceneController->GetTextureCache() );
619 void UpdateManager::RemoveShader( Shader* shader )
621 DALI_ASSERT_DEBUG(shader != NULL);
623 ShaderContainer& shaders = mImpl->shaders;
625 // Find the shader and destroy it
626 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
628 Shader& current = **iter;
629 if ( ¤t == shader )
631 // Transfer ownership to the discard queue
632 // This keeps the shader alive, until the render-thread has finished with it
633 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), shaders.Release( iter ) );
638 // Should not reach here
639 DALI_ASSERT_DEBUG(false);
642 void UpdateManager::SetShaderProgram( Shader* shader, GeometryType geometryType, ShaderSubTypes subType, ResourceId resourceId, size_t shaderHash, bool modifiesGeometry )
644 DALI_LOG_TRACE_METHOD_FMT(Debug::Filter::gShader, " - (geometryType:%d subType:%d id:%d hash:%d)\n", geometryType, subType, resourceId, shaderHash);
646 DALI_ASSERT_ALWAYS( NULL != shader && "shader is uninitialized" );
648 Integration::ShaderDataPtr shaderData( mImpl->resourceManager.GetShaderData(resourceId) );
651 shaderData->SetHashValue( shaderHash );
652 shaderData->SetResourceId( resourceId );
654 typedef MessageValue6< Shader, GeometryType, Internal::ShaderSubTypes, Integration::ResourceId, Integration::ShaderDataPtr, ProgramCache*, bool> DerivedType;
656 // Reserve some memory inside the render queue
657 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
659 // Construct message in the render queue memory; note that delete should not be called on the return value
660 new (slot) DerivedType( shader, &Shader::SetProgram, geometryType, subType, resourceId, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
664 RenderTaskList* UpdateManager::GetRenderTaskList( bool systemLevel )
668 // copy the list, this is only likely to happen once in application life cycle
669 return &(mImpl->taskList);
673 // copy the list, this is only likely to happen once in application life cycle
674 return &(mImpl->systemLevelTaskList);
678 void UpdateManager::AddGesture( PanGesture* gesture )
680 DALI_ASSERT_DEBUG( NULL != gesture );
682 mImpl->gestures.PushBack( gesture );
685 void UpdateManager::RemoveGesture( PanGesture* gesture )
687 DALI_ASSERT_DEBUG( gesture != NULL );
689 GestureContainer& gestures = mImpl->gestures;
691 // Find the gesture and destroy it
692 for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
694 PanGesture& current = **iter;
695 if ( ¤t == gesture )
697 mImpl->gestures.Erase( iter );
701 // Should not reach here
702 DALI_ASSERT_DEBUG(false);
705 void UpdateManager::ResetNodeProperty( Node& node )
707 node.ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
710 void UpdateManager::ResetProperties()
712 PERF_MONITOR_START(PerformanceMonitor::RESET_PROPERTIES);
714 // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
715 mImpl->animationFinishedDuringUpdate = false;
717 // Animated properties have to be reset to their original value each frame
719 // Reset node properties
722 ResetNodeProperty( *mImpl->root );
725 if ( mImpl->systemLevelRoot )
727 ResetNodeProperty( *mImpl->systemLevelRoot );
730 // Reset the Connected Nodes
731 const std::set<Node*>::iterator endIter = mImpl->connectedNodes.end();
732 for( std::set<Node*>::iterator iter = mImpl->connectedNodes.begin(); endIter != iter; ++iter )
734 ResetNodeProperty( **iter );
737 // If a Node is disconnected, it may still be "active" (requires a reset in next frame)
738 for( std::set<Node*>::iterator iter = mImpl->activeDisconnectedNodes.begin(); mImpl->activeDisconnectedNodes.end() != iter; iter = mImpl->activeDisconnectedNodes.begin() )
741 node->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
742 node->SetActive( false );
744 // Move everything from activeDisconnectedNodes to disconnectedNodes (no need to reset again)
745 mImpl->activeDisconnectedNodes.erase( iter );
746 mImpl->disconnectedNodes.insert( node );
749 // Reset system-level render-task list properties to base values
750 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
752 for (RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
754 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
757 // Reset render-task list properties to base values.
758 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
760 for (RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
762 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
765 // Reset custom object properties to base values
766 for (OwnerContainer<PropertyOwner*>::Iterator iter = mImpl->customObjects.Begin(); iter != mImpl->customObjects.End(); ++iter)
768 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
771 // Reset animatable material properties to base values
772 for (MaterialIter iter = mImpl->materials.Begin(); iter != mImpl->materials.End(); ++iter)
774 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
777 // Reset animatable geometry properties to base values
778 for (GeometryIter iter = mImpl->geometries.Begin(); iter != mImpl->geometries.End(); ++iter)
780 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
783 // Reset animatable shader properties to base values
784 for (ShaderIter iter = mImpl->shaders.Begin(); iter != mImpl->shaders.End(); ++iter)
786 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
789 PERF_MONITOR_END(PerformanceMonitor::RESET_PROPERTIES);
792 bool UpdateManager::ProcessGestures( unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds )
794 bool gestureUpdated( false );
796 // constrain gestures... (in construction order)
797 GestureContainer& gestures = mImpl->gestures;
799 for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
801 PanGesture& gesture = **iter;
802 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
803 gestureUpdated |= gesture.UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
806 return gestureUpdated;
809 void UpdateManager::Animate( float elapsedSeconds )
811 PERF_MONITOR_START(PerformanceMonitor::ANIMATE_NODES);
813 AnimationContainer &animations = mImpl->animations;
814 AnimationIter iter = animations.Begin();
815 while ( iter != animations.End() )
817 Animation* animation = *iter;
818 bool finished = animation->Update(mSceneGraphBuffers.GetUpdateBufferIndex(), elapsedSeconds);
820 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
822 // Remove animations that had been destroyed but were still waiting for an update
823 if (animation->GetState() == Animation::Destroyed)
825 iter = animations.Erase(iter);
833 if ( mImpl->animationFinishedDuringUpdate )
835 // The application should be notified by NotificationManager, in another thread
836 mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationFinishedNotifier );
839 PERF_MONITOR_END(PerformanceMonitor::ANIMATE_NODES);
842 void UpdateManager::ApplyConstraints()
844 PERF_MONITOR_START(PerformanceMonitor::APPLY_CONSTRAINTS);
846 mImpl->activeConstraints = 0;
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 mImpl->activeConstraints += ConstrainPropertyOwner( object, mSceneGraphBuffers.GetUpdateBufferIndex() );
858 // constrain nodes... (in Depth First traversal order)
861 mImpl->activeConstraints += ConstrainNodes( *(mImpl->root), mSceneGraphBuffers.GetUpdateBufferIndex() );
864 if ( mImpl->systemLevelRoot )
866 mImpl->activeConstraints += 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 mImpl->activeConstraints += 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 mImpl->activeConstraints += ConstrainPropertyOwner( task, mSceneGraphBuffers.GetUpdateBufferIndex() );
896 // Constrain Materials and geometries
897 MaterialContainer& materials = mImpl->materials;
898 for ( MaterialIter iter = materials.Begin(); iter != materials.End(); ++iter )
900 Material& material = **iter;
901 mImpl->activeConstraints += ConstrainPropertyOwner( material, mSceneGraphBuffers.GetUpdateBufferIndex() );
904 GeometryContainer& geometries = mImpl->geometries;
905 for ( GeometryIter iter = geometries.Begin(); iter != geometries.End(); ++iter )
907 Geometry& geometry = **iter;
908 mImpl->activeConstraints += ConstrainPropertyOwner( geometry, mSceneGraphBuffers.GetUpdateBufferIndex() );
911 // constrain shaders... (in construction order)
912 ShaderContainer& shaders = mImpl->shaders;
914 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
916 Shader& shader = **iter;
917 mImpl->activeConstraints += ConstrainPropertyOwner( shader, mSceneGraphBuffers.GetUpdateBufferIndex() );
920 PERF_MONITOR_END(PerformanceMonitor::APPLY_CONSTRAINTS);
923 void UpdateManager::ProcessPropertyNotifications()
925 PropertyNotificationContainer ¬ifications = mImpl->propertyNotifications;
926 PropertyNotificationIter iter = notifications.Begin();
928 while ( iter != notifications.End() )
930 PropertyNotification* notification = *iter;
932 bool valid = notification->Check( mSceneGraphBuffers.GetUpdateBufferIndex() );
936 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
942 void UpdateManager::UpdateNodes()
944 mImpl->nodeDirtyFlags = NothingFlag;
951 PERF_MONITOR_START( PerformanceMonitor::UPDATE_NODES );
953 // Prepare resources, update shaders, update attachments, for each node
954 // And add the renderers to the sorted layers. Start from root, which is also a layer
955 mImpl->nodeDirtyFlags = UpdateNodesAndAttachments( *( mImpl->root ),
956 mSceneGraphBuffers.GetUpdateBufferIndex(),
957 mImpl->resourceManager,
958 mImpl->renderQueue );
960 if ( mImpl->systemLevelRoot )
962 mImpl->nodeDirtyFlags |= UpdateNodesAndAttachments( *( mImpl->systemLevelRoot ),
963 mSceneGraphBuffers.GetUpdateBufferIndex(),
964 mImpl->resourceManager,
965 mImpl->renderQueue );
968 PERF_MONITOR_END( PerformanceMonitor::UPDATE_NODES );
971 unsigned int UpdateManager::Update( float elapsedSeconds,
972 unsigned int lastVSyncTimeMilliseconds,
973 unsigned int nextVSyncTimeMilliseconds )
975 PERF_MONITOR_END(PerformanceMonitor::FRAME_RATE); // Mark the End of the last frame
976 PERF_MONITOR_NEXT_FRAME(); // Prints out performance info for the last frame (if enabled)
977 PERF_MONITOR_START(PerformanceMonitor::FRAME_RATE); // Mark the start of this current frame
979 // Measure the time spent in UpdateManager::Update
980 PERF_MONITOR_START(PerformanceMonitor::UPDATE);
982 // Update the frame time delta on the render thread.
983 mImpl->renderManager.SetFrameDeltaTime(elapsedSeconds);
985 // 1) Clear nodes/resources which were previously discarded
986 mImpl->discardQueue.Clear( mSceneGraphBuffers.GetUpdateBufferIndex() );
988 // 2) Grab any loaded resources
989 bool resourceChanged = mImpl->resourceManager.UpdateCache( mSceneGraphBuffers.GetUpdateBufferIndex() );
991 // 3) Process Touches & Gestures
992 mImpl->touchResampler.Update();
993 const bool gestureUpdated = ProcessGestures( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
995 const bool updateScene = // The scene-graph requires an update if..
996 mImpl->activeConstraints != 0 || // ..constraints were active in previous frame OR
997 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
998 IsAnimationRunning() || // ..at least one animation is running OR
999 mImpl->dynamicsChanged || // ..there was a change in the dynamics simulation OR
1000 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
1001 resourceChanged || // ..one or more resources were updated/changed OR
1002 gestureUpdated; // ..a gesture property was updated
1004 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
1005 // values if the scene was updated in the previous frame.
1006 if( updateScene || mImpl->previousUpdateScene )
1008 // 4) Reset properties from the previous update
1012 // 5) Process the queued scene messages
1013 mImpl->messageQueue.ProcessMessages();
1015 // 6) Post Process Ids of resources updated by renderer
1016 mImpl->resourceManager.PostProcessResources( mSceneGraphBuffers.GetUpdateBufferIndex() );
1018 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
1019 // renderer lists if the scene was updated in the previous frame.
1020 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
1021 if( updateScene || mImpl->previousUpdateScene )
1024 Animate( elapsedSeconds );
1026 // 8) Apply Constraints
1029 #ifdef DYNAMICS_SUPPORT
1030 // 9) Update dynamics simulation
1031 mImpl->dynamicsChanged = false;
1032 if( mImpl->dynamicsWorld )
1034 mImpl->dynamicsChanged = mImpl->dynamicsWorld->Update( elapsedSeconds );
1038 // 10) Check Property Notifications
1039 ProcessPropertyNotifications();
1041 // 11) Clear the lists of renderable-attachments from the previous update
1042 ClearRenderables( mImpl->sortedLayers );
1043 ClearRenderables( mImpl->systemLevelSortedLayers );
1045 // 12) Update node hierarchy and perform sorting / culling.
1046 // This will populate each Layer with a list of renderers which are ready.
1049 // 13) Prepare for the next render
1050 PERF_MONITOR_START(PerformanceMonitor::PREPARE_RENDERABLES);
1052 PrepareRenderables( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->sortedLayers );
1053 PrepareRenderables( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->systemLevelSortedLayers );
1054 PERF_MONITOR_END(PerformanceMonitor::PREPARE_RENDERABLES);
1056 PERF_MONITOR_START(PerformanceMonitor::PROCESS_RENDER_TASKS);
1058 // 14) Process the RenderTasks; this creates the instructions for rendering the next frame.
1059 // reset the update buffer index and make sure there is enough room in the instruction container
1060 mImpl->renderInstructions.ResetAndReserve( mSceneGraphBuffers.GetUpdateBufferIndex(),
1061 mImpl->taskList.GetTasks().Count() + mImpl->systemLevelTaskList.GetTasks().Count() );
1063 if ( NULL != mImpl->root )
1065 ProcessRenderTasks( mSceneGraphBuffers.GetUpdateBufferIndex(),
1066 mImpl->completeStatusManager,
1069 mImpl->sortedLayers,
1070 mImpl->renderSortingHelper,
1071 mImpl->renderInstructions );
1073 // Process the system-level RenderTasks last
1074 if ( NULL != mImpl->systemLevelRoot )
1076 ProcessRenderTasks( mSceneGraphBuffers.GetUpdateBufferIndex(),
1077 mImpl->completeStatusManager,
1078 mImpl->systemLevelTaskList,
1079 *mImpl->systemLevelRoot,
1080 mImpl->systemLevelSortedLayers,
1081 mImpl->renderSortingHelper,
1082 mImpl->renderInstructions );
1087 // check the countdown and notify (note, at the moment this is only done for normal tasks, not for systemlevel tasks)
1088 bool doRenderOnceNotify = false;
1089 mImpl->renderTaskWaiting = false;
1090 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
1091 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(), endIter = tasks.End();
1092 endIter != iter; ++iter )
1094 RenderTask& renderTask(*(*iter));
1096 renderTask.UpdateState();
1098 if( renderTask.IsWaitingToRender() &&
1099 renderTask.ReadyToRender(mSceneGraphBuffers.GetUpdateBufferIndex()) /*avoid updating forever when source actor is off-stage*/ )
1101 mImpl->renderTaskWaiting = true; // keep update/render threads alive
1104 if( renderTask.HasRendered() )
1106 doRenderOnceNotify = true;
1110 if( doRenderOnceNotify )
1112 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
1113 mImpl->notificationManager.QueueCompleteNotification( mImpl->taskList.GetCompleteNotificationInterface() );
1116 PERF_MONITOR_END(PerformanceMonitor::PROCESS_RENDER_TASKS);
1118 // Macro is undefined in release build.
1119 SNAPSHOT_NODE_LOGGING;
1121 // A ResetProperties() may be required in the next frame
1122 mImpl->previousUpdateScene = updateScene;
1124 // Check whether further updates are required
1125 unsigned int keepUpdating = KeepUpdatingCheck( elapsedSeconds );
1127 #ifdef PERFORMANCE_MONITOR_ENABLED
1128 // Always keep rendering when measuring FPS
1129 keepUpdating |= KeepUpdating::MONITORING_PERFORMANCE;
1132 // The update has finished; swap the double-buffering indices
1133 mSceneGraphBuffers.Swap();
1135 // tell the update manager that we're done so the queue can be given to event thread
1136 mImpl->notificationManager.UpdateCompleted();
1138 PERF_MONITOR_END(PerformanceMonitor::UPDATE);
1140 return keepUpdating;
1143 unsigned int UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
1145 // Update the duration set via Stage::KeepRendering()
1146 if ( mImpl->keepRenderingSeconds > 0.0f )
1148 mImpl->keepRenderingSeconds -= elapsedSeconds;
1151 unsigned int keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
1153 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
1154 // Keep updating until no messages are received and no animations are running.
1155 // If an animation has just finished, update at least once more for Discard end-actions.
1156 // No need to check for renderQueue as there is always a render after update and if that
1157 // render needs another update it will tell the adaptor to call update again
1159 if ( mImpl->keepRenderingSeconds > 0.0f )
1161 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
1164 if ( !mImpl->messageQueue.WasEmpty() )
1166 keepUpdatingRequest |= KeepUpdating::INCOMING_MESSAGES;
1169 if ( IsAnimationRunning() ||
1170 mImpl->animationFinishedDuringUpdate )
1172 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
1175 if ( mImpl->dynamicsChanged )
1177 keepUpdatingRequest |= KeepUpdating::DYNAMICS_CHANGED;
1180 if ( mImpl->renderTaskWaiting )
1182 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
1185 return keepUpdatingRequest;
1188 void UpdateManager::SetBackgroundColor( const Vector4& color )
1190 typedef MessageValue1< RenderManager, Vector4 > DerivedType;
1192 // Reserve some memory inside the render queue
1193 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1195 // Construct message in the render queue memory; note that delete should not be called on the return value
1196 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
1199 void UpdateManager::SetDefaultSurfaceRect( const Rect<int>& rect )
1201 typedef MessageValue1< RenderManager, Rect<int> > DerivedType;
1203 // Reserve some memory inside the render queue
1204 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1206 // Construct message in the render queue memory; note that delete should not be called on the return value
1207 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1210 void UpdateManager::KeepRendering( float durationSeconds )
1212 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1215 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, bool systemLevel )
1219 // just copy the vector of pointers
1220 mImpl->sortedLayers = layers;
1224 mImpl->systemLevelSortedLayers = layers;
1228 #ifdef DYNAMICS_SUPPORT
1230 void UpdateManager::InitializeDynamicsWorld( SceneGraph::DynamicsWorld* dynamicsWorld, Integration::DynamicsWorldSettings* worldSettings )
1232 dynamicsWorld->Initialize( mImpl->sceneController, worldSettings, &mSceneGraphBuffers );
1233 mImpl->dynamicsWorld = dynamicsWorld;
1236 void UpdateManager::TerminateDynamicsWorld()
1238 mImpl->dynamicsWorld.Reset();
1241 #endif // DYNAMICS_SUPPORT
1243 } // namespace SceneGraph
1245 } // namespace Internal