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/devel-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/gestures/scene-graph-pan-gesture.h>
46 #include <dali/internal/update/manager/object-owner-container.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/node-attachments/scene-graph-renderer-attachment.h>
54 #include <dali/internal/update/node-attachments/scene-graph-image-attachment.h>
55 #include <dali/internal/update/nodes/node.h>
56 #include <dali/internal/update/nodes/scene-graph-layer.h>
57 #include <dali/internal/update/queue/update-message-queue.h>
58 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
59 #include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
60 #include <dali/internal/update/rendering/scene-graph-material.h>
61 #include <dali/internal/update/rendering/scene-graph-sampler.h>
62 #include <dali/internal/update/rendering/scene-graph-geometry.h>
63 #include <dali/internal/update/resources/resource-manager.h>
64 #include <dali/internal/update/resources/complete-status-manager.h>
65 #include <dali/internal/update/touch/touch-resampler.h>
67 #include <dali/internal/render/common/render-instruction-container.h>
68 #include <dali/internal/render/common/render-manager.h>
69 #include <dali/internal/render/queue/render-queue.h>
70 #include <dali/internal/render/common/performance-monitor.h>
71 #include <dali/internal/render/gl-resources/texture-cache.h>
72 #include <dali/internal/render/shaders/scene-graph-shader.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< Shader* > ShaderContainer;
130 typedef ShaderContainer::Iterator ShaderIter;
131 typedef ShaderContainer::ConstIterator ShaderConstIter;
133 typedef OwnerContainer<PanGesture*> GestureContainer;
134 typedef GestureContainer::Iterator GestureIter;
135 typedef GestureContainer::ConstIterator GestureConstIter;
139 * Structure to contain UpdateManager internal data
141 struct UpdateManager::Impl
143 Impl( NotificationManager& notificationManager,
144 GlSyncAbstraction& glSyncAbstraction,
145 CompleteNotificationInterface& animationFinishedNotifier,
146 PropertyNotifier& propertyNotifier,
147 ResourceManager& resourceManager,
148 DiscardQueue& discardQueue,
149 RenderController& renderController,
150 RenderManager& renderManager,
151 RenderQueue& renderQueue,
152 TextureCache& textureCache,
153 TouchResampler& touchResampler,
154 SceneGraphBuffers& sceneGraphBuffers )
156 renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ),
157 notificationManager( notificationManager ),
158 animationFinishedNotifier( animationFinishedNotifier ),
159 propertyNotifier( propertyNotifier ),
160 resourceManager( resourceManager ),
161 discardQueue( discardQueue ),
162 renderController( renderController ),
163 sceneController( NULL ),
164 renderManager( renderManager ),
165 renderQueue( renderQueue ),
166 renderInstructions( renderManager.GetRenderInstructionContainer() ),
167 completeStatusManager( glSyncAbstraction, renderMessageDispatcher, resourceManager ),
168 touchResampler( touchResampler ),
169 backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
170 taskList ( completeStatusManager ),
171 systemLevelTaskList ( completeStatusManager ),
173 systemLevelRoot( NULL ),
174 geometries( sceneGraphBuffers, discardQueue ),
175 materials( sceneGraphBuffers, discardQueue ),
176 samplers( sceneGraphBuffers, discardQueue ),
177 propertyBuffers( sceneGraphBuffers, discardQueue ),
178 messageQueue( renderController, sceneGraphBuffers ),
179 keepRenderingSeconds( 0.0f ),
180 animationFinishedDuringUpdate( false ),
181 nodeDirtyFlags( TransformFlag ), // set to TransformFlag to ensure full update the first time through Update()
182 previousUpdateScene( false ),
184 renderSortingHelper(),
185 renderTaskWaiting( false )
187 sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue, textureCache, completeStatusManager );
189 geometries.SetSceneController( *sceneController );
190 materials.SetSceneController( *sceneController );
191 propertyBuffers.SetSceneController( *sceneController );
192 samplers.SetSceneController( *sceneController );
197 // Disconnect render tasks from nodes, before destroying the nodes
198 RenderTaskList::RenderTaskContainer& tasks = taskList.GetTasks();
199 for (RenderTaskList::RenderTaskContainer::Iterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
201 (*iter)->SetSourceNode( NULL );
203 // ..repeat for system level RenderTasks
204 RenderTaskList::RenderTaskContainer& systemLevelTasks = systemLevelTaskList.GetTasks();
205 for (RenderTaskList::RenderTaskContainer::Iterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
207 (*iter)->SetSourceNode( NULL );
210 // UpdateManager owns the Nodes
211 DestroyNodeSet( activeDisconnectedNodes );
212 DestroyNodeSet( connectedNodes );
213 DestroyNodeSet( disconnectedNodes );
215 // If there is root, reset it, otherwise do nothing as rendering was never started
224 if( systemLevelRoot )
226 systemLevelRoot->OnDestroy();
228 delete systemLevelRoot;
229 systemLevelRoot = NULL;
232 sceneController->GetTextureCache().SetBufferIndices(NULL); // TODO - Remove
233 delete sceneController;
236 SceneGraphBuffers sceneGraphBuffers; ///< Used to keep track of which buffers are being written or read
237 RenderMessageDispatcher renderMessageDispatcher; ///< Used for passing messages to the render-thread
238 NotificationManager& notificationManager; ///< Queues notification messages for the event-thread.
239 CompleteNotificationInterface& animationFinishedNotifier; ///< Provides notification to applications when animations are finished.
240 PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
241 ResourceManager& resourceManager; ///< resource manager
242 DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
243 RenderController& renderController; ///< render controller
244 SceneControllerImpl* sceneController; ///< scene controller
245 RenderManager& renderManager; ///< This is responsible for rendering the results of each "update"
246 RenderQueue& renderQueue; ///< Used to queue messages for the next render
247 RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions
248 CompleteStatusManager completeStatusManager; ///< Complete Status Manager
249 TouchResampler& touchResampler; ///< Used to resample touch events on every update.
251 Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
253 RenderTaskList taskList; ///< The list of scene graph render-tasks
254 RenderTaskList systemLevelTaskList; ///< Separate render-tasks for system-level content
256 Layer* root; ///< The root node (root is a layer)
257 Layer* systemLevelRoot; ///< A separate root-node for system-level content
258 std::set< Node* > activeDisconnectedNodes; ///< A container of new or modified nodes (without parent) owned by UpdateManager
259 std::set< Node* > connectedNodes; ///< A container of connected (with parent) nodes owned by UpdateManager
260 std::set< Node* > disconnectedNodes; ///< A container of inactive disconnected nodes (without parent) owned by UpdateManager
262 SortedLayerPointers sortedLayers; ///< A container of Layer pointers sorted by depth
263 SortedLayerPointers systemLevelSortedLayers; ///< A separate container of system-level Layers
265 OwnerContainer< PropertyOwner* > customObjects; ///< A container of owned objects (with custom properties)
267 AnimationContainer animations; ///< A container of owned animations
268 PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
270 ObjectOwnerContainer<Geometry> geometries; ///< A container of geometries
271 ObjectOwnerContainer<Material> materials; ///< A container of materials
272 ObjectOwnerContainer<Sampler> samplers; ///< A container of samplers
273 ObjectOwnerContainer<PropertyBuffer> propertyBuffers; ///< A container of property buffers
275 ShaderContainer shaders; ///< A container of owned shaders
277 MessageQueue messageQueue; ///< The messages queued from the event-thread
279 float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
280 bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
282 int nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
283 bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
285 int frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
286 RendererSortingHelper renderSortingHelper; ///< helper used to sort transparent renderers
288 GestureContainer gestures; ///< A container of owned gesture detectors
289 bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
292 UpdateManager::UpdateManager( NotificationManager& notificationManager,
293 GlSyncAbstraction& glSyncAbstraction,
294 CompleteNotificationInterface& animationFinishedNotifier,
295 PropertyNotifier& propertyNotifier,
296 ResourceManager& resourceManager,
297 DiscardQueue& discardQueue,
298 RenderController& controller,
299 RenderManager& renderManager,
300 RenderQueue& renderQueue,
301 TextureCache& textureCache,
302 TouchResampler& touchResampler )
305 mImpl = new Impl( notificationManager,
307 animationFinishedNotifier,
316 mSceneGraphBuffers );
318 textureCache.SetBufferIndices( &mSceneGraphBuffers );
321 UpdateManager::~UpdateManager()
326 void UpdateManager::InstallRoot( SceneGraph::Layer* layer, bool systemLevel )
328 DALI_ASSERT_DEBUG( layer->IsLayer() );
329 DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
333 DALI_ASSERT_DEBUG( mImpl->root == NULL && "Root Node already installed" );
338 DALI_ASSERT_DEBUG( mImpl->systemLevelRoot == NULL && "System-level Root Node already installed" );
339 mImpl->systemLevelRoot = layer;
342 layer->SetRoot(true);
345 void UpdateManager::AddNode( Node* node )
347 DALI_ASSERT_ALWAYS( NULL != node );
348 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
350 mImpl->activeDisconnectedNodes.insert( node ); // Takes ownership of node
353 void UpdateManager::ConnectNode( Node* parent, Node* node, int index )
355 DALI_ASSERT_ALWAYS( NULL != parent );
356 DALI_ASSERT_ALWAYS( NULL != node );
357 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
359 // Move from active/disconnectedNodes to connectedNodes
360 std::set<Node*>::size_type removed = mImpl->activeDisconnectedNodes.erase( node );
363 removed = mImpl->disconnectedNodes.erase( node );
364 DALI_ASSERT_ALWAYS( removed );
366 mImpl->connectedNodes.insert( node );
368 node->SetActive( true );
370 parent->ConnectChild( node, index );
373 void UpdateManager::DisconnectNode( Node* node )
375 Node* parent = node->GetParent();
376 DALI_ASSERT_ALWAYS( NULL != parent );
377 parent->SetDirtyFlag( ChildDeletedFlag ); // make parent dirty so that render items dont get reused
379 // Move from connectedNodes to activeDisconnectedNodes (reset properties next frame)
380 parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node, mImpl->connectedNodes, mImpl->activeDisconnectedNodes );
383 void UpdateManager::SetNodeActive( Node* node )
385 DALI_ASSERT_ALWAYS( NULL != node );
386 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
388 // Move from disconnectedNodes to activeDisconnectedNodes (reset properties next frame)
389 std::set<Node*>::size_type removed = mImpl->disconnectedNodes.erase( node );
390 DALI_ASSERT_ALWAYS( removed );
391 mImpl->activeDisconnectedNodes.insert( node );
393 node->SetActive( true );
396 void UpdateManager::DestroyNode( Node* node )
398 DALI_ASSERT_ALWAYS( NULL != node );
399 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
401 // Transfer ownership from new/disconnectedNodes to the discard queue
402 // This keeps the nodes alive, until the render-thread has finished with them
403 std::set<Node*>::size_type removed = mImpl->activeDisconnectedNodes.erase( node );
406 removed = mImpl->disconnectedNodes.erase( node );
407 DALI_ASSERT_ALWAYS( removed );
409 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
411 // Notify the Node about impending destruction
415 //@todo MESH_REWORK Extend to allow arbitrary scene objects to connect to each other
416 void UpdateManager::AttachToNode( Node* node, NodeAttachment* attachment )
418 DALI_ASSERT_DEBUG( node != NULL );
419 DALI_ASSERT_DEBUG( attachment != NULL );
421 // attach node to attachment first so that parent is known by the time attachment is connected
422 node->Attach( *attachment ); // node takes ownership
424 // @todo MESH_REWORK Remove after merge of SceneGraph::RenderableAttachment and SceneGraph::RendererAttachment
425 if( dynamic_cast<SceneGraph::ImageAttachment*>( attachment ) != NULL )
427 attachment->Initialize( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
431 void UpdateManager::AttachToSceneGraph( RendererAttachment* renderer )
433 // @todo MESH_REWORK Take ownership of this object after merge with SceneGraph::RenderableAttachment
435 SceneGraph::NodeAttachment* attachment = static_cast<SceneGraph::NodeAttachment*>(renderer);
436 attachment->Initialize( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
439 void UpdateManager::AddObject( PropertyOwner* object )
441 DALI_ASSERT_DEBUG( NULL != object );
443 mImpl->customObjects.PushBack( object );
446 void UpdateManager::RemoveObject( PropertyOwner* object )
448 DALI_ASSERT_DEBUG( NULL != object );
450 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
452 // Find the object and destroy it
453 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); iter != customObjects.End(); ++iter )
455 PropertyOwner* current = *iter;
456 if ( current == object )
458 customObjects.Erase( iter );
463 // Should not reach here
464 DALI_ASSERT_DEBUG(false);
467 void UpdateManager::AddAnimation( Animation* animation )
469 mImpl->animations.PushBack( animation );
472 void UpdateManager::StopAnimation( Animation* animation )
474 DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
476 bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
478 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
481 void UpdateManager::RemoveAnimation( Animation* animation )
483 DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
485 animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
487 DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
490 bool UpdateManager::IsAnimationRunning() const
492 bool isRunning(false);
493 AnimationContainer& animations = mImpl->animations;
495 // Find any animation that isn't stopped or paused
497 const AnimationIter endIter = animations.End();
498 for ( AnimationIter iter = animations.Begin(); !isRunning && iter != endIter; ++iter )
500 const Animation::State state = (*iter)->GetState();
502 if (state != Animation::Stopped &&
503 state != Animation::Paused)
512 void UpdateManager::AddPropertyNotification( PropertyNotification* propertyNotification )
514 mImpl->propertyNotifications.PushBack( propertyNotification );
517 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
519 PropertyNotificationContainer &propertyNotifications = mImpl->propertyNotifications;
520 PropertyNotificationIter iter = propertyNotifications.Begin();
522 while ( iter != propertyNotifications.End() )
524 if( *iter == propertyNotification )
526 propertyNotifications.Erase(iter);
533 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
535 DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
536 propertyNotification->SetNotifyMode( notifyMode );
539 ObjectOwnerContainer<Geometry>& UpdateManager::GetGeometryOwner()
541 return mImpl->geometries;
544 ObjectOwnerContainer<Material>& UpdateManager::GetMaterialOwner()
546 return mImpl->materials;
549 ObjectOwnerContainer<Sampler>& UpdateManager::GetSamplerOwner()
551 return mImpl->samplers;
554 ObjectOwnerContainer<PropertyBuffer>& UpdateManager::GetPropertyBufferOwner()
556 return mImpl->propertyBuffers;
559 void UpdateManager::AddShader( Shader* shader )
561 DALI_ASSERT_DEBUG( NULL != shader );
563 if( mImpl->shaders.Count() == 0 )
565 // the first added shader becomes our default shader
566 // Construct message in the render queue memory; note that delete should not be called on the return value
567 typedef MessageValue1< RenderManager, Shader* > DerivedType;
569 // Reserve some memory inside the render queue
570 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
572 // Construct message in the render queue memory; note that delete should not be called on the return value
573 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultShader, shader );
576 mImpl->shaders.PushBack( shader );
578 // Allows the shader to dispatch texture requests to the cache
579 shader->Initialize( mImpl->renderQueue, mImpl->sceneController->GetTextureCache() );
582 void UpdateManager::RemoveShader( Shader* shader )
584 DALI_ASSERT_DEBUG(shader != NULL);
586 ShaderContainer& shaders = mImpl->shaders;
588 // Find the shader and destroy it
589 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
591 Shader& current = **iter;
592 if ( ¤t == shader )
594 // Transfer ownership to the discard queue
595 // This keeps the shader alive, until the render-thread has finished with it
596 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), shaders.Release( iter ) );
601 // Should not reach here
602 DALI_ASSERT_DEBUG(false);
605 void UpdateManager::SetShaderProgram( Shader* shader,
606 ResourceId resourceId, size_t shaderHash, bool modifiesGeometry )
608 DALI_LOG_TRACE_METHOD_FMT(Debug::Filter::gShader, " - (id:%d hash:%d)\n", resourceId, shaderHash);
610 DALI_ASSERT_ALWAYS( NULL != shader && "shader is uninitialized" );
612 Integration::ShaderDataPtr shaderData( mImpl->resourceManager.GetShaderData(resourceId) );
615 shaderData->SetHashValue( shaderHash );
616 shaderData->SetResourceId( resourceId );
618 typedef MessageValue4< Shader, Integration::ResourceId, Integration::ShaderDataPtr, ProgramCache*, bool> DerivedType;
620 // Reserve some memory inside the render queue
621 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
623 // Construct message in the render queue memory; note that delete should not be called on the return value
624 new (slot) DerivedType( shader, &Shader::SetProgram, resourceId, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
628 RenderTaskList* UpdateManager::GetRenderTaskList( bool systemLevel )
632 // copy the list, this is only likely to happen once in application life cycle
633 return &(mImpl->taskList);
637 // copy the list, this is only likely to happen once in application life cycle
638 return &(mImpl->systemLevelTaskList);
642 void UpdateManager::AddGesture( PanGesture* gesture )
644 DALI_ASSERT_DEBUG( NULL != gesture );
646 mImpl->gestures.PushBack( gesture );
649 void UpdateManager::RemoveGesture( PanGesture* gesture )
651 DALI_ASSERT_DEBUG( gesture != NULL );
653 GestureContainer& gestures = mImpl->gestures;
655 // Find the gesture and destroy it
656 for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
658 PanGesture& current = **iter;
659 if ( ¤t == gesture )
661 mImpl->gestures.Erase( iter );
665 // Should not reach here
666 DALI_ASSERT_DEBUG(false);
669 unsigned int* UpdateManager::ReserveMessageSlot( std::size_t size, bool updateScene )
671 return mImpl->messageQueue.ReserveMessageSlot( size, updateScene );
674 void UpdateManager::EventProcessingStarted()
676 mImpl->messageQueue.EventProcessingStarted();
679 bool UpdateManager::FlushQueue()
681 return mImpl->messageQueue.FlushQueue();
684 void UpdateManager::ResetNodeProperty( Node& node )
686 BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
688 node.ResetToBaseValues( bufferIndex );
691 void UpdateManager::ResetProperties()
693 PERF_MONITOR_START(PerformanceMonitor::RESET_PROPERTIES);
695 BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
697 // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
698 mImpl->animationFinishedDuringUpdate = false;
700 // Animated properties have to be reset to their original value each frame
702 // Reset node properties
705 ResetNodeProperty( *mImpl->root );
708 if ( mImpl->systemLevelRoot )
710 ResetNodeProperty( *mImpl->systemLevelRoot );
713 // Reset the Connected Nodes
714 const std::set<Node*>::iterator endIter = mImpl->connectedNodes.end();
715 for( std::set<Node*>::iterator iter = mImpl->connectedNodes.begin(); endIter != iter; ++iter )
717 ResetNodeProperty( **iter );
720 // If a Node is disconnected, it may still be "active" (requires a reset in next frame)
721 for( std::set<Node*>::iterator iter = mImpl->activeDisconnectedNodes.begin(); mImpl->activeDisconnectedNodes.end() != iter; iter = mImpl->activeDisconnectedNodes.begin() )
724 node->ResetToBaseValues( bufferIndex );
725 node->SetActive( false );
727 // Move everything from activeDisconnectedNodes to disconnectedNodes (no need to reset again)
728 mImpl->activeDisconnectedNodes.erase( iter );
729 mImpl->disconnectedNodes.insert( node );
732 // Reset system-level render-task list properties to base values
733 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
735 for (RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
737 (*iter)->ResetToBaseValues( bufferIndex );
740 // Reset render-task list properties to base values.
741 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
743 for (RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
745 (*iter)->ResetToBaseValues( bufferIndex );
748 // Reset custom object properties to base values
749 for (OwnerContainer<PropertyOwner*>::Iterator iter = mImpl->customObjects.Begin(); iter != mImpl->customObjects.End(); ++iter)
751 (*iter)->ResetToBaseValues( bufferIndex );
754 mImpl->materials.ResetToBaseValues( bufferIndex );
755 mImpl->geometries.ResetToBaseValues( bufferIndex );
756 mImpl->propertyBuffers.ResetToBaseValues( bufferIndex );
757 mImpl->samplers.ResetToBaseValues( bufferIndex );
760 // Reset animatable shader properties to base values
761 for (ShaderIter iter = mImpl->shaders.Begin(); iter != mImpl->shaders.End(); ++iter)
763 (*iter)->ResetToBaseValues( bufferIndex );
766 PERF_MONITOR_END(PerformanceMonitor::RESET_PROPERTIES);
769 bool UpdateManager::ProcessGestures( unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds )
771 bool gestureUpdated( false );
773 // constrain gestures... (in construction order)
774 GestureContainer& gestures = mImpl->gestures;
776 for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
778 PanGesture& gesture = **iter;
779 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
780 gestureUpdated |= gesture.UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
783 return gestureUpdated;
786 void UpdateManager::Animate( float elapsedSeconds )
788 PERF_MONITOR_START(PerformanceMonitor::ANIMATE_NODES);
790 AnimationContainer &animations = mImpl->animations;
791 AnimationIter iter = animations.Begin();
792 while ( iter != animations.End() )
794 Animation* animation = *iter;
795 bool finished = animation->Update(mSceneGraphBuffers.GetUpdateBufferIndex(), elapsedSeconds);
797 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
799 // Remove animations that had been destroyed but were still waiting for an update
800 if (animation->GetState() == Animation::Destroyed)
802 iter = animations.Erase(iter);
810 if ( mImpl->animationFinishedDuringUpdate )
812 // The application should be notified by NotificationManager, in another thread
813 mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationFinishedNotifier );
816 PERF_MONITOR_END(PerformanceMonitor::ANIMATE_NODES);
819 void UpdateManager::ApplyConstraints()
821 PERF_MONITOR_START(PerformanceMonitor::APPLY_CONSTRAINTS);
823 BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
825 // constrain custom objects... (in construction order)
826 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
828 const OwnerContainer< PropertyOwner* >::Iterator endIter = customObjects.End();
829 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); endIter != iter; ++iter )
831 PropertyOwner& object = **iter;
832 ConstrainPropertyOwner( object, bufferIndex );
835 // constrain nodes... (in Depth First traversal order)
838 ConstrainNodes( *(mImpl->root), bufferIndex );
841 if ( mImpl->systemLevelRoot )
843 ConstrainNodes( *(mImpl->systemLevelRoot), bufferIndex );
846 // constrain other property-owners after nodes as they are more likely to depend on a node's
847 // current frame property than vice versa. They tend to be final constraints (no further
848 // constraints depend on their properties)
849 // e.g. ShaderEffect uniform a function of Actor's position.
850 // Mesh vertex a function of Actor's position or world position.
852 // TODO: refactor this code (and reset nodes) as these are all just lists of property-owners
853 // they can be all processed in a super-list of property-owners.
855 // Constrain system-level render-tasks
856 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
858 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter )
860 RenderTask& task = **iter;
861 ConstrainPropertyOwner( task, bufferIndex );
864 // Constrain render-tasks
865 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
867 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter )
869 RenderTask& task = **iter;
870 ConstrainPropertyOwner( task, bufferIndex );
873 // Constrain Materials and geometries
874 mImpl->materials.ConstrainObjects( bufferIndex );
875 mImpl->geometries.ConstrainObjects( bufferIndex );
876 mImpl->samplers.ConstrainObjects( bufferIndex );
877 mImpl->propertyBuffers.ConstrainObjects( bufferIndex );
879 // constrain shaders... (in construction order)
880 ShaderContainer& shaders = mImpl->shaders;
882 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
884 Shader& shader = **iter;
885 ConstrainPropertyOwner( shader, bufferIndex );
888 PERF_MONITOR_END(PerformanceMonitor::APPLY_CONSTRAINTS);
891 void UpdateManager::ProcessPropertyNotifications()
893 PropertyNotificationContainer ¬ifications = mImpl->propertyNotifications;
894 PropertyNotificationIter iter = notifications.Begin();
896 BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
898 while ( iter != notifications.End() )
900 PropertyNotification* notification = *iter;
901 bool valid = notification->Check( bufferIndex );
904 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
910 void UpdateManager::UpdateNodes()
912 mImpl->nodeDirtyFlags = NothingFlag;
919 PERF_MONITOR_START( PerformanceMonitor::UPDATE_NODES );
921 // Prepare resources, update shaders, update attachments, for each node
922 // And add the renderers to the sorted layers. Start from root, which is also a layer
923 mImpl->nodeDirtyFlags = UpdateNodesAndAttachments( *( mImpl->root ),
924 mSceneGraphBuffers.GetUpdateBufferIndex(),
925 mImpl->resourceManager,
926 mImpl->renderQueue );
928 if ( mImpl->systemLevelRoot )
930 mImpl->nodeDirtyFlags |= UpdateNodesAndAttachments( *( mImpl->systemLevelRoot ),
931 mSceneGraphBuffers.GetUpdateBufferIndex(),
932 mImpl->resourceManager,
933 mImpl->renderQueue );
936 PERF_MONITOR_END( PerformanceMonitor::UPDATE_NODES );
939 unsigned int UpdateManager::Update( float elapsedSeconds,
940 unsigned int lastVSyncTimeMilliseconds,
941 unsigned int nextVSyncTimeMilliseconds )
943 PERF_MONITOR_END(PerformanceMonitor::FRAME_RATE); // Mark the End of the last frame
944 PERF_MONITOR_NEXT_FRAME(); // Prints out performance info for the last frame (if enabled)
945 PERF_MONITOR_START(PerformanceMonitor::FRAME_RATE); // Mark the start of this current frame
947 // Measure the time spent in UpdateManager::Update
948 PERF_MONITOR_START(PerformanceMonitor::UPDATE);
950 BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
952 // Update the frame time delta on the render thread.
953 mImpl->renderManager.SetFrameDeltaTime(elapsedSeconds);
955 // 1) Clear nodes/resources which were previously discarded
956 mImpl->discardQueue.Clear( bufferIndex );
958 // 2) Grab any loaded resources
959 bool resourceChanged = mImpl->resourceManager.UpdateCache( bufferIndex );
961 // 3) Process Touches & Gestures
962 mImpl->touchResampler.Update();
963 const bool gestureUpdated = ProcessGestures( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
965 const bool updateScene = // The scene-graph requires an update if..
966 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
967 IsAnimationRunning() || // ..at least one animation is running OR
968 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
969 resourceChanged || // ..one or more resources were updated/changed OR
970 gestureUpdated; // ..a gesture property was updated
972 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
973 // values if the scene was updated in the previous frame.
974 if( updateScene || mImpl->previousUpdateScene )
976 // 4) Reset properties from the previous update
980 // 5) Process the queued scene messages
981 mImpl->messageQueue.ProcessMessages();
983 // 6) Post Process Ids of resources updated by renderer
984 mImpl->resourceManager.PostProcessResources( bufferIndex );
986 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
987 // renderer lists if the scene was updated in the previous frame.
988 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
989 if( updateScene || mImpl->previousUpdateScene )
992 Animate( elapsedSeconds );
994 // 8) Apply Constraints
997 // 9) Check Property Notifications
998 ProcessPropertyNotifications();
1000 // 10) Clear the lists of renderable-attachments from the previous update
1001 ClearRenderables( mImpl->sortedLayers );
1002 ClearRenderables( mImpl->systemLevelSortedLayers );
1004 // 11) Update node hierarchy and perform sorting / culling.
1005 // This will populate each Layer with a list of renderers which are ready.
1008 // 12) Prepare for the next render
1009 PERF_MONITOR_START(PerformanceMonitor::PREPARE_RENDERABLES);
1011 PrepareRenderables( bufferIndex, mImpl->sortedLayers );
1012 PrepareRenderables( bufferIndex, mImpl->systemLevelSortedLayers );
1013 PERF_MONITOR_END(PerformanceMonitor::PREPARE_RENDERABLES);
1015 PERF_MONITOR_START(PerformanceMonitor::PROCESS_RENDER_TASKS);
1017 // 14) Process the RenderTasks; this creates the instructions for rendering the next frame.
1018 // reset the update buffer index and make sure there is enough room in the instruction container
1019 mImpl->renderInstructions.ResetAndReserve( mSceneGraphBuffers.GetUpdateBufferIndex(),
1020 mImpl->taskList.GetTasks().Count() + mImpl->systemLevelTaskList.GetTasks().Count() );
1022 if ( NULL != mImpl->root )
1024 ProcessRenderTasks( bufferIndex,
1025 mImpl->completeStatusManager,
1028 mImpl->sortedLayers,
1029 mImpl->renderSortingHelper,
1030 mImpl->renderInstructions );
1032 // Process the system-level RenderTasks last
1033 if ( NULL != mImpl->systemLevelRoot )
1035 ProcessRenderTasks( bufferIndex,
1036 mImpl->completeStatusManager,
1037 mImpl->systemLevelTaskList,
1038 *mImpl->systemLevelRoot,
1039 mImpl->systemLevelSortedLayers,
1040 mImpl->renderSortingHelper,
1041 mImpl->renderInstructions );
1046 // check the countdown and notify (note, at the moment this is only done for normal tasks, not for systemlevel tasks)
1047 bool doRenderOnceNotify = false;
1048 mImpl->renderTaskWaiting = false;
1049 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
1050 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(), endIter = tasks.End();
1051 endIter != iter; ++iter )
1053 RenderTask& renderTask(*(*iter));
1055 renderTask.UpdateState();
1057 if( renderTask.IsWaitingToRender() &&
1058 renderTask.ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
1060 mImpl->renderTaskWaiting = true; // keep update/render threads alive
1063 if( renderTask.HasRendered() )
1065 doRenderOnceNotify = true;
1069 if( doRenderOnceNotify )
1071 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
1072 mImpl->notificationManager.QueueCompleteNotification( mImpl->taskList.GetCompleteNotificationInterface() );
1075 PERF_MONITOR_END(PerformanceMonitor::PROCESS_RENDER_TASKS);
1077 // Macro is undefined in release build.
1078 SNAPSHOT_NODE_LOGGING;
1080 // A ResetProperties() may be required in the next frame
1081 mImpl->previousUpdateScene = updateScene;
1083 // Check whether further updates are required
1084 unsigned int keepUpdating = KeepUpdatingCheck( elapsedSeconds );
1086 #ifdef PERFORMANCE_MONITOR_ENABLED
1087 // Always keep rendering when measuring FPS
1088 keepUpdating |= KeepUpdating::MONITORING_PERFORMANCE;
1091 // The update has finished; swap the double-buffering indices
1092 mSceneGraphBuffers.Swap();
1094 // tell the update manager that we're done so the queue can be given to event thread
1095 mImpl->notificationManager.UpdateCompleted();
1097 PERF_MONITOR_END(PerformanceMonitor::UPDATE);
1099 return keepUpdating;
1102 unsigned int UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
1104 // Update the duration set via Stage::KeepRendering()
1105 if ( mImpl->keepRenderingSeconds > 0.0f )
1107 mImpl->keepRenderingSeconds -= elapsedSeconds;
1110 unsigned int keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
1112 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
1113 // Keep updating until no messages are received and no animations are running.
1114 // If an animation has just finished, update at least once more for Discard end-actions.
1115 // No need to check for renderQueue as there is always a render after update and if that
1116 // render needs another update it will tell the adaptor to call update again
1118 if ( mImpl->keepRenderingSeconds > 0.0f )
1120 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
1123 if ( IsAnimationRunning() ||
1124 mImpl->animationFinishedDuringUpdate )
1126 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
1129 if ( mImpl->renderTaskWaiting )
1131 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
1134 return keepUpdatingRequest;
1137 void UpdateManager::SetBackgroundColor( const Vector4& color )
1139 typedef MessageValue1< RenderManager, Vector4 > DerivedType;
1141 // Reserve some memory inside the render queue
1142 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1144 // Construct message in the render queue memory; note that delete should not be called on the return value
1145 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
1148 void UpdateManager::SetDefaultSurfaceRect( const Rect<int>& rect )
1150 typedef MessageValue1< RenderManager, Rect<int> > DerivedType;
1152 // Reserve some memory inside the render queue
1153 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1155 // Construct message in the render queue memory; note that delete should not be called on the return value
1156 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1159 void UpdateManager::KeepRendering( float durationSeconds )
1161 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1164 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, bool systemLevel )
1168 // just copy the vector of pointers
1169 mImpl->sortedLayers = layers;
1173 mImpl->systemLevelSortedLayers = layers;
1177 } // namespace SceneGraph
1179 } // namespace Internal