2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 // Licensed under the Flora License, Version 1.0 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://floralicense.org/license/
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an AS IS BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
18 #include <dali/internal/update/manager/update-manager.h>
21 #include <dali/public-api/common/stage.h>
22 #include <dali/public-api/common/set-wrapper.h>
24 #include <dali/integration-api/core.h>
25 #include <dali/integration-api/render-controller.h>
26 #include <dali/integration-api/shader-data.h>
27 #include <dali/integration-api/debug.h>
28 #include <dali/integration-api/dynamics/dynamics-world-settings.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>
37 #include <dali/internal/event/animation/animation-finished-notifier.h>
38 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
40 #include <dali/internal/update/animation/scene-graph-animator.h>
41 #include <dali/internal/update/animation/scene-graph-animation.h>
42 #include <dali/internal/update/common/discard-queue.h>
43 #include <dali/internal/update/common/double-buffered.h>
44 #include <dali/internal/update/manager/prepare-render-algorithms.h>
45 #include <dali/internal/update/manager/process-render-tasks.h>
46 #include <dali/internal/update/resources/resource-manager.h>
47 #include <dali/internal/update/resources/complete-status-manager.h>
48 #include <dali/internal/update/common/scene-graph-buffers.h>
49 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
50 #include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
51 #include <dali/internal/update/manager/sorted-layers.h>
52 #include <dali/internal/update/manager/update-algorithms.h>
53 #include <dali/internal/update/queue/update-message-queue.h>
54 #include <dali/internal/update/manager/update-manager-debug.h>
55 #include <dali/internal/update/controllers/render-message-dispatcher.h>
56 #include <dali/internal/update/controllers/scene-controller-impl.h>
57 #include <dali/internal/update/gestures/scene-graph-pan-gesture.h>
58 #include <dali/internal/update/modeling/scene-graph-material.h>
59 #include <dali/internal/update/node-attachments/scene-graph-camera-attachment.h>
60 #include <dali/internal/update/nodes/node.h>
61 #include <dali/internal/update/nodes/scene-graph-layer.h>
62 #include <dali/internal/update/dynamics/scene-graph-dynamics-world.h>
63 #include <dali/internal/update/touch/touch-resampler.h>
65 #include <dali/internal/render/common/render-instruction-container.h>
66 #include <dali/internal/render/common/render-manager.h>
67 #include <dali/internal/render/queue/render-queue.h>
68 #include <dali/internal/render/common/performance-monitor.h>
69 #include <dali/internal/render/gl-resources/texture-cache.h>
70 #include <dali/internal/render/renderers/render-material.h>
71 #include <dali/internal/render/shaders/shader.h>
73 // Un-comment to enable node tree debug logging
74 //#define NODE_TREE_LOGGING 1
76 #if ( defined( DEBUG_ENABLED ) && defined( NODE_TREE_LOGGING ) )
77 #define SNAPSHOT_NODE_LOGGING \
78 const int FRAME_COUNT_TRIGGER = 16;\
79 if( mImpl->frameCounter >= FRAME_COUNT_TRIGGER )\
81 if ( NULL != mImpl->root )\
83 mImpl->frameCounter = 0;\
84 PrintNodeTree( *mImpl->root, mSceneGraphBuffers.GetUpdateBufferIndex(), "" );\
87 mImpl->frameCounter++;
89 #define SNAPSHOT_NODE_LOGGING
92 #if defined(DEBUG_ENABLED)
93 extern Debug::Filter* gRenderTaskLogFilter;
97 using namespace Dali::Integration;
98 using Dali::Internal::Update::MessageQueue;
112 const int DEFAULT_CAMERA_INDEX = -1;
114 void DestroyNodeSet( std::set<Node*>& nodeSet )
116 for( std::set<Node*>::iterator iter = nodeSet.begin(); iter != nodeSet.end(); ++iter )
120 // Call Node::OnDestroy as each node is destroyed
130 typedef OwnerContainer< Shader* > ShaderContainer;
131 typedef ShaderContainer::Iterator ShaderIter;
132 typedef ShaderContainer::ConstIterator ShaderConstIter;
134 typedef AnimatableMeshContainer::Iterator AnimatableMeshIter;
135 typedef AnimatableMeshContainer::ConstIterator AnimatableMeshConstIter;
136 typedef MaterialContainer::Iterator MaterialIter;
138 typedef OwnerContainer<PanGesture*> GestureContainer;
139 typedef GestureContainer::Iterator GestureIter;
140 typedef GestureContainer::ConstIterator GestureConstIter;
144 * Structure to contain UpdateManager internal data
146 struct UpdateManager::Impl
148 Impl( NotificationManager& notificationManager,
149 GlSyncAbstraction& glSyncAbstraction,
150 AnimationFinishedNotifier& animationFinishedNotifier,
151 PropertyNotifier& propertyNotifier,
152 ResourceManager& resourceManager,
153 DiscardQueue& discardQueue,
154 RenderController& renderController,
155 RenderManager& renderManager,
156 RenderQueue& renderQueue,
157 TextureCache& textureCache,
158 TouchResampler& touchResampler,
159 SceneGraphBuffers& sceneGraphBuffers )
161 renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ),
162 notificationManager( notificationManager ),
163 animationFinishedNotifier( animationFinishedNotifier ),
164 propertyNotifier( propertyNotifier ),
165 resourceManager( resourceManager ),
166 discardQueue( discardQueue ),
167 renderController( renderController ),
168 sceneController( NULL ),
169 renderManager( renderManager ),
170 renderQueue( renderQueue ),
171 renderInstructions( renderManager.GetRenderInstructionContainer() ),
172 completeStatusManager( glSyncAbstraction, renderMessageDispatcher, resourceManager ),
173 touchResampler( touchResampler ),
174 backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
175 taskList ( completeStatusManager ),
176 systemLevelTaskList ( completeStatusManager ),
178 systemLevelRoot( NULL ),
179 defaultShader( NULL ),
180 messageQueue( renderController, sceneGraphBuffers ),
181 dynamicsWorld( NULL ),
182 dynamicsChanged( false ),
183 keepRenderingSeconds( 0.0f ),
184 animationFinishedDuringUpdate( false ),
185 activeConstraints( 0 ),
186 nodeDirtyFlags( TransformFlag ), // set to TransformFlag to ensure full update the first time through Update()
187 previousUpdateScene( false ),
189 renderSortingHelper(),
190 renderTaskList( NULL ),
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 AnimationFinishedNotifier& 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 Shader* defaultShader; ///< The default shader; owned by ShaderContainer
272 ShaderContainer shaders; ///< A container of owned shaders
273 AnimatableMeshContainer animatableMeshes; ///< A container of owned animatable meshes
274 MaterialContainer materials; ///< A container of owned materials
276 MessageQueue messageQueue; ///< The messages queued from the event-thread
278 OwnerPointer<DynamicsWorld> dynamicsWorld; ///< Wrapper for dynamics simulation
279 bool dynamicsChanged; ///< This is set to true if an object is changed in the dynamics simulation tick
281 float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
282 bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
284 unsigned int activeConstraints; ///< number of active constraints from previous frame
285 int nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
286 bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
288 int frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
289 RendererSortingHelper renderSortingHelper; ///< helper used to sort transparent renderers
291 Internal::RenderTaskList* renderTaskList; ///< Stores a pointer to the internal implementation to the render task list.
292 GestureContainer gestures; ///< A container of owned gesture detectors
293 bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
296 UpdateManager::UpdateManager( NotificationManager& notificationManager,
297 GlSyncAbstraction& glSyncAbstraction,
298 AnimationFinishedNotifier& animationFinishedNotifier,
299 PropertyNotifier& propertyNotifier,
300 ResourceManager& resourceManager,
301 DiscardQueue& discardQueue,
302 RenderController& controller,
303 RenderManager& renderManager,
304 RenderQueue& renderQueue,
305 TextureCache& textureCache,
306 TouchResampler& touchResampler )
309 mImpl = new Impl( notificationManager,
311 animationFinishedNotifier,
320 mSceneGraphBuffers );
322 textureCache.SetBufferIndices( &mSceneGraphBuffers );
325 UpdateManager::~UpdateManager()
330 void UpdateManager::SetRenderTaskList( Internal::RenderTaskList* renderTaskList )
332 mImpl->renderTaskList = renderTaskList;
335 EventToUpdate& UpdateManager::GetEventToUpdate()
337 return mImpl->messageQueue;
340 void UpdateManager::InstallRoot( SceneGraph::Layer* layer, bool systemLevel )
342 DALI_ASSERT_DEBUG( layer->IsLayer() );
343 DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
347 DALI_ASSERT_DEBUG( mImpl->root == NULL && "Root Node already installed" );
352 DALI_ASSERT_DEBUG( mImpl->systemLevelRoot == NULL && "System-level Root Node already installed" );
353 mImpl->systemLevelRoot = layer;
356 layer->SetRoot(true);
359 void UpdateManager::AddNode( Node* node )
361 DALI_ASSERT_ALWAYS( NULL != node );
362 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
364 mImpl->activeDisconnectedNodes.insert( node ); // Takes ownership of node
367 void UpdateManager::ConnectNode( Node* parent, Node* node )
369 DALI_ASSERT_ALWAYS( NULL != parent );
370 DALI_ASSERT_ALWAYS( NULL != node );
371 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
373 // Move from active/disconnectedNodes to connectedNodes
374 std::set<Node*>::size_type removed = mImpl->activeDisconnectedNodes.erase( node );
377 removed = mImpl->disconnectedNodes.erase( node );
378 DALI_ASSERT_ALWAYS( removed );
380 mImpl->connectedNodes.insert( node );
382 node->SetActive( true );
384 parent->ConnectChild( node );
387 void UpdateManager::DisconnectNode( Node* node )
389 Node* parent = node->GetParent();
390 DALI_ASSERT_ALWAYS( NULL != parent );
391 parent->SetDirtyFlag( ChildDeletedFlag ); // make parent dirty so that render items dont get reused
393 // Move from connectedNodes to activeDisconnectedNodes (reset properties next frame)
394 parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node, mImpl->connectedNodes, mImpl->activeDisconnectedNodes );
397 void UpdateManager::SetNodeActive( Node* node )
399 DALI_ASSERT_ALWAYS( NULL != node );
400 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
402 // Move from disconnectedNodes to activeDisconnectedNodes (reset properties next frame)
403 std::set<Node*>::size_type removed = mImpl->disconnectedNodes.erase( node );
404 DALI_ASSERT_ALWAYS( removed );
405 mImpl->activeDisconnectedNodes.insert( node );
407 node->SetActive( true );
410 void UpdateManager::DestroyNode( Node* node )
412 DALI_ASSERT_ALWAYS( NULL != node );
413 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
415 // Transfer ownership from new/disconnectedNodes to the discard queue
416 // This keeps the nodes alive, until the render-thread has finished with them
417 std::set<Node*>::size_type removed = mImpl->activeDisconnectedNodes.erase( node );
420 removed = mImpl->disconnectedNodes.erase( node );
421 DALI_ASSERT_ALWAYS( removed );
423 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
425 // Notify the Node about impending destruction
429 void UpdateManager::AttachToNode( Node* node, NodeAttachment* attachment )
431 DALI_ASSERT_DEBUG( node != NULL );
432 DALI_ASSERT_DEBUG( attachment != NULL );
434 // attach node to attachment first so that parent is known by the time attachment is connected
435 node->Attach( *attachment ); // node takes ownership
436 attachment->ConnectToSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
439 void UpdateManager::AddObject( PropertyOwner* object )
441 DALI_ASSERT_DEBUG( NULL != object );
443 mImpl->customObjects.PushBack( object );
446 void UpdateManager::RemoveObject( PropertyOwner* object )
448 DALI_ASSERT_DEBUG( NULL != object );
450 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
452 // Find the object and destroy it
453 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); iter != customObjects.End(); ++iter )
455 PropertyOwner* current = *iter;
456 if ( current == object )
458 customObjects.Erase( iter );
463 // Should not reach here
464 DALI_ASSERT_DEBUG(false);
467 void UpdateManager::AddAnimation( Animation* animation )
469 mImpl->animations.PushBack( animation );
472 void UpdateManager::StopAnimation( Animation* animation )
474 DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
476 bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
478 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
481 void UpdateManager::RemoveAnimation( Animation* animation )
483 DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
485 animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
487 DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
490 bool UpdateManager::IsAnimationRunning() const
492 bool isRunning(false);
493 AnimationContainer& animations = mImpl->animations;
495 // Find any animation that isn't stopped or paused
497 const AnimationIter endIter = animations.End();
498 for ( AnimationIter iter = animations.Begin(); !isRunning && iter != endIter; ++iter )
500 const Animation::State state = (*iter)->GetState();
502 if (state != Animation::Stopped &&
503 state != Animation::Paused)
512 void UpdateManager::AddPropertyNotification( PropertyNotification* propertyNotification )
514 mImpl->propertyNotifications.PushBack( propertyNotification );
517 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
519 PropertyNotificationContainer &propertyNotifications = mImpl->propertyNotifications;
520 PropertyNotificationIter iter = propertyNotifications.Begin();
522 while ( iter != propertyNotifications.End() )
524 if( *iter == propertyNotification )
526 propertyNotifications.Erase(iter);
533 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
535 DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
536 propertyNotification->SetNotifyMode( notifyMode );
539 Shader* UpdateManager::GetDefaultShader()
541 return mImpl->defaultShader;
544 void UpdateManager::AddShader( Shader* shader )
546 DALI_ASSERT_DEBUG( NULL != shader );
548 // Note: The first shader added becomes the default shader
549 if( NULL == mImpl->defaultShader )
551 mImpl->defaultShader = shader;
554 mImpl->shaders.PushBack( shader );
556 // Allows the shader to dispatch texture requests to the cache and "save shader"
557 // requests to the resource manager from the render thread.
558 shader->Initialize( mImpl->renderManager, mImpl->renderQueue, mImpl->sceneController->GetTextureCache() );
561 void UpdateManager::RemoveShader(Shader* shader)
563 DALI_ASSERT_DEBUG(shader != NULL);
565 ShaderContainer& shaders = mImpl->shaders;
567 // Find the shader and destroy it
568 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
570 Shader& current = **iter;
571 if ( ¤t == shader )
573 // Transfer ownership to the discard queue
574 // This keeps the shader alive, until the render-thread has finished with it
575 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), shaders.Release( iter ) );
580 // Should not reach here
581 DALI_ASSERT_DEBUG(false);
584 void UpdateManager::SetShaderProgram( Shader* shader, GeometryType geometryType, ShaderSubTypes subType, ResourceId resourceId, size_t shaderHash )
586 DALI_LOG_TRACE_METHOD_FMT(Debug::Filter::gShader, " - (geometryType:%d subType:%d id:%d hash:%d)\n", geometryType, subType, resourceId, shaderHash);
588 DALI_ASSERT_ALWAYS( NULL != shader && "shader is uninitialized" );
590 Integration::ShaderDataPtr shaderData( mImpl->resourceManager.GetShaderData(resourceId) );
591 shaderData->SetHashValue( shaderHash );
595 // This is done in the render thread, to allow GL program compilation
596 // Will trigger a NotifySaveRequest back to updateManager to forward onto ResourceClient
597 typedef MessageValue5< Shader, GeometryType, Internal::ShaderSubTypes, Integration::ResourceId, Integration::ShaderDataPtr, Context* > DerivedType;
599 // Reserve some memory inside the render queue
600 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
602 // Construct message in the render queue memory; note that delete should not be called on the return value
603 new (slot) DerivedType( shader, &Shader::SetProgram, geometryType, subType, resourceId, shaderData, &(mImpl->renderManager.GetContext()) );
607 void UpdateManager::AddAnimatableMesh( AnimatableMesh* animatableMesh )
609 mImpl->animatableMeshes.PushBack(animatableMesh);
612 void UpdateManager::RemoveAnimatableMesh( AnimatableMesh* animatableMesh )
614 DALI_ASSERT_DEBUG(animatableMesh != NULL);
616 AnimatableMeshContainer& animatableMeshes = mImpl->animatableMeshes;
618 // Find the animatableMesh and destroy it
619 for ( AnimatableMeshIter iter = animatableMeshes.Begin(); iter != animatableMeshes.End(); ++iter )
621 AnimatableMesh& current = **iter;
622 if ( ¤t == animatableMesh )
624 animatableMeshes.Erase( iter );
630 void UpdateManager::AddMaterial( Material* material )
632 DALI_ASSERT_DEBUG( NULL != material );
634 mImpl->materials.PushBack( material );
635 RenderMaterial* renderMaterial = new RenderMaterial();
637 typedef MessageValue1< RenderManager, RenderMaterial* > DerivedType;
639 // Reserve some memory inside the render queue
640 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
642 // Construct message in the render queue memory; note that delete should not be called on the return value
643 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddRenderMaterial, renderMaterial );
645 material->SetRenderMaterial( renderMaterial );
646 material->OnStageConnection( *mImpl->sceneController );
649 void UpdateManager::RemoveMaterial( Material* theMaterial )
651 // Caused by last reference to material being released (e.g. app or internal mesh-actor)
653 for ( MaterialIter iter=mImpl->materials.Begin(), end=mImpl->materials.End() ; iter != end ; ++iter )
655 const Material* aMaterial = *iter;
657 if( aMaterial == theMaterial )
659 typedef MessageValue1< RenderManager, RenderMaterial* > DerivedType;
661 // Reserve some memory inside the render queue
662 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
664 // Construct message in the render queue memory; note that delete should not be called on the return value
665 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveRenderMaterial, theMaterial->GetRenderMaterial() );
667 mImpl->materials.Erase( iter );
673 RenderTaskList* UpdateManager::GetRenderTaskList( bool systemLevel )
677 // copy the list, this is only likely to happen once in application life cycle
678 return &(mImpl->taskList);
682 // copy the list, this is only likely to happen once in application life cycle
683 return &(mImpl->systemLevelTaskList);
687 void UpdateManager::AddGesture( PanGesture* gesture )
689 DALI_ASSERT_DEBUG( NULL != gesture );
691 mImpl->gestures.PushBack( gesture );
694 void UpdateManager::RemoveGesture( PanGesture* gesture )
696 DALI_ASSERT_DEBUG( gesture != NULL );
698 GestureContainer& gestures = mImpl->gestures;
700 // Find the gesture and destroy it
701 for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
703 PanGesture& current = **iter;
704 if ( ¤t == gesture )
706 mImpl->gestures.Erase( iter );
710 // Should not reach here
711 DALI_ASSERT_DEBUG(false);
714 void UpdateManager::ResetNodeProperty( Node& node )
716 node.ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
719 void UpdateManager::ResetProperties()
721 PERF_MONITOR_START(PerformanceMonitor::RESET_PROPERTIES);
723 // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
724 mImpl->animationFinishedDuringUpdate = false;
726 // Animated properties have to be reset to their original value each frame
728 // Reset node properties
731 ResetNodeProperty( *mImpl->root );
734 if ( mImpl->systemLevelRoot )
736 ResetNodeProperty( *mImpl->systemLevelRoot );
739 // Reset the Connected Nodes
740 const std::set<Node*>::iterator endIter = mImpl->connectedNodes.end();
741 for( std::set<Node*>::iterator iter = mImpl->connectedNodes.begin(); endIter != iter; ++iter )
743 ResetNodeProperty( **iter );
746 // If a Node is disconnected, it may still be "active" (requires a reset in next frame)
747 for( std::set<Node*>::iterator iter = mImpl->activeDisconnectedNodes.begin(); mImpl->activeDisconnectedNodes.end() != iter; iter = mImpl->activeDisconnectedNodes.begin() )
750 node->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
751 node->SetActive( false );
753 // Move everything from activeDisconnectedNodes to disconnectedNodes (no need to reset again)
754 mImpl->activeDisconnectedNodes.erase( iter );
755 mImpl->disconnectedNodes.insert( node );
758 // Reset system-level render-task list properties to base values
759 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
761 for (RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
763 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
766 // Reset render-task list properties to base values.
767 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
769 for (RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
771 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
774 // Reset custom object properties to base values
775 for (OwnerContainer<PropertyOwner*>::Iterator iter = mImpl->customObjects.Begin(); iter != mImpl->customObjects.End(); ++iter)
777 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
780 // Reset animatable shader properties to base values
781 for (ShaderIter iter = mImpl->shaders.Begin(); iter != mImpl->shaders.End(); ++iter)
783 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
786 // Reset animatable mesh properties to base values
787 for ( AnimatableMeshIter iter = mImpl->animatableMeshes.Begin(); iter != mImpl->animatableMeshes.End(); ++iter )
789 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
792 PERF_MONITOR_END(PerformanceMonitor::RESET_PROPERTIES);
795 bool UpdateManager::ProcessGestures( unsigned int lastVSyncTime, unsigned int nextVSyncTime )
797 bool gestureUpdated( false );
799 // constrain gestures... (in construction order)
800 GestureContainer& gestures = mImpl->gestures;
802 for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
804 PanGesture& gesture = **iter;
805 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
806 gestureUpdated |= gesture.UpdateProperties( lastVSyncTime, nextVSyncTime );
809 return gestureUpdated;
812 void UpdateManager::Animate( float elapsedSeconds )
814 PERF_MONITOR_START(PerformanceMonitor::ANIMATE_NODES);
816 AnimationContainer &animations = mImpl->animations;
817 AnimationIter iter = animations.Begin();
818 while ( iter != animations.End() )
820 Animation* animation = *iter;
821 bool finished = animation->Update(mSceneGraphBuffers.GetUpdateBufferIndex(), elapsedSeconds);
823 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
825 // Remove animations that had been destroyed but were still waiting for an update
826 if (animation->GetState() == Animation::Destroyed)
828 iter = animations.Erase(iter);
836 if ( mImpl->animationFinishedDuringUpdate )
838 // The application should be notified by NotificationManager, in another thread
839 mImpl->notificationManager.QueueMessage( AnimationFinishedMessage( mImpl->animationFinishedNotifier ) );
842 PERF_MONITOR_END(PerformanceMonitor::ANIMATE_NODES);
845 void UpdateManager::ApplyConstraints()
847 PERF_MONITOR_START(PerformanceMonitor::APPLY_CONSTRAINTS);
849 mImpl->activeConstraints = 0;
851 // constrain custom objects... (in construction order)
852 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
854 const OwnerContainer< PropertyOwner* >::Iterator endIter = customObjects.End();
855 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); endIter != iter; ++iter )
857 PropertyOwner& object = **iter;
858 mImpl->activeConstraints += ConstrainPropertyOwner( object, mSceneGraphBuffers.GetUpdateBufferIndex() );
861 // constrain nodes... (in Depth First traversal order)
864 mImpl->activeConstraints += ConstrainNodes( *(mImpl->root), mSceneGraphBuffers.GetUpdateBufferIndex() );
867 if ( mImpl->systemLevelRoot )
869 mImpl->activeConstraints += ConstrainNodes( *(mImpl->systemLevelRoot), mSceneGraphBuffers.GetUpdateBufferIndex() );
872 // constrain other property-owners after nodes as they are more likely to depend on a node's
873 // current frame property than vice versa. They tend to be final constraints (no further
874 // constraints depend on their properties)
875 // e.g. ShaderEffect uniform a function of Actor's position.
876 // Mesh vertex a function of Actor's position or world position.
878 // TODO: refactor this code (and reset nodes) as these are all just lists of property-owners
879 // they can be all processed in a super-list of property-owners.
881 // Constrain system-level render-tasks
882 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
884 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter )
886 RenderTask& task = **iter;
887 mImpl->activeConstraints += ConstrainPropertyOwner( task, mSceneGraphBuffers.GetUpdateBufferIndex() );
890 // Constrain render-tasks
891 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
893 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter )
895 RenderTask& task = **iter;
896 mImpl->activeConstraints += ConstrainPropertyOwner( task, mSceneGraphBuffers.GetUpdateBufferIndex() );
899 // constrain meshes (in construction order)
900 AnimatableMeshContainer& meshes = mImpl->animatableMeshes;
901 for ( AnimatableMeshIter iter = meshes.Begin(); iter != meshes.End(); ++iter )
903 AnimatableMesh& mesh = **iter;
904 mImpl->activeConstraints += ConstrainPropertyOwner( mesh, mSceneGraphBuffers.GetUpdateBufferIndex() );
907 // constrain shaders... (in construction order)
908 ShaderContainer& shaders = mImpl->shaders;
910 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
912 Shader& shader = **iter;
913 mImpl->activeConstraints += ConstrainPropertyOwner( shader, mSceneGraphBuffers.GetUpdateBufferIndex() );
916 PERF_MONITOR_END(PerformanceMonitor::APPLY_CONSTRAINTS);
919 void UpdateManager::ProcessPropertyNotifications()
921 PropertyNotificationContainer ¬ifications = mImpl->propertyNotifications;
922 PropertyNotificationIter iter = notifications.Begin();
924 while ( iter != notifications.End() )
926 PropertyNotification* notification = *iter;
928 bool valid = notification->Check( mSceneGraphBuffers.GetUpdateBufferIndex() );
932 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
938 void UpdateManager::UpdateNodes()
940 mImpl->nodeDirtyFlags = NothingFlag;
947 PERF_MONITOR_START( PerformanceMonitor::UPDATE_NODES );
949 Shader* defaultShader = GetDefaultShader();
951 if ( NULL != defaultShader )
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,
961 if ( mImpl->systemLevelRoot )
963 mImpl->nodeDirtyFlags |= UpdateNodesAndAttachments( *( mImpl->systemLevelRoot ),
964 mSceneGraphBuffers.GetUpdateBufferIndex(),
965 mImpl->resourceManager,
971 PERF_MONITOR_END( PerformanceMonitor::UPDATE_NODES );
974 void UpdateManager::UpdateMeshes( BufferIndex updateBufferIndex, AnimatableMeshContainer& meshes )
976 for ( AnimatableMeshIter iter = meshes.Begin(); iter != meshes.End(); ++iter )
978 AnimatableMesh& current = **iter;
979 current.UpdateMesh( updateBufferIndex );
983 void UpdateManager::UpdateMaterials( BufferIndex updateBufferIndex, MaterialContainer& materials )
985 for( MaterialIter iter = materials.Begin(), end = materials.End(); iter != end; iter++ )
987 Material* material = *iter;
988 material->PrepareResources( updateBufferIndex, mImpl->resourceManager );
992 void UpdateManager::PrepareMaterials( BufferIndex updateBufferIndex, MaterialContainer& materials )
994 for( MaterialIter iter = materials.Begin(), end = materials.End(); iter != end; iter++ )
996 Material* material = *iter;
997 material->PrepareRender( updateBufferIndex );
1001 unsigned int UpdateManager::Update( float elapsedSeconds, unsigned int lastVSyncTime, unsigned int nextVSyncTime )
1003 PERF_MONITOR_END(PerformanceMonitor::FRAME_RATE); // Mark the End of the last frame
1004 PERF_MONITOR_NEXT_FRAME(); // Prints out performance info for the last frame (if enabled)
1005 PERF_MONITOR_START(PerformanceMonitor::FRAME_RATE); // Mark the start of this current frame
1007 // Measure the time spent in UpdateManager::Update
1008 PERF_MONITOR_START(PerformanceMonitor::UPDATE);
1010 // Update the frame time delta on the render thread.
1011 mImpl->renderManager.SetFrameDeltaTime(elapsedSeconds);
1013 // 1) Clear nodes/resources which were previously discarded
1014 mImpl->discardQueue.Clear( mSceneGraphBuffers.GetUpdateBufferIndex() );
1016 // 2) Grab any loaded resources
1017 bool resourceChanged = mImpl->resourceManager.UpdateCache( mSceneGraphBuffers.GetUpdateBufferIndex() );
1019 // 3) Process Touches & Gestures
1020 mImpl->touchResampler.Update();
1021 const bool gestureUpdated = ProcessGestures( lastVSyncTime, nextVSyncTime );
1023 const bool updateScene = // The scene-graph requires an update if..
1024 mImpl->activeConstraints != 0 || // ..constraints were active in previous frame OR
1025 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
1026 IsAnimationRunning() || // ..at least one animation is running OR
1027 mImpl->dynamicsChanged || // ..there was a change in the dynamics simulation OR
1028 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
1029 resourceChanged || // ..one or more resources were updated/changed OR
1030 gestureUpdated; // ..a gesture property was updated
1032 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
1033 // values if the scene was updated in the previous frame.
1034 if( updateScene || mImpl->previousUpdateScene )
1036 // 4) Reset properties from the previous update
1040 // 5) Process the queued scene messages
1041 mImpl->messageQueue.ProcessMessages();
1043 // 6) Post Process Ids of resources updated by renderer
1044 mImpl->resourceManager.PostProcessResources( mSceneGraphBuffers.GetUpdateBufferIndex() );
1046 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
1047 // renderer lists if the scene was updated in the previous frame.
1048 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
1049 if( updateScene || mImpl->previousUpdateScene )
1052 Animate( elapsedSeconds );
1054 // 8) Apply Constraints
1057 // 9) Update dynamics simulation
1058 mImpl->dynamicsChanged = false;
1059 if( mImpl->dynamicsWorld )
1061 mImpl->dynamicsChanged = mImpl->dynamicsWorld->Update( elapsedSeconds );
1064 // 10) Check Property Notifications
1065 ProcessPropertyNotifications();
1067 // 11) Clear the lists of renderable-attachments from the previous update
1068 ClearRenderables( mImpl->sortedLayers );
1069 ClearRenderables( mImpl->systemLevelSortedLayers );
1071 // 12) Update animated meshes
1072 UpdateMeshes( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->animatableMeshes );
1074 // 13) Update materials. Prepares image resources
1075 UpdateMaterials( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->materials );
1077 // 14) Update node hierarchy and perform sorting / culling.
1078 // This will populate each Layer with a list of renderers which are ready.
1081 // 15) Prepare for the next render
1082 PERF_MONITOR_START(PerformanceMonitor::PREPARE_RENDERABLES);
1083 PrepareMaterials( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->materials );
1084 PrepareRenderables( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->sortedLayers );
1085 PrepareRenderables( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->systemLevelSortedLayers );
1086 PERF_MONITOR_END(PerformanceMonitor::PREPARE_RENDERABLES);
1088 PERF_MONITOR_START(PerformanceMonitor::PROCESS_RENDER_TASKS);
1090 // 16) Process the RenderTasks; this creates the instructions for rendering the next frame.
1091 // reset the update buffer index and make sure there is enough room in the instruction container
1092 mImpl->renderInstructions.ResetAndReserve( mSceneGraphBuffers.GetUpdateBufferIndex(),
1093 mImpl->taskList.GetTasks().Count() + mImpl->systemLevelTaskList.GetTasks().Count() );
1095 if ( NULL != mImpl->root )
1097 ProcessRenderTasks( mSceneGraphBuffers.GetUpdateBufferIndex(),
1098 mImpl->completeStatusManager,
1101 mImpl->sortedLayers,
1102 mImpl->renderSortingHelper,
1103 mImpl->renderInstructions );
1105 // Process the system-level RenderTasks last
1106 if ( NULL != mImpl->systemLevelRoot )
1108 ProcessRenderTasks( mSceneGraphBuffers.GetUpdateBufferIndex(),
1109 mImpl->completeStatusManager,
1110 mImpl->systemLevelTaskList,
1111 *mImpl->systemLevelRoot,
1112 mImpl->systemLevelSortedLayers,
1113 mImpl->renderSortingHelper,
1114 mImpl->renderInstructions );
1117 // if dynamics enabled and active...update matrices for debug drawing
1118 if( mImpl->dynamicsWorld && mImpl->dynamicsChanged )
1120 RenderTask* task(mImpl->taskList.GetTasks()[0]);
1123 mImpl->dynamicsWorld->UpdateMatrices( task->GetProjectionMatrix(mSceneGraphBuffers.GetUpdateBufferIndex()),
1124 task->GetViewMatrix(mSceneGraphBuffers.GetUpdateBufferIndex()) );
1130 // check the countdown and notify
1131 bool doRenderOnceNotify = false;
1132 mImpl->renderTaskWaiting = false;
1133 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
1134 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(), endIter = tasks.End();
1135 endIter != iter; ++iter )
1137 RenderTask& renderTask(*(*iter));
1139 if( renderTask.IsWaitingToRender() )
1141 mImpl->renderTaskWaiting = true; // keep update/render threads alive
1144 if( renderTask.HasRendered() )
1146 doRenderOnceNotify = true;
1150 if( doRenderOnceNotify )
1152 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
1153 mImpl->notificationManager.QueueMessage( NotifyFinishedMessage( *mImpl->renderTaskList ) );
1156 PERF_MONITOR_END(PerformanceMonitor::PROCESS_RENDER_TASKS);
1158 // Macro is undefined in release build.
1159 SNAPSHOT_NODE_LOGGING;
1161 // A ResetProperties() may be required in the next frame
1162 mImpl->previousUpdateScene = updateScene;
1164 // Check whether further updates are required
1165 unsigned int keepUpdating = KeepUpdatingCheck( elapsedSeconds );
1167 #ifdef PERFORMANCE_MONITOR_ENABLED
1168 // Always keep rendering when measuring FPS
1169 keepUpdating |= KeepUpdating::MONITORING_PERFORMANCE;
1172 // The update has finished; swap the double-buffering indices
1173 mSceneGraphBuffers.Swap();
1175 PERF_MONITOR_END(PerformanceMonitor::UPDATE);
1177 return keepUpdating;
1180 unsigned int UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
1182 // Update the duration set via Stage::KeepRendering()
1183 if ( mImpl->keepRenderingSeconds > 0.0f )
1185 mImpl->keepRenderingSeconds -= elapsedSeconds;
1188 unsigned int keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
1190 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
1191 // Keep updating until no messages are received and no animations are running.
1192 // If an animation has just finished, update at least once more for Discard end-actions.
1193 // No need to check for renderQueue as there is always a render after update and if that
1194 // render needs another update it will tell the adaptor to call update again
1196 if ( mImpl->keepRenderingSeconds > 0.0f )
1198 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
1201 if ( !mImpl->messageQueue.WasEmpty() )
1203 keepUpdatingRequest |= KeepUpdating::INCOMING_MESSAGES;
1206 if ( IsAnimationRunning() ||
1207 mImpl->animationFinishedDuringUpdate )
1209 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
1212 if ( mImpl->dynamicsChanged )
1214 keepUpdatingRequest |= KeepUpdating::DYNAMICS_CHANGED;
1217 if ( mImpl->renderTaskWaiting )
1219 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
1222 return keepUpdatingRequest;
1225 void UpdateManager::SetBackgroundColor( const Vector4& color )
1227 typedef MessageValue1< RenderManager, Vector4 > DerivedType;
1229 // Reserve some memory inside the render queue
1230 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1232 // Construct message in the render queue memory; note that delete should not be called on the return value
1233 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
1236 void UpdateManager::SetDefaultSurfaceRect( const Rect<int>& rect )
1238 typedef MessageValue1< RenderManager, Rect<int> > DerivedType;
1240 // Reserve some memory inside the render queue
1241 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1243 // Construct message in the render queue memory; note that delete should not be called on the return value
1244 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1247 void UpdateManager::KeepRendering( float durationSeconds )
1249 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1252 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, bool systemLevel )
1256 // just copy the vector of pointers
1257 mImpl->sortedLayers = layers;
1261 mImpl->systemLevelSortedLayers = layers;
1265 void UpdateManager::InitializeDynamicsWorld( DynamicsWorld* dynamicsWorld, Integration::DynamicsWorldSettings* worldSettings, Shader* debugShader )
1267 dynamicsWorld->Initialize( mImpl->sceneController, worldSettings, debugShader, &mSceneGraphBuffers );
1268 mImpl->dynamicsWorld = dynamicsWorld;
1270 typedef MessageValue1< RenderManager, DynamicsDebugRenderer* > DerivedType;
1272 // Reserve some memory inside the render queue
1273 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1275 // Construct message in the render queue memory; note that delete should not be called on the return value
1276 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::InitializeDynamicsDebugRenderer, &dynamicsWorld->GetDebugRenderer() );
1279 void UpdateManager::TerminateDynamicsWorld()
1281 mImpl->dynamicsWorld.Reset();
1284 } // namespace SceneGraph
1286 } // namespace Internal