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 ) );
589 materials.Erase(iter);
593 // Should not reach here
594 DALI_ASSERT_DEBUG(false);
597 void UpdateManager::AddShader( Shader* shader )
599 DALI_ASSERT_DEBUG( NULL != shader );
601 if( mImpl->shaders.Count() == 0 )
603 // the first added shader becomes our default shader
604 // Construct message in the render queue memory; note that delete should not be called on the return value
605 typedef MessageValue1< RenderManager, Shader* > DerivedType;
607 // Reserve some memory inside the render queue
608 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
610 // Construct message in the render queue memory; note that delete should not be called on the return value
611 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultShader, shader );
614 mImpl->shaders.PushBack( shader );
616 // Allows the shader to dispatch texture requests to the cache
617 shader->Initialize( mImpl->renderQueue, mImpl->sceneController->GetTextureCache() );
620 void UpdateManager::RemoveShader( Shader* shader )
622 DALI_ASSERT_DEBUG(shader != NULL);
624 ShaderContainer& shaders = mImpl->shaders;
626 // Find the shader and destroy it
627 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
629 Shader& current = **iter;
630 if ( ¤t == shader )
632 // Transfer ownership to the discard queue
633 // This keeps the shader alive, until the render-thread has finished with it
634 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), shaders.Release( iter ) );
639 // Should not reach here
640 DALI_ASSERT_DEBUG(false);
643 void UpdateManager::SetShaderProgram( Shader* shader, GeometryType geometryType, ShaderSubTypes subType, ResourceId resourceId, size_t shaderHash, bool modifiesGeometry )
645 DALI_LOG_TRACE_METHOD_FMT(Debug::Filter::gShader, " - (geometryType:%d subType:%d id:%d hash:%d)\n", geometryType, subType, resourceId, shaderHash);
647 DALI_ASSERT_ALWAYS( NULL != shader && "shader is uninitialized" );
649 Integration::ShaderDataPtr shaderData( mImpl->resourceManager.GetShaderData(resourceId) );
652 shaderData->SetHashValue( shaderHash );
653 shaderData->SetResourceId( resourceId );
655 typedef MessageValue6< Shader, GeometryType, Internal::ShaderSubTypes, Integration::ResourceId, Integration::ShaderDataPtr, ProgramCache*, bool> DerivedType;
657 // Reserve some memory inside the render queue
658 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
660 // Construct message in the render queue memory; note that delete should not be called on the return value
661 new (slot) DerivedType( shader, &Shader::SetProgram, geometryType, subType, resourceId, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
665 RenderTaskList* UpdateManager::GetRenderTaskList( bool systemLevel )
669 // copy the list, this is only likely to happen once in application life cycle
670 return &(mImpl->taskList);
674 // copy the list, this is only likely to happen once in application life cycle
675 return &(mImpl->systemLevelTaskList);
679 void UpdateManager::AddGesture( PanGesture* gesture )
681 DALI_ASSERT_DEBUG( NULL != gesture );
683 mImpl->gestures.PushBack( gesture );
686 void UpdateManager::RemoveGesture( PanGesture* gesture )
688 DALI_ASSERT_DEBUG( gesture != NULL );
690 GestureContainer& gestures = mImpl->gestures;
692 // Find the gesture and destroy it
693 for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
695 PanGesture& current = **iter;
696 if ( ¤t == gesture )
698 mImpl->gestures.Erase( iter );
702 // Should not reach here
703 DALI_ASSERT_DEBUG(false);
706 void UpdateManager::ResetNodeProperty( Node& node )
708 node.ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
711 void UpdateManager::ResetProperties()
713 PERF_MONITOR_START(PerformanceMonitor::RESET_PROPERTIES);
715 // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
716 mImpl->animationFinishedDuringUpdate = false;
718 // Animated properties have to be reset to their original value each frame
720 // Reset node properties
723 ResetNodeProperty( *mImpl->root );
726 if ( mImpl->systemLevelRoot )
728 ResetNodeProperty( *mImpl->systemLevelRoot );
731 // Reset the Connected Nodes
732 const std::set<Node*>::iterator endIter = mImpl->connectedNodes.end();
733 for( std::set<Node*>::iterator iter = mImpl->connectedNodes.begin(); endIter != iter; ++iter )
735 ResetNodeProperty( **iter );
738 // If a Node is disconnected, it may still be "active" (requires a reset in next frame)
739 for( std::set<Node*>::iterator iter = mImpl->activeDisconnectedNodes.begin(); mImpl->activeDisconnectedNodes.end() != iter; iter = mImpl->activeDisconnectedNodes.begin() )
742 node->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
743 node->SetActive( false );
745 // Move everything from activeDisconnectedNodes to disconnectedNodes (no need to reset again)
746 mImpl->activeDisconnectedNodes.erase( iter );
747 mImpl->disconnectedNodes.insert( node );
750 // Reset system-level render-task list properties to base values
751 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
753 for (RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
755 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
758 // Reset render-task list properties to base values.
759 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
761 for (RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
763 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
766 // Reset custom object properties to base values
767 for (OwnerContainer<PropertyOwner*>::Iterator iter = mImpl->customObjects.Begin(); iter != mImpl->customObjects.End(); ++iter)
769 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
772 // Reset animatable material properties to base values
773 for (MaterialIter iter = mImpl->materials.Begin(); iter != mImpl->materials.End(); ++iter)
775 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
778 // Reset animatable geometry properties to base values
779 for (GeometryIter iter = mImpl->geometries.Begin(); iter != mImpl->geometries.End(); ++iter)
781 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
784 // Reset animatable shader properties to base values
785 for (ShaderIter iter = mImpl->shaders.Begin(); iter != mImpl->shaders.End(); ++iter)
787 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
790 PERF_MONITOR_END(PerformanceMonitor::RESET_PROPERTIES);
793 bool UpdateManager::ProcessGestures( unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds )
795 bool gestureUpdated( false );
797 // constrain gestures... (in construction order)
798 GestureContainer& gestures = mImpl->gestures;
800 for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
802 PanGesture& gesture = **iter;
803 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
804 gestureUpdated |= gesture.UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
807 return gestureUpdated;
810 void UpdateManager::Animate( float elapsedSeconds )
812 PERF_MONITOR_START(PerformanceMonitor::ANIMATE_NODES);
814 AnimationContainer &animations = mImpl->animations;
815 AnimationIter iter = animations.Begin();
816 while ( iter != animations.End() )
818 Animation* animation = *iter;
819 bool finished = animation->Update(mSceneGraphBuffers.GetUpdateBufferIndex(), elapsedSeconds);
821 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
823 // Remove animations that had been destroyed but were still waiting for an update
824 if (animation->GetState() == Animation::Destroyed)
826 iter = animations.Erase(iter);
834 if ( mImpl->animationFinishedDuringUpdate )
836 // The application should be notified by NotificationManager, in another thread
837 mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationFinishedNotifier );
840 PERF_MONITOR_END(PerformanceMonitor::ANIMATE_NODES);
843 void UpdateManager::ApplyConstraints()
845 PERF_MONITOR_START(PerformanceMonitor::APPLY_CONSTRAINTS);
847 mImpl->activeConstraints = 0;
849 // constrain custom objects... (in construction order)
850 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
852 const OwnerContainer< PropertyOwner* >::Iterator endIter = customObjects.End();
853 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); endIter != iter; ++iter )
855 PropertyOwner& object = **iter;
856 mImpl->activeConstraints += ConstrainPropertyOwner( object, mSceneGraphBuffers.GetUpdateBufferIndex() );
859 // constrain nodes... (in Depth First traversal order)
862 mImpl->activeConstraints += ConstrainNodes( *(mImpl->root), mSceneGraphBuffers.GetUpdateBufferIndex() );
865 if ( mImpl->systemLevelRoot )
867 mImpl->activeConstraints += ConstrainNodes( *(mImpl->systemLevelRoot), mSceneGraphBuffers.GetUpdateBufferIndex() );
870 // constrain other property-owners after nodes as they are more likely to depend on a node's
871 // current frame property than vice versa. They tend to be final constraints (no further
872 // constraints depend on their properties)
873 // e.g. ShaderEffect uniform a function of Actor's position.
874 // Mesh vertex a function of Actor's position or world position.
876 // TODO: refactor this code (and reset nodes) as these are all just lists of property-owners
877 // they can be all processed in a super-list of property-owners.
879 // Constrain system-level render-tasks
880 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
882 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter )
884 RenderTask& task = **iter;
885 mImpl->activeConstraints += ConstrainPropertyOwner( task, mSceneGraphBuffers.GetUpdateBufferIndex() );
888 // Constrain render-tasks
889 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
891 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter )
893 RenderTask& task = **iter;
894 mImpl->activeConstraints += ConstrainPropertyOwner( task, mSceneGraphBuffers.GetUpdateBufferIndex() );
897 // Constrain Materials and geometries
898 MaterialContainer& materials = mImpl->materials;
899 for ( MaterialIter iter = materials.Begin(); iter != materials.End(); ++iter )
901 Material& material = **iter;
902 mImpl->activeConstraints += ConstrainPropertyOwner( material, mSceneGraphBuffers.GetUpdateBufferIndex() );
905 GeometryContainer& geometries = mImpl->geometries;
906 for ( GeometryIter iter = geometries.Begin(); iter != geometries.End(); ++iter )
908 Geometry& geometry = **iter;
909 mImpl->activeConstraints += ConstrainPropertyOwner( geometry, mSceneGraphBuffers.GetUpdateBufferIndex() );
912 // constrain shaders... (in construction order)
913 ShaderContainer& shaders = mImpl->shaders;
915 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
917 Shader& shader = **iter;
918 mImpl->activeConstraints += ConstrainPropertyOwner( shader, mSceneGraphBuffers.GetUpdateBufferIndex() );
921 PERF_MONITOR_END(PerformanceMonitor::APPLY_CONSTRAINTS);
924 void UpdateManager::ProcessPropertyNotifications()
926 PropertyNotificationContainer ¬ifications = mImpl->propertyNotifications;
927 PropertyNotificationIter iter = notifications.Begin();
929 while ( iter != notifications.End() )
931 PropertyNotification* notification = *iter;
933 bool valid = notification->Check( mSceneGraphBuffers.GetUpdateBufferIndex() );
937 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
943 void UpdateManager::UpdateNodes()
945 mImpl->nodeDirtyFlags = NothingFlag;
952 PERF_MONITOR_START( PerformanceMonitor::UPDATE_NODES );
954 // Prepare resources, update shaders, update attachments, for each node
955 // And add the renderers to the sorted layers. Start from root, which is also a layer
956 mImpl->nodeDirtyFlags = UpdateNodesAndAttachments( *( mImpl->root ),
957 mSceneGraphBuffers.GetUpdateBufferIndex(),
958 mImpl->resourceManager,
959 mImpl->renderQueue );
961 if ( mImpl->systemLevelRoot )
963 mImpl->nodeDirtyFlags |= UpdateNodesAndAttachments( *( mImpl->systemLevelRoot ),
964 mSceneGraphBuffers.GetUpdateBufferIndex(),
965 mImpl->resourceManager,
966 mImpl->renderQueue );
969 PERF_MONITOR_END( PerformanceMonitor::UPDATE_NODES );
972 unsigned int UpdateManager::Update( float elapsedSeconds,
973 unsigned int lastVSyncTimeMilliseconds,
974 unsigned int nextVSyncTimeMilliseconds )
976 PERF_MONITOR_END(PerformanceMonitor::FRAME_RATE); // Mark the End of the last frame
977 PERF_MONITOR_NEXT_FRAME(); // Prints out performance info for the last frame (if enabled)
978 PERF_MONITOR_START(PerformanceMonitor::FRAME_RATE); // Mark the start of this current frame
980 // Measure the time spent in UpdateManager::Update
981 PERF_MONITOR_START(PerformanceMonitor::UPDATE);
983 // Update the frame time delta on the render thread.
984 mImpl->renderManager.SetFrameDeltaTime(elapsedSeconds);
986 // 1) Clear nodes/resources which were previously discarded
987 mImpl->discardQueue.Clear( mSceneGraphBuffers.GetUpdateBufferIndex() );
989 // 2) Grab any loaded resources
990 bool resourceChanged = mImpl->resourceManager.UpdateCache( mSceneGraphBuffers.GetUpdateBufferIndex() );
992 // 3) Process Touches & Gestures
993 mImpl->touchResampler.Update();
994 const bool gestureUpdated = ProcessGestures( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
996 const bool updateScene = // The scene-graph requires an update if..
997 mImpl->activeConstraints != 0 || // ..constraints were active in previous frame OR
998 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
999 IsAnimationRunning() || // ..at least one animation is running OR
1000 mImpl->dynamicsChanged || // ..there was a change in the dynamics simulation OR
1001 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
1002 resourceChanged || // ..one or more resources were updated/changed OR
1003 gestureUpdated; // ..a gesture property was updated
1005 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
1006 // values if the scene was updated in the previous frame.
1007 if( updateScene || mImpl->previousUpdateScene )
1009 // 4) Reset properties from the previous update
1013 // 5) Process the queued scene messages
1014 mImpl->messageQueue.ProcessMessages();
1016 // 6) Post Process Ids of resources updated by renderer
1017 mImpl->resourceManager.PostProcessResources( mSceneGraphBuffers.GetUpdateBufferIndex() );
1019 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
1020 // renderer lists if the scene was updated in the previous frame.
1021 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
1022 if( updateScene || mImpl->previousUpdateScene )
1025 Animate( elapsedSeconds );
1027 // 8) Apply Constraints
1030 #ifdef DYNAMICS_SUPPORT
1031 // 9) Update dynamics simulation
1032 mImpl->dynamicsChanged = false;
1033 if( mImpl->dynamicsWorld )
1035 mImpl->dynamicsChanged = mImpl->dynamicsWorld->Update( elapsedSeconds );
1039 // 10) Check Property Notifications
1040 ProcessPropertyNotifications();
1042 // 11) Clear the lists of renderable-attachments from the previous update
1043 ClearRenderables( mImpl->sortedLayers );
1044 ClearRenderables( mImpl->systemLevelSortedLayers );
1046 // 12) Update node hierarchy and perform sorting / culling.
1047 // This will populate each Layer with a list of renderers which are ready.
1050 // 13) Prepare for the next render
1051 PERF_MONITOR_START(PerformanceMonitor::PREPARE_RENDERABLES);
1053 PrepareRenderables( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->sortedLayers );
1054 PrepareRenderables( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->systemLevelSortedLayers );
1055 PERF_MONITOR_END(PerformanceMonitor::PREPARE_RENDERABLES);
1057 PERF_MONITOR_START(PerformanceMonitor::PROCESS_RENDER_TASKS);
1059 // 14) Process the RenderTasks; this creates the instructions for rendering the next frame.
1060 // reset the update buffer index and make sure there is enough room in the instruction container
1061 mImpl->renderInstructions.ResetAndReserve( mSceneGraphBuffers.GetUpdateBufferIndex(),
1062 mImpl->taskList.GetTasks().Count() + mImpl->systemLevelTaskList.GetTasks().Count() );
1064 if ( NULL != mImpl->root )
1066 ProcessRenderTasks( mSceneGraphBuffers.GetUpdateBufferIndex(),
1067 mImpl->completeStatusManager,
1070 mImpl->sortedLayers,
1071 mImpl->renderSortingHelper,
1072 mImpl->renderInstructions );
1074 // Process the system-level RenderTasks last
1075 if ( NULL != mImpl->systemLevelRoot )
1077 ProcessRenderTasks( mSceneGraphBuffers.GetUpdateBufferIndex(),
1078 mImpl->completeStatusManager,
1079 mImpl->systemLevelTaskList,
1080 *mImpl->systemLevelRoot,
1081 mImpl->systemLevelSortedLayers,
1082 mImpl->renderSortingHelper,
1083 mImpl->renderInstructions );
1088 // check the countdown and notify (note, at the moment this is only done for normal tasks, not for systemlevel tasks)
1089 bool doRenderOnceNotify = false;
1090 mImpl->renderTaskWaiting = false;
1091 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
1092 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(), endIter = tasks.End();
1093 endIter != iter; ++iter )
1095 RenderTask& renderTask(*(*iter));
1097 renderTask.UpdateState();
1099 if( renderTask.IsWaitingToRender() &&
1100 renderTask.ReadyToRender(mSceneGraphBuffers.GetUpdateBufferIndex()) /*avoid updating forever when source actor is off-stage*/ )
1102 mImpl->renderTaskWaiting = true; // keep update/render threads alive
1105 if( renderTask.HasRendered() )
1107 doRenderOnceNotify = true;
1111 if( doRenderOnceNotify )
1113 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
1114 mImpl->notificationManager.QueueCompleteNotification( mImpl->taskList.GetCompleteNotificationInterface() );
1117 PERF_MONITOR_END(PerformanceMonitor::PROCESS_RENDER_TASKS);
1119 // Macro is undefined in release build.
1120 SNAPSHOT_NODE_LOGGING;
1122 // A ResetProperties() may be required in the next frame
1123 mImpl->previousUpdateScene = updateScene;
1125 // Check whether further updates are required
1126 unsigned int keepUpdating = KeepUpdatingCheck( elapsedSeconds );
1128 #ifdef PERFORMANCE_MONITOR_ENABLED
1129 // Always keep rendering when measuring FPS
1130 keepUpdating |= KeepUpdating::MONITORING_PERFORMANCE;
1133 // The update has finished; swap the double-buffering indices
1134 mSceneGraphBuffers.Swap();
1136 // tell the update manager that we're done so the queue can be given to event thread
1137 mImpl->notificationManager.UpdateCompleted();
1139 PERF_MONITOR_END(PerformanceMonitor::UPDATE);
1141 return keepUpdating;
1144 unsigned int UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
1146 // Update the duration set via Stage::KeepRendering()
1147 if ( mImpl->keepRenderingSeconds > 0.0f )
1149 mImpl->keepRenderingSeconds -= elapsedSeconds;
1152 unsigned int keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
1154 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
1155 // Keep updating until no messages are received and no animations are running.
1156 // If an animation has just finished, update at least once more for Discard end-actions.
1157 // No need to check for renderQueue as there is always a render after update and if that
1158 // render needs another update it will tell the adaptor to call update again
1160 if ( mImpl->keepRenderingSeconds > 0.0f )
1162 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
1165 if ( !mImpl->messageQueue.WasEmpty() )
1167 keepUpdatingRequest |= KeepUpdating::INCOMING_MESSAGES;
1170 if ( IsAnimationRunning() ||
1171 mImpl->animationFinishedDuringUpdate )
1173 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
1176 if ( mImpl->dynamicsChanged )
1178 keepUpdatingRequest |= KeepUpdating::DYNAMICS_CHANGED;
1181 if ( mImpl->renderTaskWaiting )
1183 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
1186 return keepUpdatingRequest;
1189 void UpdateManager::SetBackgroundColor( const Vector4& color )
1191 typedef MessageValue1< RenderManager, Vector4 > DerivedType;
1193 // Reserve some memory inside the render queue
1194 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1196 // Construct message in the render queue memory; note that delete should not be called on the return value
1197 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
1200 void UpdateManager::SetDefaultSurfaceRect( const Rect<int>& rect )
1202 typedef MessageValue1< RenderManager, Rect<int> > DerivedType;
1204 // Reserve some memory inside the render queue
1205 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1207 // Construct message in the render queue memory; note that delete should not be called on the return value
1208 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1211 void UpdateManager::KeepRendering( float durationSeconds )
1213 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1216 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, bool systemLevel )
1220 // just copy the vector of pointers
1221 mImpl->sortedLayers = layers;
1225 mImpl->systemLevelSortedLayers = layers;
1229 #ifdef DYNAMICS_SUPPORT
1231 void UpdateManager::InitializeDynamicsWorld( SceneGraph::DynamicsWorld* dynamicsWorld, Integration::DynamicsWorldSettings* worldSettings )
1233 dynamicsWorld->Initialize( mImpl->sceneController, worldSettings, &mSceneGraphBuffers );
1234 mImpl->dynamicsWorld = dynamicsWorld;
1237 void UpdateManager::TerminateDynamicsWorld()
1239 mImpl->dynamicsWorld.Reset();
1242 #endif // DYNAMICS_SUPPORT
1244 } // namespace SceneGraph
1246 } // namespace Internal