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/common/scene-graph-property-buffer.h>
43 #include <dali/internal/update/controllers/render-message-dispatcher.h>
44 #include <dali/internal/update/controllers/scene-controller-impl.h>
45 #include <dali/internal/update/effects/scene-graph-material.h>
46 #include <dali/internal/update/effects/scene-graph-sampler.h>
47 #include <dali/internal/update/geometry/scene-graph-geometry.h>
48 #include <dali/internal/update/gestures/scene-graph-pan-gesture.h>
49 #include <dali/internal/update/manager/object-owner-container.h>
50 #include <dali/internal/update/manager/prepare-render-algorithms.h>
51 #include <dali/internal/update/manager/process-render-tasks.h>
52 #include <dali/internal/update/manager/sorted-layers.h>
53 #include <dali/internal/update/manager/update-algorithms.h>
54 #include <dali/internal/update/manager/update-manager-debug.h>
55 #include <dali/internal/update/node-attachments/scene-graph-camera-attachment.h>
56 #include <dali/internal/update/node-attachments/scene-graph-renderer-attachment.h>
57 #include <dali/internal/update/node-attachments/scene-graph-image-attachment.h>
58 #include <dali/internal/update/node-attachments/scene-graph-text-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/queue/update-message-queue.h>
62 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
63 #include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
64 #include <dali/internal/update/resources/resource-manager.h>
65 #include <dali/internal/update/resources/complete-status-manager.h>
66 #include <dali/internal/update/touch/touch-resampler.h>
68 #include <dali/internal/render/common/render-instruction-container.h>
69 #include <dali/internal/render/common/render-manager.h>
70 #include <dali/internal/render/queue/render-queue.h>
71 #include <dali/internal/render/common/performance-monitor.h>
72 #include <dali/internal/render/gl-resources/texture-cache.h>
73 #include <dali/internal/render/shaders/scene-graph-shader.h>
75 #ifdef DYNAMICS_SUPPORT
76 #include <dali/integration-api/dynamics/dynamics-world-settings.h>
77 #include <dali/internal/update/dynamics/scene-graph-dynamics-world.h>
80 // Un-comment to enable node tree debug logging
81 //#define NODE_TREE_LOGGING 1
83 #if ( defined( DEBUG_ENABLED ) && defined( NODE_TREE_LOGGING ) )
84 #define SNAPSHOT_NODE_LOGGING \
85 const int FRAME_COUNT_TRIGGER = 16;\
86 if( mImpl->frameCounter >= FRAME_COUNT_TRIGGER )\
88 if ( NULL != mImpl->root )\
90 mImpl->frameCounter = 0;\
91 PrintNodeTree( *mImpl->root, mSceneGraphBuffers.GetUpdateBufferIndex(), "" );\
94 mImpl->frameCounter++;
96 #define SNAPSHOT_NODE_LOGGING
99 #if defined(DEBUG_ENABLED)
100 extern Debug::Filter* gRenderTaskLogFilter;
104 using namespace Dali::Integration;
105 using Dali::Internal::Update::MessageQueue;
119 void DestroyNodeSet( std::set<Node*>& nodeSet )
121 for( std::set<Node*>::iterator iter = nodeSet.begin(); iter != nodeSet.end(); ++iter )
125 // Call Node::OnDestroy as each node is destroyed
135 typedef OwnerContainer< Shader* > ShaderContainer;
136 typedef ShaderContainer::Iterator ShaderIter;
137 typedef ShaderContainer::ConstIterator ShaderConstIter;
139 typedef OwnerContainer<PanGesture*> GestureContainer;
140 typedef GestureContainer::Iterator GestureIter;
141 typedef GestureContainer::ConstIterator GestureConstIter;
145 * Structure to contain UpdateManager internal data
147 struct UpdateManager::Impl
149 Impl( NotificationManager& notificationManager,
150 GlSyncAbstraction& glSyncAbstraction,
151 CompleteNotificationInterface& animationFinishedNotifier,
152 PropertyNotifier& propertyNotifier,
153 ResourceManager& resourceManager,
154 DiscardQueue& discardQueue,
155 RenderController& renderController,
156 RenderManager& renderManager,
157 RenderQueue& renderQueue,
158 TextureCache& textureCache,
159 TouchResampler& touchResampler,
160 SceneGraphBuffers& sceneGraphBuffers )
162 renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ),
163 notificationManager( notificationManager ),
164 animationFinishedNotifier( animationFinishedNotifier ),
165 propertyNotifier( propertyNotifier ),
166 resourceManager( resourceManager ),
167 discardQueue( discardQueue ),
168 renderController( renderController ),
169 sceneController( NULL ),
170 renderManager( renderManager ),
171 renderQueue( renderQueue ),
172 renderInstructions( renderManager.GetRenderInstructionContainer() ),
173 completeStatusManager( glSyncAbstraction, renderMessageDispatcher, resourceManager ),
174 touchResampler( touchResampler ),
175 backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
176 taskList ( completeStatusManager ),
177 systemLevelTaskList ( completeStatusManager ),
179 systemLevelRoot( NULL ),
180 geometries( sceneGraphBuffers, discardQueue ),
181 materials( sceneGraphBuffers, discardQueue ),
182 samplers( sceneGraphBuffers, discardQueue ),
183 propertyBuffers( sceneGraphBuffers, discardQueue ),
184 messageQueue( renderController, sceneGraphBuffers ),
185 dynamicsChanged( false ),
186 keepRenderingSeconds( 0.0f ),
187 animationFinishedDuringUpdate( false ),
188 activeConstraints( 0 ),
189 nodeDirtyFlags( TransformFlag ), // set to TransformFlag to ensure full update the first time through Update()
190 previousUpdateScene( false ),
192 renderSortingHelper(),
193 renderTaskWaiting( false )
195 sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue, textureCache, completeStatusManager );
197 geometries.SetSceneController( *sceneController );
198 materials.SetSceneController( *sceneController );
199 propertyBuffers.SetSceneController( *sceneController );
200 samplers.SetSceneController( *sceneController );
205 // Disconnect render tasks from nodes, before destroying the nodes
206 RenderTaskList::RenderTaskContainer& tasks = taskList.GetTasks();
207 for (RenderTaskList::RenderTaskContainer::Iterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
209 (*iter)->SetSourceNode( NULL );
211 // ..repeat for system level RenderTasks
212 RenderTaskList::RenderTaskContainer& systemLevelTasks = systemLevelTaskList.GetTasks();
213 for (RenderTaskList::RenderTaskContainer::Iterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
215 (*iter)->SetSourceNode( NULL );
218 // UpdateManager owns the Nodes
219 DestroyNodeSet( activeDisconnectedNodes );
220 DestroyNodeSet( connectedNodes );
221 DestroyNodeSet( disconnectedNodes );
223 // If there is root, reset it, otherwise do nothing as rendering was never started
232 if( systemLevelRoot )
234 systemLevelRoot->OnDestroy();
236 delete systemLevelRoot;
237 systemLevelRoot = NULL;
240 sceneController->GetTextureCache().SetBufferIndices(NULL); // TODO - Remove
241 delete sceneController;
244 SceneGraphBuffers sceneGraphBuffers; ///< Used to keep track of which buffers are being written or read
245 RenderMessageDispatcher renderMessageDispatcher; ///< Used for passing messages to the render-thread
246 NotificationManager& notificationManager; ///< Queues notification messages for the event-thread.
247 CompleteNotificationInterface& animationFinishedNotifier; ///< Provides notification to applications when animations are finished.
248 PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
249 ResourceManager& resourceManager; ///< resource manager
250 DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
251 RenderController& renderController; ///< render controller
252 SceneControllerImpl* sceneController; ///< scene controller
253 RenderManager& renderManager; ///< This is responsible for rendering the results of each "update"
254 RenderQueue& renderQueue; ///< Used to queue messages for the next render
255 RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions
256 CompleteStatusManager completeStatusManager; ///< Complete Status Manager
257 TouchResampler& touchResampler; ///< Used to resample touch events on every update.
259 Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
261 RenderTaskList taskList; ///< The list of scene graph render-tasks
262 RenderTaskList systemLevelTaskList; ///< Separate render-tasks for system-level content
264 Layer* root; ///< The root node (root is a layer)
265 Layer* systemLevelRoot; ///< A separate root-node for system-level content
266 std::set< Node* > activeDisconnectedNodes; ///< A container of new or modified nodes (without parent) owned by UpdateManager
267 std::set< Node* > connectedNodes; ///< A container of connected (with parent) nodes owned by UpdateManager
268 std::set< Node* > disconnectedNodes; ///< A container of inactive disconnected nodes (without parent) owned by UpdateManager
270 SortedLayerPointers sortedLayers; ///< A container of Layer pointers sorted by depth
271 SortedLayerPointers systemLevelSortedLayers; ///< A separate container of system-level Layers
273 OwnerContainer< PropertyOwner* > customObjects; ///< A container of owned objects (with custom properties)
275 AnimationContainer animations; ///< A container of owned animations
276 PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
278 ObjectOwnerContainer<Geometry> geometries; ///< A container of geometries
279 ObjectOwnerContainer<Material> materials; ///< A container of materials
280 ObjectOwnerContainer<Sampler> samplers; ///< A container of samplers
281 ObjectOwnerContainer<PropertyBuffer> propertyBuffers; ///< A container of property buffers
283 ShaderContainer shaders; ///< A container of owned shaders
285 MessageQueue messageQueue; ///< The messages queued from the event-thread
287 #ifdef DYNAMICS_SUPPORT
288 OwnerPointer<DynamicsWorld> dynamicsWorld; ///< Wrapper for dynamics simulation
290 bool dynamicsChanged; ///< This is set to true if an object is changed in the dynamics simulation tick
292 float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
293 bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
295 unsigned int activeConstraints; ///< number of active constraints from previous frame
296 int nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
297 bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
299 int frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
300 RendererSortingHelper renderSortingHelper; ///< helper used to sort transparent renderers
302 GestureContainer gestures; ///< A container of owned gesture detectors
303 bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
306 UpdateManager::UpdateManager( NotificationManager& notificationManager,
307 GlSyncAbstraction& glSyncAbstraction,
308 CompleteNotificationInterface& animationFinishedNotifier,
309 PropertyNotifier& propertyNotifier,
310 ResourceManager& resourceManager,
311 DiscardQueue& discardQueue,
312 RenderController& controller,
313 RenderManager& renderManager,
314 RenderQueue& renderQueue,
315 TextureCache& textureCache,
316 TouchResampler& touchResampler )
319 mImpl = new Impl( notificationManager,
321 animationFinishedNotifier,
330 mSceneGraphBuffers );
332 textureCache.SetBufferIndices( &mSceneGraphBuffers );
335 UpdateManager::~UpdateManager()
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, int index )
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, index );
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 //@todo MESH_REWORK Extend to allow arbitrary scene objects to connect to each other
430 void UpdateManager::AttachToNode( Node* node, NodeAttachment* attachment )
432 DALI_ASSERT_DEBUG( node != NULL );
433 DALI_ASSERT_DEBUG( attachment != NULL );
435 // attach node to attachment first so that parent is known by the time attachment is connected
436 node->Attach( *attachment ); // node takes ownership
438 // @todo MESH_REWORK Remove after merge of SceneGraph::RenderableAttachment and SceneGraph::RendererAttachment
439 if( dynamic_cast<SceneGraph::ImageAttachment*>( attachment ) != NULL ||
440 dynamic_cast<SceneGraph::TextAttachment*>( attachment ) != NULL )
442 attachment->Initialize( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
446 void UpdateManager::AttachToSceneGraph( RendererAttachment* renderer )
448 // @todo MESH_REWORK Take ownership of this object after merge with SceneGraph::RenderableAttachment
450 SceneGraph::NodeAttachment* attachment = static_cast<SceneGraph::NodeAttachment*>(renderer);
451 attachment->Initialize( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
454 void UpdateManager::AddObject( PropertyOwner* object )
456 DALI_ASSERT_DEBUG( NULL != object );
458 mImpl->customObjects.PushBack( object );
461 void UpdateManager::RemoveObject( PropertyOwner* object )
463 DALI_ASSERT_DEBUG( NULL != object );
465 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
467 // Find the object and destroy it
468 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); iter != customObjects.End(); ++iter )
470 PropertyOwner* current = *iter;
471 if ( current == object )
473 customObjects.Erase( iter );
478 // Should not reach here
479 DALI_ASSERT_DEBUG(false);
482 void UpdateManager::AddAnimation( Animation* animation )
484 mImpl->animations.PushBack( animation );
487 void UpdateManager::StopAnimation( Animation* animation )
489 DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
491 bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
493 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
496 void UpdateManager::RemoveAnimation( Animation* animation )
498 DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
500 animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
502 DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
505 bool UpdateManager::IsAnimationRunning() const
507 bool isRunning(false);
508 AnimationContainer& animations = mImpl->animations;
510 // Find any animation that isn't stopped or paused
512 const AnimationIter endIter = animations.End();
513 for ( AnimationIter iter = animations.Begin(); !isRunning && iter != endIter; ++iter )
515 const Animation::State state = (*iter)->GetState();
517 if (state != Animation::Stopped &&
518 state != Animation::Paused)
527 void UpdateManager::AddPropertyNotification( PropertyNotification* propertyNotification )
529 mImpl->propertyNotifications.PushBack( propertyNotification );
532 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
534 PropertyNotificationContainer &propertyNotifications = mImpl->propertyNotifications;
535 PropertyNotificationIter iter = propertyNotifications.Begin();
537 while ( iter != propertyNotifications.End() )
539 if( *iter == propertyNotification )
541 propertyNotifications.Erase(iter);
548 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
550 DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
551 propertyNotification->SetNotifyMode( notifyMode );
554 ObjectOwnerContainer<Geometry>& UpdateManager::GetGeometryOwner()
556 return mImpl->geometries;
559 ObjectOwnerContainer<Material>& UpdateManager::GetMaterialOwner()
561 return mImpl->materials;
564 ObjectOwnerContainer<Sampler>& UpdateManager::GetSamplerOwner()
566 return mImpl->samplers;
569 ObjectOwnerContainer<PropertyBuffer>& UpdateManager::GetPropertyBufferOwner()
571 return mImpl->propertyBuffers;
574 void UpdateManager::AddShader( Shader* shader )
576 DALI_ASSERT_DEBUG( NULL != shader );
578 if( mImpl->shaders.Count() == 0 )
580 // the first added shader becomes our default shader
581 // Construct message in the render queue memory; note that delete should not be called on the return value
582 typedef MessageValue1< RenderManager, Shader* > DerivedType;
584 // Reserve some memory inside the render queue
585 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
587 // Construct message in the render queue memory; note that delete should not be called on the return value
588 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultShader, shader );
591 mImpl->shaders.PushBack( shader );
593 // Allows the shader to dispatch texture requests to the cache
594 shader->Initialize( mImpl->renderQueue, mImpl->sceneController->GetTextureCache() );
597 void UpdateManager::RemoveShader( Shader* shader )
599 DALI_ASSERT_DEBUG(shader != NULL);
601 ShaderContainer& shaders = mImpl->shaders;
603 // Find the shader and destroy it
604 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
606 Shader& current = **iter;
607 if ( ¤t == shader )
609 // Transfer ownership to the discard queue
610 // This keeps the shader alive, until the render-thread has finished with it
611 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), shaders.Release( iter ) );
616 // Should not reach here
617 DALI_ASSERT_DEBUG(false);
620 void UpdateManager::SetShaderProgram( Shader* shader, GeometryType geometryType, ShaderSubTypes subType, ResourceId resourceId, size_t shaderHash, bool modifiesGeometry )
622 DALI_LOG_TRACE_METHOD_FMT(Debug::Filter::gShader, " - (geometryType:%d subType:%d id:%d hash:%d)\n", geometryType, subType, resourceId, shaderHash);
624 DALI_ASSERT_ALWAYS( NULL != shader && "shader is uninitialized" );
626 Integration::ShaderDataPtr shaderData( mImpl->resourceManager.GetShaderData(resourceId) );
629 shaderData->SetHashValue( shaderHash );
630 shaderData->SetResourceId( resourceId );
632 typedef MessageValue6< Shader, GeometryType, Internal::ShaderSubTypes, Integration::ResourceId, Integration::ShaderDataPtr, ProgramCache*, bool> DerivedType;
634 // Reserve some memory inside the render queue
635 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
637 // Construct message in the render queue memory; note that delete should not be called on the return value
638 new (slot) DerivedType( shader, &Shader::SetProgram, geometryType, subType, resourceId, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
642 RenderTaskList* UpdateManager::GetRenderTaskList( bool systemLevel )
646 // copy the list, this is only likely to happen once in application life cycle
647 return &(mImpl->taskList);
651 // copy the list, this is only likely to happen once in application life cycle
652 return &(mImpl->systemLevelTaskList);
656 void UpdateManager::AddGesture( PanGesture* gesture )
658 DALI_ASSERT_DEBUG( NULL != gesture );
660 mImpl->gestures.PushBack( gesture );
663 void UpdateManager::RemoveGesture( PanGesture* gesture )
665 DALI_ASSERT_DEBUG( gesture != NULL );
667 GestureContainer& gestures = mImpl->gestures;
669 // Find the gesture and destroy it
670 for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
672 PanGesture& current = **iter;
673 if ( ¤t == gesture )
675 mImpl->gestures.Erase( iter );
679 // Should not reach here
680 DALI_ASSERT_DEBUG(false);
683 unsigned int* UpdateManager::ReserveMessageSlot( std::size_t size, bool updateScene )
685 return mImpl->messageQueue.ReserveMessageSlot( size, updateScene );
688 void UpdateManager::EventProcessingStarted()
690 mImpl->messageQueue.EventProcessingStarted();
693 bool UpdateManager::FlushQueue()
695 return mImpl->messageQueue.FlushQueue();
698 void UpdateManager::ResetNodeProperty( Node& node )
700 node.ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() );
703 void UpdateManager::ResetProperties()
705 PERF_MONITOR_START(PerformanceMonitor::RESET_PROPERTIES);
707 BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
709 // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
710 mImpl->animationFinishedDuringUpdate = false;
712 // Animated properties have to be reset to their original value each frame
714 // Reset node properties
717 ResetNodeProperty( *mImpl->root );
720 if ( mImpl->systemLevelRoot )
722 ResetNodeProperty( *mImpl->systemLevelRoot );
725 // Reset the Connected Nodes
726 const std::set<Node*>::iterator endIter = mImpl->connectedNodes.end();
727 for( std::set<Node*>::iterator iter = mImpl->connectedNodes.begin(); endIter != iter; ++iter )
729 ResetNodeProperty( **iter );
732 // If a Node is disconnected, it may still be "active" (requires a reset in next frame)
733 for( std::set<Node*>::iterator iter = mImpl->activeDisconnectedNodes.begin(); mImpl->activeDisconnectedNodes.end() != iter; iter = mImpl->activeDisconnectedNodes.begin() )
736 node->ResetToBaseValues( bufferIndex );
737 node->SetActive( false );
739 // Move everything from activeDisconnectedNodes to disconnectedNodes (no need to reset again)
740 mImpl->activeDisconnectedNodes.erase( iter );
741 mImpl->disconnectedNodes.insert( node );
744 // Reset system-level render-task list properties to base values
745 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
747 for (RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
749 (*iter)->ResetToBaseValues( bufferIndex );
752 // Reset render-task list properties to base values.
753 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
755 for (RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
757 (*iter)->ResetToBaseValues( bufferIndex );
760 // Reset custom object properties to base values
761 for (OwnerContainer<PropertyOwner*>::Iterator iter = mImpl->customObjects.Begin(); iter != mImpl->customObjects.End(); ++iter)
763 (*iter)->ResetToBaseValues( bufferIndex );
766 mImpl->materials.ResetToBaseValues( bufferIndex );
767 mImpl->geometries.ResetToBaseValues( bufferIndex );
768 mImpl->propertyBuffers.ResetToBaseValues( bufferIndex );
769 mImpl->samplers.ResetToBaseValues( bufferIndex );
772 // Reset animatable shader properties to base values
773 for (ShaderIter iter = mImpl->shaders.Begin(); iter != mImpl->shaders.End(); ++iter)
775 (*iter)->ResetToBaseValues( bufferIndex );
778 PERF_MONITOR_END(PerformanceMonitor::RESET_PROPERTIES);
781 bool UpdateManager::ProcessGestures( unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds )
783 bool gestureUpdated( false );
785 // constrain gestures... (in construction order)
786 GestureContainer& gestures = mImpl->gestures;
788 for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
790 PanGesture& gesture = **iter;
791 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
792 gestureUpdated |= gesture.UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
795 return gestureUpdated;
798 void UpdateManager::Animate( float elapsedSeconds )
800 PERF_MONITOR_START(PerformanceMonitor::ANIMATE_NODES);
802 AnimationContainer &animations = mImpl->animations;
803 AnimationIter iter = animations.Begin();
804 while ( iter != animations.End() )
806 Animation* animation = *iter;
807 bool finished = animation->Update(mSceneGraphBuffers.GetUpdateBufferIndex(), elapsedSeconds);
809 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
811 // Remove animations that had been destroyed but were still waiting for an update
812 if (animation->GetState() == Animation::Destroyed)
814 iter = animations.Erase(iter);
822 if ( mImpl->animationFinishedDuringUpdate )
824 // The application should be notified by NotificationManager, in another thread
825 mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationFinishedNotifier );
828 PERF_MONITOR_END(PerformanceMonitor::ANIMATE_NODES);
831 void UpdateManager::ApplyConstraints()
833 PERF_MONITOR_START(PerformanceMonitor::APPLY_CONSTRAINTS);
835 BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
837 mImpl->activeConstraints = 0;
839 // constrain custom objects... (in construction order)
840 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
842 const OwnerContainer< PropertyOwner* >::Iterator endIter = customObjects.End();
843 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); endIter != iter; ++iter )
845 PropertyOwner& object = **iter;
846 mImpl->activeConstraints += ConstrainPropertyOwner( object, bufferIndex );
849 // constrain nodes... (in Depth First traversal order)
852 mImpl->activeConstraints += ConstrainNodes( *(mImpl->root), bufferIndex );
855 if ( mImpl->systemLevelRoot )
857 mImpl->activeConstraints += ConstrainNodes( *(mImpl->systemLevelRoot), bufferIndex );
860 // constrain other property-owners after nodes as they are more likely to depend on a node's
861 // current frame property than vice versa. They tend to be final constraints (no further
862 // constraints depend on their properties)
863 // e.g. ShaderEffect uniform a function of Actor's position.
864 // Mesh vertex a function of Actor's position or world position.
866 // TODO: refactor this code (and reset nodes) as these are all just lists of property-owners
867 // they can be all processed in a super-list of property-owners.
869 // Constrain system-level render-tasks
870 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
872 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter )
874 RenderTask& task = **iter;
875 mImpl->activeConstraints += ConstrainPropertyOwner( task, bufferIndex );
878 // Constrain render-tasks
879 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
881 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter )
883 RenderTask& task = **iter;
884 mImpl->activeConstraints += ConstrainPropertyOwner( task, bufferIndex );
887 // Constrain Materials and geometries
888 mImpl->activeConstraints += mImpl->materials.ConstrainObjects( bufferIndex );
889 mImpl->activeConstraints += mImpl->geometries.ConstrainObjects( bufferIndex );
890 mImpl->activeConstraints += mImpl->samplers.ConstrainObjects( bufferIndex );
891 mImpl->activeConstraints += mImpl->propertyBuffers.ConstrainObjects( bufferIndex );
893 // constrain shaders... (in construction order)
894 ShaderContainer& shaders = mImpl->shaders;
896 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
898 Shader& shader = **iter;
899 mImpl->activeConstraints += ConstrainPropertyOwner( shader, bufferIndex );
902 PERF_MONITOR_END(PerformanceMonitor::APPLY_CONSTRAINTS);
905 void UpdateManager::ProcessPropertyNotifications()
907 PropertyNotificationContainer ¬ifications = mImpl->propertyNotifications;
908 PropertyNotificationIter iter = notifications.Begin();
910 BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
912 while ( iter != notifications.End() )
914 PropertyNotification* notification = *iter;
915 bool valid = notification->Check( bufferIndex );
918 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
924 void UpdateManager::UpdateNodes()
926 mImpl->nodeDirtyFlags = NothingFlag;
933 PERF_MONITOR_START( PerformanceMonitor::UPDATE_NODES );
935 // Prepare resources, update shaders, update attachments, for each node
936 // And add the renderers to the sorted layers. Start from root, which is also a layer
937 mImpl->nodeDirtyFlags = UpdateNodesAndAttachments( *( mImpl->root ),
938 mSceneGraphBuffers.GetUpdateBufferIndex(),
939 mImpl->resourceManager,
940 mImpl->renderQueue );
942 if ( mImpl->systemLevelRoot )
944 mImpl->nodeDirtyFlags |= UpdateNodesAndAttachments( *( mImpl->systemLevelRoot ),
945 mSceneGraphBuffers.GetUpdateBufferIndex(),
946 mImpl->resourceManager,
947 mImpl->renderQueue );
950 PERF_MONITOR_END( PerformanceMonitor::UPDATE_NODES );
953 unsigned int UpdateManager::Update( float elapsedSeconds,
954 unsigned int lastVSyncTimeMilliseconds,
955 unsigned int nextVSyncTimeMilliseconds )
957 PERF_MONITOR_END(PerformanceMonitor::FRAME_RATE); // Mark the End of the last frame
958 PERF_MONITOR_NEXT_FRAME(); // Prints out performance info for the last frame (if enabled)
959 PERF_MONITOR_START(PerformanceMonitor::FRAME_RATE); // Mark the start of this current frame
961 // Measure the time spent in UpdateManager::Update
962 PERF_MONITOR_START(PerformanceMonitor::UPDATE);
964 BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
966 // Update the frame time delta on the render thread.
967 mImpl->renderManager.SetFrameDeltaTime(elapsedSeconds);
969 // 1) Clear nodes/resources which were previously discarded
970 mImpl->discardQueue.Clear( bufferIndex );
972 // 2) Grab any loaded resources
973 bool resourceChanged = mImpl->resourceManager.UpdateCache( bufferIndex );
975 // 3) Process Touches & Gestures
976 mImpl->touchResampler.Update();
977 const bool gestureUpdated = ProcessGestures( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
979 const bool updateScene = // The scene-graph requires an update if..
980 mImpl->activeConstraints != 0 || // ..constraints were active in previous frame OR
981 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
982 IsAnimationRunning() || // ..at least one animation is running OR
983 mImpl->dynamicsChanged || // ..there was a change in the dynamics simulation OR
984 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
985 resourceChanged || // ..one or more resources were updated/changed OR
986 gestureUpdated; // ..a gesture property was updated
988 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
989 // values if the scene was updated in the previous frame.
990 if( updateScene || mImpl->previousUpdateScene )
992 // 4) Reset properties from the previous update
996 // 5) Process the queued scene messages
997 mImpl->messageQueue.ProcessMessages();
999 // 6) Post Process Ids of resources updated by renderer
1000 mImpl->resourceManager.PostProcessResources( bufferIndex );
1002 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
1003 // renderer lists if the scene was updated in the previous frame.
1004 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
1005 if( updateScene || mImpl->previousUpdateScene )
1008 Animate( elapsedSeconds );
1010 // 8) Apply Constraints
1013 #ifdef DYNAMICS_SUPPORT
1014 // 9) Update dynamics simulation
1015 mImpl->dynamicsChanged = false;
1016 if( mImpl->dynamicsWorld )
1018 mImpl->dynamicsChanged = mImpl->dynamicsWorld->Update( elapsedSeconds );
1022 // 10) Check Property Notifications
1023 ProcessPropertyNotifications();
1025 // 11) Clear the lists of renderable-attachments from the previous update
1026 ClearRenderables( mImpl->sortedLayers );
1027 ClearRenderables( mImpl->systemLevelSortedLayers );
1029 // 12) Update node hierarchy and perform sorting / culling.
1030 // This will populate each Layer with a list of renderers which are ready.
1033 // 13) Prepare for the next render
1034 PERF_MONITOR_START(PerformanceMonitor::PREPARE_RENDERABLES);
1036 PrepareRenderables( bufferIndex, mImpl->sortedLayers );
1037 PrepareRenderables( bufferIndex, mImpl->systemLevelSortedLayers );
1038 PERF_MONITOR_END(PerformanceMonitor::PREPARE_RENDERABLES);
1040 PERF_MONITOR_START(PerformanceMonitor::PROCESS_RENDER_TASKS);
1042 // 14) Process the RenderTasks; this creates the instructions for rendering the next frame.
1043 // reset the update buffer index and make sure there is enough room in the instruction container
1044 mImpl->renderInstructions.ResetAndReserve( mSceneGraphBuffers.GetUpdateBufferIndex(),
1045 mImpl->taskList.GetTasks().Count() + mImpl->systemLevelTaskList.GetTasks().Count() );
1047 if ( NULL != mImpl->root )
1049 ProcessRenderTasks( bufferIndex,
1050 mImpl->completeStatusManager,
1053 mImpl->sortedLayers,
1054 mImpl->renderSortingHelper,
1055 mImpl->renderInstructions );
1057 // Process the system-level RenderTasks last
1058 if ( NULL != mImpl->systemLevelRoot )
1060 ProcessRenderTasks( bufferIndex,
1061 mImpl->completeStatusManager,
1062 mImpl->systemLevelTaskList,
1063 *mImpl->systemLevelRoot,
1064 mImpl->systemLevelSortedLayers,
1065 mImpl->renderSortingHelper,
1066 mImpl->renderInstructions );
1071 // check the countdown and notify (note, at the moment this is only done for normal tasks, not for systemlevel tasks)
1072 bool doRenderOnceNotify = false;
1073 mImpl->renderTaskWaiting = false;
1074 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
1075 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(), endIter = tasks.End();
1076 endIter != iter; ++iter )
1078 RenderTask& renderTask(*(*iter));
1080 renderTask.UpdateState();
1082 if( renderTask.IsWaitingToRender() &&
1083 renderTask.ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
1085 mImpl->renderTaskWaiting = true; // keep update/render threads alive
1088 if( renderTask.HasRendered() )
1090 doRenderOnceNotify = true;
1094 if( doRenderOnceNotify )
1096 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
1097 mImpl->notificationManager.QueueCompleteNotification( mImpl->taskList.GetCompleteNotificationInterface() );
1100 PERF_MONITOR_END(PerformanceMonitor::PROCESS_RENDER_TASKS);
1102 // Macro is undefined in release build.
1103 SNAPSHOT_NODE_LOGGING;
1105 // A ResetProperties() may be required in the next frame
1106 mImpl->previousUpdateScene = updateScene;
1108 // Check whether further updates are required
1109 unsigned int keepUpdating = KeepUpdatingCheck( elapsedSeconds );
1111 #ifdef PERFORMANCE_MONITOR_ENABLED
1112 // Always keep rendering when measuring FPS
1113 keepUpdating |= KeepUpdating::MONITORING_PERFORMANCE;
1116 // The update has finished; swap the double-buffering indices
1117 mSceneGraphBuffers.Swap();
1119 // tell the update manager that we're done so the queue can be given to event thread
1120 mImpl->notificationManager.UpdateCompleted();
1122 PERF_MONITOR_END(PerformanceMonitor::UPDATE);
1124 return keepUpdating;
1127 unsigned int UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
1129 // Update the duration set via Stage::KeepRendering()
1130 if ( mImpl->keepRenderingSeconds > 0.0f )
1132 mImpl->keepRenderingSeconds -= elapsedSeconds;
1135 unsigned int keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
1137 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
1138 // Keep updating until no messages are received and no animations are running.
1139 // If an animation has just finished, update at least once more for Discard end-actions.
1140 // No need to check for renderQueue as there is always a render after update and if that
1141 // render needs another update it will tell the adaptor to call update again
1143 if ( mImpl->keepRenderingSeconds > 0.0f )
1145 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
1148 if ( IsAnimationRunning() ||
1149 mImpl->animationFinishedDuringUpdate )
1151 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
1154 if ( mImpl->dynamicsChanged )
1156 keepUpdatingRequest |= KeepUpdating::DYNAMICS_CHANGED;
1159 if ( mImpl->renderTaskWaiting )
1161 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
1164 return keepUpdatingRequest;
1167 void UpdateManager::SetBackgroundColor( const Vector4& color )
1169 typedef MessageValue1< RenderManager, Vector4 > DerivedType;
1171 // Reserve some memory inside the render queue
1172 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1174 // Construct message in the render queue memory; note that delete should not be called on the return value
1175 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
1178 void UpdateManager::SetDefaultSurfaceRect( const Rect<int>& rect )
1180 typedef MessageValue1< RenderManager, Rect<int> > DerivedType;
1182 // Reserve some memory inside the render queue
1183 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1185 // Construct message in the render queue memory; note that delete should not be called on the return value
1186 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1189 void UpdateManager::KeepRendering( float durationSeconds )
1191 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1194 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, bool systemLevel )
1198 // just copy the vector of pointers
1199 mImpl->sortedLayers = layers;
1203 mImpl->systemLevelSortedLayers = layers;
1207 #ifdef DYNAMICS_SUPPORT
1209 void UpdateManager::InitializeDynamicsWorld( SceneGraph::DynamicsWorld* dynamicsWorld, Integration::DynamicsWorldSettings* worldSettings )
1211 dynamicsWorld->Initialize( mImpl->sceneController, worldSettings, &mSceneGraphBuffers );
1212 mImpl->dynamicsWorld = dynamicsWorld;
1215 void UpdateManager::TerminateDynamicsWorld()
1217 mImpl->dynamicsWorld.Reset();
1220 #endif // DYNAMICS_SUPPORT
1222 } // namespace SceneGraph
1224 } // namespace Internal