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>
29 #include <dali/internal/common/core-impl.h>
30 #include <dali/internal/common/owner-container.h>
31 #include <dali/internal/common/message.h>
33 #include <dali/internal/event/common/notification-manager.h>
34 #include <dali/internal/event/common/property-notification-impl.h>
35 #include <dali/internal/event/common/property-notifier.h>
36 #include <dali/internal/event/animation/animation-finished-notifier.h>
37 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
39 #include <dali/internal/update/animation/scene-graph-animator.h>
40 #include <dali/internal/update/animation/scene-graph-animation.h>
41 #include <dali/internal/update/common/discard-queue.h>
42 #include <dali/internal/update/common/double-buffered.h>
43 #include <dali/internal/update/manager/prepare-render-algorithms.h>
44 #include <dali/internal/update/manager/process-render-tasks.h>
45 #include <dali/internal/update/resources/resource-manager.h>
46 #include <dali/internal/update/resources/complete-status-manager.h>
47 #include <dali/internal/update/common/scene-graph-buffers.h>
48 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
49 #include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
50 #include <dali/internal/update/manager/sorted-layers.h>
51 #include <dali/internal/update/manager/update-algorithms.h>
52 #include <dali/internal/update/queue/update-message-queue.h>
53 #include <dali/internal/update/manager/update-manager-debug.h>
54 #include <dali/internal/update/controllers/render-message-dispatcher.h>
55 #include <dali/internal/update/controllers/scene-controller-impl.h>
56 #include <dali/internal/update/gestures/scene-graph-pan-gesture.h>
57 #include <dali/internal/update/modeling/scene-graph-material.h>
58 #include <dali/internal/update/node-attachments/scene-graph-camera-attachment.h>
59 #include <dali/internal/update/nodes/node.h>
60 #include <dali/internal/update/nodes/scene-graph-layer.h>
61 #include <dali/internal/update/touch/touch-resampler.h>
63 #include <dali/internal/render/common/render-instruction-container.h>
64 #include <dali/internal/render/common/render-manager.h>
65 #include <dali/internal/render/queue/render-queue.h>
66 #include <dali/internal/render/common/performance-monitor.h>
67 #include <dali/internal/render/gl-resources/texture-cache.h>
68 #include <dali/internal/render/renderers/render-material.h>
69 #include <dali/internal/render/shaders/shader.h>
71 #ifdef DYNAMICS_SUPPORT
72 #include <dali/integration-api/dynamics/dynamics-world-settings.h>
73 #include <dali/internal/update/dynamics/scene-graph-dynamics-world.h>
76 // Un-comment to enable node tree debug logging
77 //#define NODE_TREE_LOGGING 1
79 #if ( defined( DEBUG_ENABLED ) && defined( NODE_TREE_LOGGING ) )
80 #define SNAPSHOT_NODE_LOGGING \
81 const int FRAME_COUNT_TRIGGER = 16;\
82 if( mImpl->frameCounter >= FRAME_COUNT_TRIGGER )\
84 if ( NULL != mImpl->root )\
86 mImpl->frameCounter = 0;\
87 PrintNodeTree( *mImpl->root, mSceneGraphBuffers.GetUpdateBufferIndex(), "" );\
90 mImpl->frameCounter++;
92 #define SNAPSHOT_NODE_LOGGING
95 #if defined(DEBUG_ENABLED)
96 extern Debug::Filter* gRenderTaskLogFilter;
100 using namespace Dali::Integration;
101 using Dali::Internal::Update::MessageQueue;
115 const int DEFAULT_CAMERA_INDEX = -1;
117 void DestroyNodeSet( std::set<Node*>& nodeSet )
119 for( std::set<Node*>::iterator iter = nodeSet.begin(); iter != nodeSet.end(); ++iter )
123 // Call Node::OnDestroy as each node is destroyed
133 typedef OwnerContainer< Shader* > ShaderContainer;
134 typedef ShaderContainer::Iterator ShaderIter;
135 typedef ShaderContainer::ConstIterator ShaderConstIter;
137 typedef AnimatableMeshContainer::Iterator AnimatableMeshIter;
138 typedef AnimatableMeshContainer::ConstIterator AnimatableMeshConstIter;
139 typedef MaterialContainer::Iterator MaterialIter;
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 AnimationFinishedNotifier& 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 defaultShader( NULL ),
183 messageQueue( renderController, sceneGraphBuffers ),
184 dynamicsChanged( false ),
185 keepRenderingSeconds( 0.0f ),
186 animationFinishedDuringUpdate( false ),
187 activeConstraints( 0 ),
188 nodeDirtyFlags( TransformFlag ), // set to TransformFlag to ensure full update the first time through Update()
189 previousUpdateScene( false ),
191 renderSortingHelper(),
192 renderTaskList( NULL ),
193 renderTaskWaiting( false )
195 sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue, textureCache, completeStatusManager );
200 // Disconnect render tasks from nodes, before destroying the nodes
201 RenderTaskList::RenderTaskContainer& tasks = taskList.GetTasks();
202 for (RenderTaskList::RenderTaskContainer::Iterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
204 (*iter)->SetSourceNode( NULL );
206 // ..repeat for system level RenderTasks
207 RenderTaskList::RenderTaskContainer& systemLevelTasks = systemLevelTaskList.GetTasks();
208 for (RenderTaskList::RenderTaskContainer::Iterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
210 (*iter)->SetSourceNode( NULL );
213 // UpdateManager owns the Nodes
214 DestroyNodeSet( activeDisconnectedNodes );
215 DestroyNodeSet( connectedNodes );
216 DestroyNodeSet( disconnectedNodes );
218 // If there is root, reset it, otherwise do nothing as rendering was never started
227 if( systemLevelRoot )
229 systemLevelRoot->OnDestroy();
231 delete systemLevelRoot;
232 systemLevelRoot = NULL;
235 sceneController->GetTextureCache().SetBufferIndices(NULL); // TODO - Remove
236 delete sceneController;
239 SceneGraphBuffers sceneGraphBuffers; ///< Used to keep track of which buffers are being written or read
240 RenderMessageDispatcher renderMessageDispatcher; ///< Used for passing messages to the render-thread
241 NotificationManager& notificationManager; ///< Queues notification messages for the event-thread.
242 AnimationFinishedNotifier& animationFinishedNotifier; ///< Provides notification to applications when animations are finished.
243 PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
244 ResourceManager& resourceManager; ///< resource manager
245 DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
246 RenderController& renderController; ///< render controller
247 SceneControllerImpl* sceneController; ///< scene controller
248 RenderManager& renderManager; ///< This is responsible for rendering the results of each "update"
249 RenderQueue& renderQueue; ///< Used to queue messages for the next render
250 RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions
251 CompleteStatusManager completeStatusManager; ///< Complete Status Manager
252 TouchResampler& touchResampler; ///< Used to resample touch events on every update.
254 Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
256 RenderTaskList taskList; ///< The list of scene graph render-tasks
257 RenderTaskList systemLevelTaskList; ///< Separate render-tasks for system-level content
259 Layer* root; ///< The root node (root is a layer)
260 Layer* systemLevelRoot; ///< A separate root-node for system-level content
261 std::set< Node* > activeDisconnectedNodes; ///< A container of new or modified nodes (without parent) owned by UpdateManager
262 std::set< Node* > connectedNodes; ///< A container of connected (with parent) nodes owned by UpdateManager
263 std::set< Node* > disconnectedNodes; ///< A container of inactive disconnected nodes (without parent) owned by UpdateManager
265 SortedLayerPointers sortedLayers; ///< A container of Layer pointers sorted by depth
266 SortedLayerPointers systemLevelSortedLayers; ///< A separate container of system-level Layers
268 OwnerContainer< PropertyOwner* > customObjects; ///< A container of owned objects (with custom properties)
270 AnimationContainer animations; ///< A container of owned animations
271 PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
273 Shader* defaultShader; ///< The default shader; owned by ShaderContainer
274 ShaderContainer shaders; ///< A container of owned shaders
275 AnimatableMeshContainer animatableMeshes; ///< A container of owned animatable meshes
276 MaterialContainer materials; ///< A container of owned materials
278 MessageQueue messageQueue; ///< The messages queued from the event-thread
280 #ifdef DYNAMICS_SUPPORT
281 OwnerPointer<DynamicsWorld> dynamicsWorld; ///< Wrapper for dynamics simulation
283 bool dynamicsChanged; ///< This is set to true if an object is changed in the dynamics simulation tick
285 float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
286 bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
288 unsigned int activeConstraints; ///< number of active constraints from previous frame
289 int nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
290 bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
292 int frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
293 RendererSortingHelper renderSortingHelper; ///< helper used to sort transparent renderers
295 Internal::RenderTaskList* renderTaskList; ///< Stores a pointer to the internal implementation to the render task list.
296 GestureContainer gestures; ///< A container of owned gesture detectors
297 bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
300 UpdateManager::UpdateManager( NotificationManager& notificationManager,
301 GlSyncAbstraction& glSyncAbstraction,
302 AnimationFinishedNotifier& animationFinishedNotifier,
303 PropertyNotifier& propertyNotifier,
304 ResourceManager& resourceManager,
305 DiscardQueue& discardQueue,
306 RenderController& controller,
307 RenderManager& renderManager,
308 RenderQueue& renderQueue,
309 TextureCache& textureCache,
310 TouchResampler& touchResampler )
313 mImpl = new Impl( notificationManager,
315 animationFinishedNotifier,
324 mSceneGraphBuffers );
326 textureCache.SetBufferIndices( &mSceneGraphBuffers );
329 UpdateManager::~UpdateManager()
334 void UpdateManager::SetRenderTaskList( Internal::RenderTaskList* renderTaskList )
336 mImpl->renderTaskList = renderTaskList;
339 EventToUpdate& UpdateManager::GetEventToUpdate()
341 return mImpl->messageQueue;
344 void UpdateManager::InstallRoot( SceneGraph::Layer* layer, bool systemLevel )
346 DALI_ASSERT_DEBUG( layer->IsLayer() );
347 DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
351 DALI_ASSERT_DEBUG( mImpl->root == NULL && "Root Node already installed" );
356 DALI_ASSERT_DEBUG( mImpl->systemLevelRoot == NULL && "System-level Root Node already installed" );
357 mImpl->systemLevelRoot = layer;
360 layer->SetRoot(true);
363 void UpdateManager::AddNode( Node* node )
365 DALI_ASSERT_ALWAYS( NULL != node );
366 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
368 mImpl->activeDisconnectedNodes.insert( node ); // Takes ownership of node
371 void UpdateManager::ConnectNode( Node* parent, Node* node )
373 DALI_ASSERT_ALWAYS( NULL != parent );
374 DALI_ASSERT_ALWAYS( NULL != node );
375 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
377 // Move from active/disconnectedNodes to connectedNodes
378 std::set<Node*>::size_type removed = mImpl->activeDisconnectedNodes.erase( node );
381 removed = mImpl->disconnectedNodes.erase( node );
382 DALI_ASSERT_ALWAYS( removed );
384 mImpl->connectedNodes.insert( node );
386 node->SetActive( true );
388 parent->ConnectChild( node );
391 void UpdateManager::DisconnectNode( Node* node )
393 Node* parent = node->GetParent();
394 DALI_ASSERT_ALWAYS( NULL != parent );
395 parent->SetDirtyFlag( ChildDeletedFlag ); // make parent dirty so that render items dont get reused
397 // Move from connectedNodes to activeDisconnectedNodes (reset properties next frame)
398 parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node, mImpl->connectedNodes, mImpl->activeDisconnectedNodes );
401 void UpdateManager::SetNodeActive( Node* node )
403 DALI_ASSERT_ALWAYS( NULL != node );
404 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
406 // Move from disconnectedNodes to activeDisconnectedNodes (reset properties next frame)
407 std::set<Node*>::size_type removed = mImpl->disconnectedNodes.erase( node );
408 DALI_ASSERT_ALWAYS( removed );
409 mImpl->activeDisconnectedNodes.insert( node );
411 node->SetActive( true );
414 void UpdateManager::DestroyNode( Node* node )
416 DALI_ASSERT_ALWAYS( NULL != node );
417 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
419 // Transfer ownership from new/disconnectedNodes to the discard queue
420 // This keeps the nodes alive, until the render-thread has finished with them
421 std::set<Node*>::size_type removed = mImpl->activeDisconnectedNodes.erase( node );
424 removed = mImpl->disconnectedNodes.erase( node );
425 DALI_ASSERT_ALWAYS( removed );
427 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
429 // Notify the Node about impending destruction
433 void UpdateManager::AttachToNode( Node* node, NodeAttachment* attachment )
435 DALI_ASSERT_DEBUG( node != NULL );
436 DALI_ASSERT_DEBUG( attachment != NULL );
438 // attach node to attachment first so that parent is known by the time attachment is connected
439 node->Attach( *attachment ); // node takes ownership
440 attachment->ConnectToSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
443 void UpdateManager::AddObject( PropertyOwner* object )
445 DALI_ASSERT_DEBUG( NULL != object );
447 mImpl->customObjects.PushBack( object );
450 void UpdateManager::RemoveObject( PropertyOwner* object )
452 DALI_ASSERT_DEBUG( NULL != object );
454 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
456 // Find the object and destroy it
457 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); iter != customObjects.End(); ++iter )
459 PropertyOwner* current = *iter;
460 if ( current == object )
462 customObjects.Erase( iter );
467 // Should not reach here
468 DALI_ASSERT_DEBUG(false);
471 void UpdateManager::AddAnimation( Animation* animation )
473 mImpl->animations.PushBack( animation );
476 void UpdateManager::StopAnimation( Animation* animation )
478 DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
480 bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
482 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
485 void UpdateManager::RemoveAnimation( Animation* animation )
487 DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
489 animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
491 DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
494 bool UpdateManager::IsAnimationRunning() const
496 bool isRunning(false);
497 AnimationContainer& animations = mImpl->animations;
499 // Find any animation that isn't stopped or paused
501 const AnimationIter endIter = animations.End();
502 for ( AnimationIter iter = animations.Begin(); !isRunning && iter != endIter; ++iter )
504 const Animation::State state = (*iter)->GetState();
506 if (state != Animation::Stopped &&
507 state != Animation::Paused)
516 void UpdateManager::AddPropertyNotification( PropertyNotification* propertyNotification )
518 mImpl->propertyNotifications.PushBack( propertyNotification );
521 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
523 PropertyNotificationContainer &propertyNotifications = mImpl->propertyNotifications;
524 PropertyNotificationIter iter = propertyNotifications.Begin();
526 while ( iter != propertyNotifications.End() )
528 if( *iter == propertyNotification )
530 propertyNotifications.Erase(iter);
537 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
539 DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
540 propertyNotification->SetNotifyMode( notifyMode );
543 Shader* UpdateManager::GetDefaultShader()
545 return mImpl->defaultShader;
548 void UpdateManager::AddShader( Shader* shader )
550 DALI_ASSERT_DEBUG( NULL != shader );
552 // Note: The first shader added becomes the default shader
553 if( NULL == mImpl->defaultShader )
555 mImpl->defaultShader = shader;
558 mImpl->shaders.PushBack( shader );
560 // Allows the shader to dispatch texture requests to the cache and "save shader"
561 // requests to the resource manager from the render thread.
562 shader->Initialize( mImpl->renderManager, mImpl->renderQueue, mImpl->sceneController->GetTextureCache() );
565 void UpdateManager::RemoveShader(Shader* shader)
567 DALI_ASSERT_DEBUG(shader != NULL);
569 ShaderContainer& shaders = mImpl->shaders;
571 // Find the shader and destroy it
572 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
574 Shader& current = **iter;
575 if ( ¤t == shader )
577 // Transfer ownership to the discard queue
578 // This keeps the shader alive, until the render-thread has finished with it
579 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), shaders.Release( iter ) );
584 // Should not reach here
585 DALI_ASSERT_DEBUG(false);
588 void UpdateManager::SetShaderProgram( Shader* shader, GeometryType geometryType, ShaderSubTypes subType, ResourceId resourceId, size_t shaderHash )
590 DALI_LOG_TRACE_METHOD_FMT(Debug::Filter::gShader, " - (geometryType:%d subType:%d id:%d hash:%d)\n", geometryType, subType, resourceId, shaderHash);
592 DALI_ASSERT_ALWAYS( NULL != shader && "shader is uninitialized" );
594 Integration::ShaderDataPtr shaderData( mImpl->resourceManager.GetShaderData(resourceId) );
595 shaderData->SetHashValue( shaderHash );
599 // This is done in the render thread, to allow GL program compilation
600 // Will trigger a NotifySaveRequest back to updateManager to forward onto ResourceClient
601 typedef MessageValue5< Shader, GeometryType, Internal::ShaderSubTypes, Integration::ResourceId, Integration::ShaderDataPtr, Context* > DerivedType;
603 // Reserve some memory inside the render queue
604 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
606 // Construct message in the render queue memory; note that delete should not be called on the return value
607 new (slot) DerivedType( shader, &Shader::SetProgram, geometryType, subType, resourceId, shaderData, &(mImpl->renderManager.GetContext()) );
611 void UpdateManager::AddAnimatableMesh( AnimatableMesh* animatableMesh )
613 mImpl->animatableMeshes.PushBack(animatableMesh);
616 void UpdateManager::RemoveAnimatableMesh( AnimatableMesh* animatableMesh )
618 DALI_ASSERT_DEBUG(animatableMesh != NULL);
620 AnimatableMeshContainer& animatableMeshes = mImpl->animatableMeshes;
622 // Find the animatableMesh and destroy it
623 for ( AnimatableMeshIter iter = animatableMeshes.Begin(); iter != animatableMeshes.End(); ++iter )
625 AnimatableMesh& current = **iter;
626 if ( ¤t == animatableMesh )
628 animatableMeshes.Erase( iter );
634 void UpdateManager::AddMaterial( Material* material )
636 DALI_ASSERT_DEBUG( NULL != material );
638 mImpl->materials.PushBack( material );
639 RenderMaterial* renderMaterial = new RenderMaterial();
641 typedef MessageValue1< RenderManager, RenderMaterial* > DerivedType;
643 // Reserve some memory inside the render queue
644 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
646 // Construct message in the render queue memory; note that delete should not be called on the return value
647 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddRenderMaterial, renderMaterial );
649 material->SetRenderMaterial( renderMaterial );
650 material->OnStageConnection( *mImpl->sceneController );
653 void UpdateManager::RemoveMaterial( Material* theMaterial )
655 // Caused by last reference to material being released (e.g. app or internal mesh-actor)
657 for ( MaterialIter iter=mImpl->materials.Begin(), end=mImpl->materials.End() ; iter != end ; ++iter )
659 const Material* aMaterial = *iter;
661 if( aMaterial == theMaterial )
663 typedef MessageValue1< RenderManager, RenderMaterial* > DerivedType;
665 // Reserve some memory inside the render queue
666 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
668 // Construct message in the render queue memory; note that delete should not be called on the return value
669 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveRenderMaterial, theMaterial->GetRenderMaterial() );
671 mImpl->materials.Erase( iter );
677 RenderTaskList* UpdateManager::GetRenderTaskList( bool systemLevel )
681 // copy the list, this is only likely to happen once in application life cycle
682 return &(mImpl->taskList);
686 // copy the list, this is only likely to happen once in application life cycle
687 return &(mImpl->systemLevelTaskList);
691 void UpdateManager::AddGesture( PanGesture* gesture )
693 DALI_ASSERT_DEBUG( NULL != gesture );
695 mImpl->gestures.PushBack( gesture );
698 void UpdateManager::RemoveGesture( PanGesture* gesture )
700 DALI_ASSERT_DEBUG( gesture != NULL );
702 GestureContainer& gestures = mImpl->gestures;
704 // Find the gesture and destroy it
705 for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
707 PanGesture& current = **iter;
708 if ( ¤t == gesture )
710 mImpl->gestures.Erase( iter );
714 // Should not reach here
715 DALI_ASSERT_DEBUG(false);
718 void UpdateManager::ResetNodeProperty( Node& node )
720 node.ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
723 void UpdateManager::ResetProperties()
725 PERF_MONITOR_START(PerformanceMonitor::RESET_PROPERTIES);
727 // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
728 mImpl->animationFinishedDuringUpdate = false;
730 // Animated properties have to be reset to their original value each frame
732 // Reset node properties
735 ResetNodeProperty( *mImpl->root );
738 if ( mImpl->systemLevelRoot )
740 ResetNodeProperty( *mImpl->systemLevelRoot );
743 // Reset the Connected Nodes
744 const std::set<Node*>::iterator endIter = mImpl->connectedNodes.end();
745 for( std::set<Node*>::iterator iter = mImpl->connectedNodes.begin(); endIter != iter; ++iter )
747 ResetNodeProperty( **iter );
750 // If a Node is disconnected, it may still be "active" (requires a reset in next frame)
751 for( std::set<Node*>::iterator iter = mImpl->activeDisconnectedNodes.begin(); mImpl->activeDisconnectedNodes.end() != iter; iter = mImpl->activeDisconnectedNodes.begin() )
754 node->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
755 node->SetActive( false );
757 // Move everything from activeDisconnectedNodes to disconnectedNodes (no need to reset again)
758 mImpl->activeDisconnectedNodes.erase( iter );
759 mImpl->disconnectedNodes.insert( node );
762 // Reset system-level render-task list properties to base values
763 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
765 for (RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
767 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
770 // Reset render-task list properties to base values.
771 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
773 for (RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
775 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
778 // Reset custom object properties to base values
779 for (OwnerContainer<PropertyOwner*>::Iterator iter = mImpl->customObjects.Begin(); iter != mImpl->customObjects.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 // Reset animatable mesh properties to base values
791 for ( AnimatableMeshIter iter = mImpl->animatableMeshes.Begin(); iter != mImpl->animatableMeshes.End(); ++iter )
793 (*iter)->ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
796 PERF_MONITOR_END(PerformanceMonitor::RESET_PROPERTIES);
799 bool UpdateManager::ProcessGestures( unsigned int lastVSyncTime, unsigned int nextVSyncTime )
801 bool gestureUpdated( false );
803 // constrain gestures... (in construction order)
804 GestureContainer& gestures = mImpl->gestures;
806 for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
808 PanGesture& gesture = **iter;
809 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
810 gestureUpdated |= gesture.UpdateProperties( lastVSyncTime, nextVSyncTime );
813 return gestureUpdated;
816 void UpdateManager::Animate( float elapsedSeconds )
818 PERF_MONITOR_START(PerformanceMonitor::ANIMATE_NODES);
820 AnimationContainer &animations = mImpl->animations;
821 AnimationIter iter = animations.Begin();
822 while ( iter != animations.End() )
824 Animation* animation = *iter;
825 bool finished = animation->Update(mSceneGraphBuffers.GetUpdateBufferIndex(), elapsedSeconds);
827 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
829 // Remove animations that had been destroyed but were still waiting for an update
830 if (animation->GetState() == Animation::Destroyed)
832 iter = animations.Erase(iter);
840 if ( mImpl->animationFinishedDuringUpdate )
842 // The application should be notified by NotificationManager, in another thread
843 mImpl->notificationManager.QueueMessage( AnimationFinishedMessage( mImpl->animationFinishedNotifier ) );
846 PERF_MONITOR_END(PerformanceMonitor::ANIMATE_NODES);
849 void UpdateManager::ApplyConstraints()
851 PERF_MONITOR_START(PerformanceMonitor::APPLY_CONSTRAINTS);
853 mImpl->activeConstraints = 0;
855 // constrain custom objects... (in construction order)
856 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
858 const OwnerContainer< PropertyOwner* >::Iterator endIter = customObjects.End();
859 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); endIter != iter; ++iter )
861 PropertyOwner& object = **iter;
862 mImpl->activeConstraints += ConstrainPropertyOwner( object, mSceneGraphBuffers.GetUpdateBufferIndex() );
865 // constrain nodes... (in Depth First traversal order)
868 mImpl->activeConstraints += ConstrainNodes( *(mImpl->root), mSceneGraphBuffers.GetUpdateBufferIndex() );
871 if ( mImpl->systemLevelRoot )
873 mImpl->activeConstraints += ConstrainNodes( *(mImpl->systemLevelRoot), mSceneGraphBuffers.GetUpdateBufferIndex() );
876 // constrain other property-owners after nodes as they are more likely to depend on a node's
877 // current frame property than vice versa. They tend to be final constraints (no further
878 // constraints depend on their properties)
879 // e.g. ShaderEffect uniform a function of Actor's position.
880 // Mesh vertex a function of Actor's position or world position.
882 // TODO: refactor this code (and reset nodes) as these are all just lists of property-owners
883 // they can be all processed in a super-list of property-owners.
885 // Constrain system-level render-tasks
886 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
888 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter )
890 RenderTask& task = **iter;
891 mImpl->activeConstraints += ConstrainPropertyOwner( task, mSceneGraphBuffers.GetUpdateBufferIndex() );
894 // Constrain render-tasks
895 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
897 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter )
899 RenderTask& task = **iter;
900 mImpl->activeConstraints += ConstrainPropertyOwner( task, mSceneGraphBuffers.GetUpdateBufferIndex() );
903 // constrain meshes (in construction order)
904 AnimatableMeshContainer& meshes = mImpl->animatableMeshes;
905 for ( AnimatableMeshIter iter = meshes.Begin(); iter != meshes.End(); ++iter )
907 AnimatableMesh& mesh = **iter;
908 mImpl->activeConstraints += ConstrainPropertyOwner( mesh, 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 Shader* defaultShader = GetDefaultShader();
955 if ( NULL != defaultShader )
957 // Prepare resources, update shaders, update attachments, for each node
958 // And add the renderers to the sorted layers. Start from root, which is also a layer
959 mImpl->nodeDirtyFlags = UpdateNodesAndAttachments( *( mImpl->root ),
960 mSceneGraphBuffers.GetUpdateBufferIndex(),
961 mImpl->resourceManager,
965 if ( mImpl->systemLevelRoot )
967 mImpl->nodeDirtyFlags |= UpdateNodesAndAttachments( *( mImpl->systemLevelRoot ),
968 mSceneGraphBuffers.GetUpdateBufferIndex(),
969 mImpl->resourceManager,
975 PERF_MONITOR_END( PerformanceMonitor::UPDATE_NODES );
978 void UpdateManager::UpdateMeshes( BufferIndex updateBufferIndex, AnimatableMeshContainer& meshes )
980 for ( AnimatableMeshIter iter = meshes.Begin(); iter != meshes.End(); ++iter )
982 AnimatableMesh& current = **iter;
983 current.UpdateMesh( updateBufferIndex );
987 void UpdateManager::UpdateMaterials( BufferIndex updateBufferIndex, MaterialContainer& materials )
989 for( MaterialIter iter = materials.Begin(), end = materials.End(); iter != end; iter++ )
991 Material* material = *iter;
992 material->PrepareResources( updateBufferIndex, mImpl->resourceManager );
996 void UpdateManager::PrepareMaterials( BufferIndex updateBufferIndex, MaterialContainer& materials )
998 for( MaterialIter iter = materials.Begin(), end = materials.End(); iter != end; iter++ )
1000 Material* material = *iter;
1001 material->PrepareRender( updateBufferIndex );
1005 unsigned int UpdateManager::Update( float elapsedSeconds, unsigned int lastVSyncTime, unsigned int nextVSyncTime )
1007 PERF_MONITOR_END(PerformanceMonitor::FRAME_RATE); // Mark the End of the last frame
1008 PERF_MONITOR_NEXT_FRAME(); // Prints out performance info for the last frame (if enabled)
1009 PERF_MONITOR_START(PerformanceMonitor::FRAME_RATE); // Mark the start of this current frame
1011 // Measure the time spent in UpdateManager::Update
1012 PERF_MONITOR_START(PerformanceMonitor::UPDATE);
1014 // Update the frame time delta on the render thread.
1015 mImpl->renderManager.SetFrameDeltaTime(elapsedSeconds);
1017 // 1) Clear nodes/resources which were previously discarded
1018 mImpl->discardQueue.Clear( mSceneGraphBuffers.GetUpdateBufferIndex() );
1020 // 2) Grab any loaded resources
1021 bool resourceChanged = mImpl->resourceManager.UpdateCache( mSceneGraphBuffers.GetUpdateBufferIndex() );
1023 // 3) Process Touches & Gestures
1024 mImpl->touchResampler.Update();
1025 const bool gestureUpdated = ProcessGestures( lastVSyncTime, nextVSyncTime );
1027 const bool updateScene = // The scene-graph requires an update if..
1028 mImpl->activeConstraints != 0 || // ..constraints were active in previous frame OR
1029 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
1030 IsAnimationRunning() || // ..at least one animation is running OR
1031 mImpl->dynamicsChanged || // ..there was a change in the dynamics simulation OR
1032 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
1033 resourceChanged || // ..one or more resources were updated/changed OR
1034 gestureUpdated; // ..a gesture property was updated
1036 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
1037 // values if the scene was updated in the previous frame.
1038 if( updateScene || mImpl->previousUpdateScene )
1040 // 4) Reset properties from the previous update
1044 // 5) Process the queued scene messages
1045 mImpl->messageQueue.ProcessMessages();
1047 // 6) Post Process Ids of resources updated by renderer
1048 mImpl->resourceManager.PostProcessResources( mSceneGraphBuffers.GetUpdateBufferIndex() );
1050 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
1051 // renderer lists if the scene was updated in the previous frame.
1052 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
1053 if( updateScene || mImpl->previousUpdateScene )
1056 Animate( elapsedSeconds );
1058 // 8) Apply Constraints
1061 #ifdef DYNAMICS_SUPPORT
1062 // 9) Update dynamics simulation
1063 mImpl->dynamicsChanged = false;
1064 if( mImpl->dynamicsWorld )
1066 mImpl->dynamicsChanged = mImpl->dynamicsWorld->Update( elapsedSeconds );
1070 // 10) Check Property Notifications
1071 ProcessPropertyNotifications();
1073 // 11) Clear the lists of renderable-attachments from the previous update
1074 ClearRenderables( mImpl->sortedLayers );
1075 ClearRenderables( mImpl->systemLevelSortedLayers );
1077 // 12) Update animated meshes
1078 UpdateMeshes( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->animatableMeshes );
1080 // 13) Update materials. Prepares image resources
1081 UpdateMaterials( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->materials );
1083 // 14) Update node hierarchy and perform sorting / culling.
1084 // This will populate each Layer with a list of renderers which are ready.
1087 // 15) Prepare for the next render
1088 PERF_MONITOR_START(PerformanceMonitor::PREPARE_RENDERABLES);
1089 PrepareMaterials( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->materials );
1090 PrepareRenderables( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->sortedLayers );
1091 PrepareRenderables( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->systemLevelSortedLayers );
1092 PERF_MONITOR_END(PerformanceMonitor::PREPARE_RENDERABLES);
1094 PERF_MONITOR_START(PerformanceMonitor::PROCESS_RENDER_TASKS);
1096 // 16) Process the RenderTasks; this creates the instructions for rendering the next frame.
1097 // reset the update buffer index and make sure there is enough room in the instruction container
1098 mImpl->renderInstructions.ResetAndReserve( mSceneGraphBuffers.GetUpdateBufferIndex(),
1099 mImpl->taskList.GetTasks().Count() + mImpl->systemLevelTaskList.GetTasks().Count() );
1101 if ( NULL != mImpl->root )
1103 ProcessRenderTasks( mSceneGraphBuffers.GetUpdateBufferIndex(),
1104 mImpl->completeStatusManager,
1107 mImpl->sortedLayers,
1108 mImpl->renderSortingHelper,
1109 mImpl->renderInstructions );
1111 // Process the system-level RenderTasks last
1112 if ( NULL != mImpl->systemLevelRoot )
1114 ProcessRenderTasks( mSceneGraphBuffers.GetUpdateBufferIndex(),
1115 mImpl->completeStatusManager,
1116 mImpl->systemLevelTaskList,
1117 *mImpl->systemLevelRoot,
1118 mImpl->systemLevelSortedLayers,
1119 mImpl->renderSortingHelper,
1120 mImpl->renderInstructions );
1123 #ifdef DYNAMICS_SUPPORT
1124 // if dynamics enabled and active...update matrices for debug drawing
1125 if( mImpl->dynamicsWorld && mImpl->dynamicsChanged )
1127 RenderTask* task(mImpl->taskList.GetTasks()[0]);
1130 mImpl->dynamicsWorld->UpdateMatrices( task->GetProjectionMatrix(mSceneGraphBuffers.GetUpdateBufferIndex()),
1131 task->GetViewMatrix(mSceneGraphBuffers.GetUpdateBufferIndex()) );
1134 #endif // DYNAMICS_SUPPORT
1139 // check the countdown and notify
1140 bool doRenderOnceNotify = false;
1141 mImpl->renderTaskWaiting = false;
1142 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
1143 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(), endIter = tasks.End();
1144 endIter != iter; ++iter )
1146 RenderTask& renderTask(*(*iter));
1148 if( renderTask.IsWaitingToRender() )
1150 mImpl->renderTaskWaiting = true; // keep update/render threads alive
1153 if( renderTask.HasRendered() )
1155 doRenderOnceNotify = true;
1159 if( doRenderOnceNotify )
1161 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
1162 mImpl->notificationManager.QueueMessage( NotifyFinishedMessage( *mImpl->renderTaskList ) );
1165 PERF_MONITOR_END(PerformanceMonitor::PROCESS_RENDER_TASKS);
1167 // Macro is undefined in release build.
1168 SNAPSHOT_NODE_LOGGING;
1170 // A ResetProperties() may be required in the next frame
1171 mImpl->previousUpdateScene = updateScene;
1173 // Check whether further updates are required
1174 unsigned int keepUpdating = KeepUpdatingCheck( elapsedSeconds );
1176 #ifdef PERFORMANCE_MONITOR_ENABLED
1177 // Always keep rendering when measuring FPS
1178 keepUpdating |= KeepUpdating::MONITORING_PERFORMANCE;
1181 // The update has finished; swap the double-buffering indices
1182 mSceneGraphBuffers.Swap();
1184 PERF_MONITOR_END(PerformanceMonitor::UPDATE);
1186 return keepUpdating;
1189 unsigned int UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
1191 // Update the duration set via Stage::KeepRendering()
1192 if ( mImpl->keepRenderingSeconds > 0.0f )
1194 mImpl->keepRenderingSeconds -= elapsedSeconds;
1197 unsigned int keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
1199 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
1200 // Keep updating until no messages are received and no animations are running.
1201 // If an animation has just finished, update at least once more for Discard end-actions.
1202 // No need to check for renderQueue as there is always a render after update and if that
1203 // render needs another update it will tell the adaptor to call update again
1205 if ( mImpl->keepRenderingSeconds > 0.0f )
1207 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
1210 if ( !mImpl->messageQueue.WasEmpty() )
1212 keepUpdatingRequest |= KeepUpdating::INCOMING_MESSAGES;
1215 if ( IsAnimationRunning() ||
1216 mImpl->animationFinishedDuringUpdate )
1218 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
1221 if ( mImpl->dynamicsChanged )
1223 keepUpdatingRequest |= KeepUpdating::DYNAMICS_CHANGED;
1226 if ( mImpl->renderTaskWaiting )
1228 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
1231 return keepUpdatingRequest;
1234 void UpdateManager::SetBackgroundColor( const Vector4& color )
1236 typedef MessageValue1< RenderManager, Vector4 > DerivedType;
1238 // Reserve some memory inside the render queue
1239 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1241 // Construct message in the render queue memory; note that delete should not be called on the return value
1242 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
1245 void UpdateManager::SetDefaultSurfaceRect( const Rect<int>& rect )
1247 typedef MessageValue1< RenderManager, Rect<int> > DerivedType;
1249 // Reserve some memory inside the render queue
1250 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1252 // Construct message in the render queue memory; note that delete should not be called on the return value
1253 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1256 void UpdateManager::KeepRendering( float durationSeconds )
1258 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1261 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, bool systemLevel )
1265 // just copy the vector of pointers
1266 mImpl->sortedLayers = layers;
1270 mImpl->systemLevelSortedLayers = layers;
1274 #ifdef DYNAMICS_SUPPORT
1276 void UpdateManager::InitializeDynamicsWorld( SceneGraph::DynamicsWorld* dynamicsWorld, Integration::DynamicsWorldSettings* worldSettings, SceneGraph::Shader* debugShader )
1278 dynamicsWorld->Initialize( mImpl->sceneController, worldSettings, debugShader, &mSceneGraphBuffers );
1279 mImpl->dynamicsWorld = dynamicsWorld;
1281 typedef MessageValue1< RenderManager, DynamicsDebugRenderer* > DerivedType;
1283 // Reserve some memory inside the render queue
1284 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1286 // Construct message in the render queue memory; note that delete should not be called on the return value
1287 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::InitializeDynamicsDebugRenderer, &dynamicsWorld->GetDebugRenderer() );
1290 void UpdateManager::TerminateDynamicsWorld()
1292 mImpl->dynamicsWorld.Reset();
1295 #endif // DYNAMICS_SUPPORT
1297 } // namespace SceneGraph
1299 } // namespace Internal