2 * Copyright (c) 2015 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>
24 #include <dali/devel-api/common/owner-container.h>
25 #include <dali/devel-api/threading/mutex.h>
27 #include <dali/integration-api/core.h>
28 #include <dali/integration-api/render-controller.h>
29 #include <dali/internal/common/shader-data.h>
30 #include <dali/integration-api/debug.h>
32 #include <dali/internal/common/core-impl.h>
33 #include <dali/internal/common/message.h>
35 #include <dali/internal/event/common/notification-manager.h>
36 #include <dali/internal/event/common/property-notification-impl.h>
37 #include <dali/internal/event/common/property-notifier.h>
38 #include <dali/internal/event/effects/shader-factory.h>
40 #include <dali/internal/update/animation/scene-graph-animator.h>
41 #include <dali/internal/update/animation/scene-graph-animation.h>
42 #include <dali/internal/update/common/discard-queue.h>
43 #include <dali/internal/update/common/scene-graph-buffers.h>
44 #include <dali/internal/update/controllers/render-message-dispatcher.h>
45 #include <dali/internal/update/controllers/scene-controller-impl.h>
46 #include <dali/internal/update/gestures/scene-graph-pan-gesture.h>
47 #include <dali/internal/update/manager/object-owner-container.h>
48 #include <dali/internal/update/manager/process-render-tasks.h>
49 #include <dali/internal/update/manager/sorted-layers.h>
50 #include <dali/internal/update/manager/update-algorithms.h>
51 #include <dali/internal/update/manager/update-manager-debug.h>
52 #include <dali/internal/update/node-attachments/scene-graph-camera-attachment.h>
53 #include <dali/internal/update/nodes/node.h>
54 #include <dali/internal/update/nodes/scene-graph-layer.h>
55 #include <dali/internal/update/queue/update-message-queue.h>
56 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
57 #include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
58 #include <dali/internal/update/rendering/scene-graph-material.h>
59 #include <dali/internal/update/rendering/scene-graph-geometry.h>
60 #include <dali/internal/update/resources/resource-manager.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/gl-resources/texture-cache.h>
67 #include <dali/internal/render/shaders/scene-graph-shader.h>
68 #include <dali/internal/render/renderers/render-sampler.h>
70 // Un-comment to enable node tree debug logging
71 //#define NODE_TREE_LOGGING 1
73 #if ( defined( DEBUG_ENABLED ) && defined( NODE_TREE_LOGGING ) )
74 #define SNAPSHOT_NODE_LOGGING \
75 const int FRAME_COUNT_TRIGGER = 16;\
76 if( mImpl->frameCounter >= FRAME_COUNT_TRIGGER )\
78 if ( NULL != mImpl->root )\
80 mImpl->frameCounter = 0;\
81 PrintNodeTree( *mImpl->root, mSceneGraphBuffers.GetUpdateBufferIndex(), "" );\
84 mImpl->frameCounter++;
86 #define SNAPSHOT_NODE_LOGGING
89 #if defined(DEBUG_ENABLED)
90 extern Debug::Filter* gRenderTaskLogFilter;
94 using namespace Dali::Integration;
95 using Dali::Internal::Update::MessageQueue;
109 void DestroyNodeSet( std::set<Node*>& nodeSet )
111 for( std::set<Node*>::iterator iter = nodeSet.begin(); iter != nodeSet.end(); ++iter )
115 // Call Node::OnDestroy as each node is destroyed
125 typedef OwnerContainer< Shader* > ShaderContainer;
126 typedef ShaderContainer::Iterator ShaderIter;
127 typedef ShaderContainer::ConstIterator ShaderConstIter;
129 typedef std::vector<Internal::ShaderDataPtr> ShaderDataBinaryQueue;
131 typedef OwnerContainer<PanGesture*> GestureContainer;
132 typedef GestureContainer::Iterator GestureIter;
133 typedef GestureContainer::ConstIterator GestureConstIter;
137 * Structure to contain UpdateManager internal data
139 struct UpdateManager::Impl
141 Impl( NotificationManager& notificationManager,
142 CompleteNotificationInterface& animationFinishedNotifier,
143 PropertyNotifier& propertyNotifier,
144 ResourceManager& resourceManager,
145 DiscardQueue& discardQueue,
146 RenderController& renderController,
147 RenderManager& renderManager,
148 RenderQueue& renderQueue,
149 TextureCache& textureCache,
150 TouchResampler& touchResampler,
151 SceneGraphBuffers& sceneGraphBuffers )
153 renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ),
154 notificationManager( notificationManager ),
155 animationFinishedNotifier( animationFinishedNotifier ),
156 propertyNotifier( propertyNotifier ),
158 resourceManager( resourceManager ),
159 discardQueue( discardQueue ),
160 renderController( renderController ),
161 sceneController( NULL ),
162 renderManager( renderManager ),
163 renderQueue( renderQueue ),
164 renderInstructions( renderManager.GetRenderInstructionContainer() ),
165 touchResampler( touchResampler ),
166 backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
167 taskList( renderMessageDispatcher, resourceManager ),
168 systemLevelTaskList( renderMessageDispatcher, resourceManager ),
170 systemLevelRoot( NULL ),
171 renderers( sceneGraphBuffers, discardQueue ),
172 geometries( sceneGraphBuffers, discardQueue ),
173 materials( sceneGraphBuffers, discardQueue ),
174 messageQueue( renderController, sceneGraphBuffers ),
175 keepRenderingSeconds( 0.0f ),
176 animationFinishedDuringUpdate( false ),
177 nodeDirtyFlags( TransformFlag ), // set to TransformFlag to ensure full update the first time through Update()
178 previousUpdateScene( false ),
180 renderSortingHelper(),
181 renderTaskWaiting( false )
183 sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue, textureCache );
185 renderers.SetSceneController( *sceneController );
186 geometries.SetSceneController( *sceneController );
187 materials.SetSceneController( *sceneController );
192 // Disconnect render tasks from nodes, before destroying the nodes
193 RenderTaskList::RenderTaskContainer& tasks = taskList.GetTasks();
194 for (RenderTaskList::RenderTaskContainer::Iterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
196 (*iter)->SetSourceNode( NULL );
198 // ..repeat for system level RenderTasks
199 RenderTaskList::RenderTaskContainer& systemLevelTasks = systemLevelTaskList.GetTasks();
200 for (RenderTaskList::RenderTaskContainer::Iterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
202 (*iter)->SetSourceNode( NULL );
205 // UpdateManager owns the Nodes
206 DestroyNodeSet( activeDisconnectedNodes );
207 DestroyNodeSet( connectedNodes );
208 DestroyNodeSet( disconnectedNodes );
210 // If there is root, reset it, otherwise do nothing as rendering was never started
219 if( systemLevelRoot )
221 systemLevelRoot->OnDestroy();
223 delete systemLevelRoot;
224 systemLevelRoot = NULL;
227 sceneController->GetTextureCache().SetBufferIndices(NULL); // TODO - Remove
228 delete sceneController;
231 SceneGraphBuffers sceneGraphBuffers; ///< Used to keep track of which buffers are being written or read
232 RenderMessageDispatcher renderMessageDispatcher; ///< Used for passing messages to the render-thread
233 NotificationManager& notificationManager; ///< Queues notification messages for the event-thread.
234 CompleteNotificationInterface& animationFinishedNotifier; ///< Provides notification to applications when animations are finished.
235 PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
236 ShaderSaver* shaderSaver; ///< Saves shader binaries.
237 ResourceManager& resourceManager; ///< resource manager
238 DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
239 RenderController& renderController; ///< render controller
240 SceneControllerImpl* sceneController; ///< scene controller
241 RenderManager& renderManager; ///< This is responsible for rendering the results of each "update"
242 RenderQueue& renderQueue; ///< Used to queue messages for the next render
243 RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions
244 TouchResampler& touchResampler; ///< Used to resample touch events on every update.
246 Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
248 RenderTaskList taskList; ///< The list of scene graph render-tasks
249 RenderTaskList systemLevelTaskList; ///< Separate render-tasks for system-level content
251 Layer* root; ///< The root node (root is a layer)
252 Layer* systemLevelRoot; ///< A separate root-node for system-level content
253 std::set< Node* > activeDisconnectedNodes; ///< A container of new or modified nodes (without parent) owned by UpdateManager
254 std::set< Node* > connectedNodes; ///< A container of connected (with parent) nodes owned by UpdateManager
255 std::set< Node* > disconnectedNodes; ///< A container of inactive disconnected nodes (without parent) owned by UpdateManager
257 SortedLayerPointers sortedLayers; ///< A container of Layer pointers sorted by depth
258 SortedLayerPointers systemLevelSortedLayers; ///< A separate container of system-level Layers
260 OwnerContainer< PropertyOwner* > customObjects; ///< A container of owned objects (with custom properties)
262 AnimationContainer animations; ///< A container of owned animations
263 PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
265 ObjectOwnerContainer<Renderer> renderers;
266 ObjectOwnerContainer<Geometry> geometries; ///< A container of geometries
267 ObjectOwnerContainer<Material> materials; ///< A container of materials
269 ShaderContainer shaders; ///< A container of owned shaders
271 MessageQueue messageQueue; ///< The messages queued from the event-thread
272 ShaderDataBinaryQueue renderCompiledShaders; ///< Shaders compiled on Render thread are inserted here for update thread to pass on to event thread.
273 ShaderDataBinaryQueue updateCompiledShaders; ///< Shaders to be sent from Update to Event
274 Mutex compiledShaderMutex; ///< lock to ensure no corruption on the renderCompiledShaders
276 float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
277 bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
279 int nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
280 bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
282 int frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
283 RendererSortingHelper renderSortingHelper; ///< helper used to sort transparent renderers
285 GestureContainer gestures; ///< A container of owned gesture detectors
286 bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
289 UpdateManager::UpdateManager( NotificationManager& notificationManager,
290 CompleteNotificationInterface& animationFinishedNotifier,
291 PropertyNotifier& propertyNotifier,
292 ResourceManager& resourceManager,
293 DiscardQueue& discardQueue,
294 RenderController& controller,
295 RenderManager& renderManager,
296 RenderQueue& renderQueue,
297 TextureCache& textureCache,
298 TouchResampler& touchResampler )
301 mImpl = new Impl( notificationManager,
302 animationFinishedNotifier,
311 mSceneGraphBuffers );
313 textureCache.SetBufferIndices( &mSceneGraphBuffers );
316 UpdateManager::~UpdateManager()
321 void UpdateManager::InstallRoot( SceneGraph::Layer* layer, bool systemLevel )
323 DALI_ASSERT_DEBUG( layer->IsLayer() );
324 DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
328 DALI_ASSERT_DEBUG( mImpl->root == NULL && "Root Node already installed" );
333 DALI_ASSERT_DEBUG( mImpl->systemLevelRoot == NULL && "System-level Root Node already installed" );
334 mImpl->systemLevelRoot = layer;
337 layer->SetRoot(true);
340 void UpdateManager::AddNode( Node* node )
342 DALI_ASSERT_ALWAYS( NULL != node );
343 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
345 mImpl->activeDisconnectedNodes.insert( node ); // Takes ownership of node
348 void UpdateManager::ConnectNode( Node* parent, Node* node )
350 DALI_ASSERT_ALWAYS( NULL != parent );
351 DALI_ASSERT_ALWAYS( NULL != node );
352 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
354 // Move from active/disconnectedNodes to connectedNodes
355 std::set<Node*>::size_type removed = mImpl->activeDisconnectedNodes.erase( node );
358 removed = mImpl->disconnectedNodes.erase( node );
359 DALI_ASSERT_ALWAYS( removed );
361 mImpl->connectedNodes.insert( node );
363 node->SetActive( true );
365 parent->ConnectChild( node );
368 void UpdateManager::DisconnectNode( Node* node )
370 Node* parent = node->GetParent();
371 DALI_ASSERT_ALWAYS( NULL != parent );
372 parent->SetDirtyFlag( ChildDeletedFlag ); // make parent dirty so that render items dont get reused
374 // Move from connectedNodes to activeDisconnectedNodes (reset properties next frame)
375 parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node, mImpl->connectedNodes, mImpl->activeDisconnectedNodes );
378 void UpdateManager::SetNodeActive( Node* node )
380 DALI_ASSERT_ALWAYS( NULL != node );
381 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
383 // Move from disconnectedNodes to activeDisconnectedNodes (reset properties next frame)
384 std::set<Node*>::size_type removed = mImpl->disconnectedNodes.erase( node );
385 DALI_ASSERT_ALWAYS( removed );
386 mImpl->activeDisconnectedNodes.insert( node );
388 node->SetActive( true );
391 void UpdateManager::DestroyNode( Node* node )
393 DALI_ASSERT_ALWAYS( NULL != node );
394 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
396 // Transfer ownership from new/disconnectedNodes to the discard queue
397 // This keeps the nodes alive, until the render-thread has finished with them
398 std::set<Node*>::size_type removed = mImpl->activeDisconnectedNodes.erase( node );
401 removed = mImpl->disconnectedNodes.erase( node );
402 DALI_ASSERT_ALWAYS( removed );
404 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
406 // Notify the Node about impending destruction
410 //@todo MESH_REWORK Extend to allow arbitrary scene objects to connect to each other
411 void UpdateManager::AttachToNode( Node* node, NodeAttachment* attachment )
413 DALI_ASSERT_DEBUG( node != NULL );
414 DALI_ASSERT_DEBUG( attachment != NULL );
416 // attach node to attachment first so that parent is known by the time attachment is connected
417 node->Attach( *attachment ); // node takes ownership
420 void UpdateManager::AddObject( PropertyOwner* object )
422 DALI_ASSERT_DEBUG( NULL != object );
424 mImpl->customObjects.PushBack( object );
427 void UpdateManager::RemoveObject( PropertyOwner* object )
429 DALI_ASSERT_DEBUG( NULL != object );
431 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
433 // Find the object and destroy it
434 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); iter != customObjects.End(); ++iter )
436 PropertyOwner* current = *iter;
437 if ( current == object )
439 customObjects.Erase( iter );
444 // Should not reach here
445 DALI_ASSERT_DEBUG(false);
448 void UpdateManager::AddAnimation( Animation* animation )
450 mImpl->animations.PushBack( animation );
453 void UpdateManager::StopAnimation( Animation* animation )
455 DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
457 bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
459 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
462 void UpdateManager::RemoveAnimation( Animation* animation )
464 DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
466 animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
468 DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
471 bool UpdateManager::IsAnimationRunning() const
473 bool isRunning(false);
474 AnimationContainer& animations = mImpl->animations;
476 // Find any animation that isn't stopped or paused
478 const AnimationIter endIter = animations.End();
479 for ( AnimationIter iter = animations.Begin(); !isRunning && iter != endIter; ++iter )
481 const Animation::State state = (*iter)->GetState();
483 if (state != Animation::Stopped &&
484 state != Animation::Paused)
493 void UpdateManager::AddPropertyNotification( PropertyNotification* propertyNotification )
495 mImpl->propertyNotifications.PushBack( propertyNotification );
498 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
500 PropertyNotificationContainer &propertyNotifications = mImpl->propertyNotifications;
501 PropertyNotificationIter iter = propertyNotifications.Begin();
503 while ( iter != propertyNotifications.End() )
505 if( *iter == propertyNotification )
507 propertyNotifications.Erase(iter);
514 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
516 DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
517 propertyNotification->SetNotifyMode( notifyMode );
520 ObjectOwnerContainer<Geometry>& UpdateManager::GetGeometryOwner()
522 return mImpl->geometries;
525 ObjectOwnerContainer<Renderer>& UpdateManager::GetRendererOwner()
527 return mImpl->renderers;
531 ObjectOwnerContainer<Material>& UpdateManager::GetMaterialOwner()
533 return mImpl->materials;
536 void UpdateManager::AddShader( Shader* shader )
538 DALI_ASSERT_DEBUG( NULL != shader );
540 if( mImpl->shaders.Count() == 0 )
542 // the first added shader becomes our default shader
543 // Construct message in the render queue memory; note that delete should not be called on the return value
544 typedef MessageValue1< RenderManager, Shader* > DerivedType;
546 // Reserve some memory inside the render queue
547 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
549 // Construct message in the render queue memory; note that delete should not be called on the return value
550 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultShader, shader );
553 mImpl->shaders.PushBack( shader );
555 // Allows the shader to dispatch texture requests to the cache
556 shader->Initialize( mImpl->renderQueue, mImpl->sceneController->GetTextureCache() );
559 void UpdateManager::RemoveShader( Shader* shader )
561 DALI_ASSERT_DEBUG(shader != NULL);
563 ShaderContainer& shaders = mImpl->shaders;
565 // Find the shader and destroy it
566 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
568 Shader& current = **iter;
569 if ( ¤t == shader )
571 // Transfer ownership to the discard queue
572 // This keeps the shader alive, until the render-thread has finished with it
573 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), shaders.Release( iter ) );
578 // Should not reach here
579 DALI_ASSERT_DEBUG(false);
582 void UpdateManager::SetShaderProgram( Shader* shader,
583 Internal::ShaderDataPtr shaderData, bool modifiesGeometry )
588 typedef MessageValue3< Shader, Internal::ShaderDataPtr, ProgramCache*, bool> DerivedType;
590 // Reserve some memory inside the render queue
591 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
593 // Construct message in the render queue memory; note that delete should not be called on the return value
594 new (slot) DerivedType( shader, &Shader::SetProgram, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
598 void UpdateManager::SaveBinary( Internal::ShaderDataPtr shaderData )
600 DALI_ASSERT_DEBUG( shaderData && "No NULL shader data pointers please." );
601 DALI_ASSERT_DEBUG( shaderData->GetBufferSize() > 0 && "Shader binary empty so nothing to save." );
603 // lock as update might be sending previously compiled shaders to event thread
604 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
605 mImpl->renderCompiledShaders.push_back( shaderData );
609 RenderTaskList* UpdateManager::GetRenderTaskList( bool systemLevel )
613 // copy the list, this is only likely to happen once in application life cycle
614 return &(mImpl->taskList);
618 // copy the list, this is only likely to happen once in application life cycle
619 return &(mImpl->systemLevelTaskList);
623 void UpdateManager::AddGesture( PanGesture* gesture )
625 DALI_ASSERT_DEBUG( NULL != gesture );
627 mImpl->gestures.PushBack( gesture );
630 void UpdateManager::RemoveGesture( PanGesture* gesture )
632 DALI_ASSERT_DEBUG( gesture != NULL );
634 GestureContainer& gestures = mImpl->gestures;
636 // Find the gesture and destroy it
637 for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
639 PanGesture& current = **iter;
640 if ( ¤t == gesture )
642 mImpl->gestures.Erase( iter );
646 // Should not reach here
647 DALI_ASSERT_DEBUG(false);
650 unsigned int* UpdateManager::ReserveMessageSlot( std::size_t size, bool updateScene )
652 return mImpl->messageQueue.ReserveMessageSlot( size, updateScene );
655 void UpdateManager::EventProcessingStarted()
657 mImpl->messageQueue.EventProcessingStarted();
660 bool UpdateManager::FlushQueue()
662 return mImpl->messageQueue.FlushQueue();
665 void UpdateManager::ResetProperties( BufferIndex bufferIndex )
667 // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
668 mImpl->animationFinishedDuringUpdate = false;
670 // Animated properties have to be reset to their original value each frame
672 // Reset root properties
675 mImpl->root->ResetToBaseValues( bufferIndex );
677 if ( mImpl->systemLevelRoot )
679 mImpl->systemLevelRoot->ResetToBaseValues( bufferIndex );
682 // Reset the Connected Nodes
683 const std::set<Node*>::iterator endIter = mImpl->connectedNodes.end();
684 for( std::set<Node*>::iterator iter = mImpl->connectedNodes.begin(); endIter != iter; ++iter )
686 (*iter)->ResetToBaseValues( bufferIndex );
689 // If a Node is disconnected, it may still be "active" (requires a reset in next frame)
690 for( std::set<Node*>::iterator iter = mImpl->activeDisconnectedNodes.begin(); mImpl->activeDisconnectedNodes.end() != iter; iter = mImpl->activeDisconnectedNodes.begin() )
693 node->ResetToBaseValues( bufferIndex );
694 node->SetActive( false );
696 // Move everything from activeDisconnectedNodes to disconnectedNodes (no need to reset again)
697 mImpl->activeDisconnectedNodes.erase( iter );
698 mImpl->disconnectedNodes.insert( node );
701 // Reset system-level render-task list properties to base values
702 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
704 for (RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
706 (*iter)->ResetToBaseValues( bufferIndex );
709 // Reset render-task list properties to base values.
710 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
712 for (RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
714 (*iter)->ResetToBaseValues( bufferIndex );
717 // Reset custom object properties to base values
718 for (OwnerContainer<PropertyOwner*>::Iterator iter = mImpl->customObjects.Begin(); iter != mImpl->customObjects.End(); ++iter)
720 (*iter)->ResetToBaseValues( bufferIndex );
723 mImpl->materials.ResetToBaseValues( bufferIndex );
724 mImpl->geometries.ResetToBaseValues( bufferIndex );
725 mImpl->renderers.ResetToBaseValues( bufferIndex );
728 // Reset animatable shader properties to base values
729 for (ShaderIter iter = mImpl->shaders.Begin(); iter != mImpl->shaders.End(); ++iter)
731 (*iter)->ResetToBaseValues( bufferIndex );
735 bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds )
737 bool gestureUpdated( false );
739 // constrain gestures... (in construction order)
740 GestureContainer& gestures = mImpl->gestures;
742 for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
744 PanGesture& gesture = **iter;
745 gesture.ResetToBaseValues( bufferIndex ); // Needs to be done every time as gesture data is written directly to an update-buffer rather than via a message
746 gestureUpdated |= gesture.UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
749 return gestureUpdated;
752 void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
754 AnimationContainer &animations = mImpl->animations;
755 AnimationIter iter = animations.Begin();
756 while ( iter != animations.End() )
758 Animation* animation = *iter;
759 bool finished = animation->Update( bufferIndex, elapsedSeconds );
761 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
763 // Remove animations that had been destroyed but were still waiting for an update
764 if (animation->GetState() == Animation::Destroyed)
766 iter = animations.Erase(iter);
774 if ( mImpl->animationFinishedDuringUpdate )
776 // The application should be notified by NotificationManager, in another thread
777 mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationFinishedNotifier );
781 void UpdateManager::ApplyConstraints( BufferIndex bufferIndex )
783 // constrain custom objects... (in construction order)
784 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
786 const OwnerContainer< PropertyOwner* >::Iterator endIter = customObjects.End();
787 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); endIter != iter; ++iter )
789 PropertyOwner& object = **iter;
790 ConstrainPropertyOwner( object, bufferIndex );
793 // constrain nodes... (in Depth First traversal order)
796 ConstrainNodes( *(mImpl->root), bufferIndex );
799 if ( mImpl->systemLevelRoot )
801 ConstrainNodes( *(mImpl->systemLevelRoot), bufferIndex );
804 // constrain other property-owners after nodes as they are more likely to depend on a node's
805 // current frame property than vice versa. They tend to be final constraints (no further
806 // constraints depend on their properties)
807 // e.g. ShaderEffect uniform a function of Actor's position.
808 // Mesh vertex a function of Actor's position or world position.
810 // Constrain system-level render-tasks
811 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
813 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter )
815 RenderTask& task = **iter;
816 ConstrainPropertyOwner( task, bufferIndex );
819 // Constrain render-tasks
820 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
822 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter )
824 RenderTask& task = **iter;
825 ConstrainPropertyOwner( task, bufferIndex );
828 // Constrain Materials and geometries
829 mImpl->materials.ConstrainObjects( bufferIndex );
830 mImpl->geometries.ConstrainObjects( bufferIndex );
831 mImpl->renderers.ConstrainObjects( bufferIndex );
833 // constrain shaders... (in construction order)
834 ShaderContainer& shaders = mImpl->shaders;
836 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
838 Shader& shader = **iter;
839 ConstrainPropertyOwner( shader, bufferIndex );
843 void UpdateManager::ProcessPropertyNotifications( BufferIndex bufferIndex )
845 PropertyNotificationContainer ¬ifications = mImpl->propertyNotifications;
846 PropertyNotificationIter iter = notifications.Begin();
848 while ( iter != notifications.End() )
850 PropertyNotification* notification = *iter;
851 bool valid = notification->Check( bufferIndex );
854 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
860 void UpdateManager::PrepareMaterials()
862 ObjectOwnerContainer<Material>::Iterator iter = mImpl->materials.GetObjectContainer().Begin();
863 const ObjectOwnerContainer<Material>::Iterator end = mImpl->materials.GetObjectContainer().End();
864 for( ; iter != end; ++iter )
866 (*iter)->Prepare( mImpl->resourceManager );
870 void UpdateManager::ForwardCompiledShadersToEventThread()
872 DALI_ASSERT_DEBUG( (mImpl->shaderSaver != 0) && "shaderSaver should be wired-up during startup." );
873 if( mImpl->shaderSaver )
875 // lock and swap the queues
877 // render might be attempting to send us more binaries at the same time
878 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
879 mImpl->renderCompiledShaders.swap( mImpl->updateCompiledShaders );
882 if( mImpl->updateCompiledShaders.size() > 0 )
884 ShaderSaver& factory = *mImpl->shaderSaver;
885 ShaderDataBinaryQueue::iterator i = mImpl->updateCompiledShaders.begin();
886 ShaderDataBinaryQueue::iterator end = mImpl->updateCompiledShaders.end();
887 for( ; i != end; ++i )
889 mImpl->notificationManager.QueueMessage( ShaderCompiledMessage( factory, *i ) );
891 // we don't need them in update anymore
892 mImpl->updateCompiledShaders.clear();
897 void UpdateManager::UpdateRenderers( BufferIndex bufferIndex )
899 const OwnerContainer<Renderer*>& rendererContainer( mImpl->renderers.GetObjectContainer() );
900 unsigned int rendererCount( rendererContainer.Size() );
901 for( unsigned int i(0); i<rendererCount; ++i )
903 if( rendererContainer[i]->IsReferenced() )
905 rendererContainer[i]->PrepareRender( bufferIndex );
910 void UpdateManager::UpdateNodes( BufferIndex bufferIndex )
912 mImpl->nodeDirtyFlags = NothingFlag;
919 // Prepare resources, update shaders, update attachments, for each node
920 // And add the renderers to the sorted layers. Start from root, which is also a layer
921 mImpl->nodeDirtyFlags = UpdateNodesAndAttachments( *( mImpl->root ),
923 mImpl->resourceManager,
924 mImpl->renderQueue );
926 if ( mImpl->systemLevelRoot )
928 mImpl->nodeDirtyFlags |= UpdateNodesAndAttachments( *( mImpl->systemLevelRoot ),
930 mImpl->resourceManager,
931 mImpl->renderQueue );
935 unsigned int UpdateManager::Update( float elapsedSeconds,
936 unsigned int lastVSyncTimeMilliseconds,
937 unsigned int nextVSyncTimeMilliseconds )
939 const BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
941 // 1) Clear nodes/resources which were previously discarded
942 mImpl->discardQueue.Clear( bufferIndex );
944 // 2) Grab any loaded resources
945 bool resourceChanged = mImpl->resourceManager.UpdateCache( bufferIndex );
947 // 3) Process Touches & Gestures
948 mImpl->touchResampler.Update();
949 const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
951 const bool updateScene = // The scene-graph requires an update if..
952 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
953 IsAnimationRunning() || // ..at least one animation is running OR
954 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
955 resourceChanged || // ..one or more resources were updated/changed OR
956 gestureUpdated; // ..a gesture property was updated
959 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
960 // values if the scene was updated in the previous frame.
961 if( updateScene || mImpl->previousUpdateScene )
963 // 4) Reset properties from the previous update
964 ResetProperties( bufferIndex );
967 // 5) Process the queued scene messages
968 mImpl->messageQueue.ProcessMessages( bufferIndex );
970 // 6) Post Process Ids of resources updated by renderer
971 mImpl->resourceManager.PostProcessResources( bufferIndex );
973 // 6.1) Forward compiled shader programs to event thread for saving
974 ForwardCompiledShadersToEventThread();
976 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
977 // renderer lists if the scene was updated in the previous frame.
978 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
979 if( updateScene || mImpl->previousUpdateScene )
982 Animate( bufferIndex, elapsedSeconds );
984 // 8) Apply Constraints
985 ApplyConstraints( bufferIndex );
987 // 9) Check Property Notifications
988 ProcessPropertyNotifications( bufferIndex );
990 // 10) Prepare materials
993 // 11) Clear the lists of renderable-attachments from the previous update
994 for( size_t i(0); i<mImpl->sortedLayers.size(); ++i )
996 mImpl->sortedLayers[i]->ClearRenderables();
999 for( size_t i(0); i<mImpl->systemLevelSortedLayers.size(); ++i )
1001 mImpl->systemLevelSortedLayers[i]->ClearRenderables();
1004 // 12) Update node hierarchy and perform sorting / culling.
1005 // This will populate each Layer with a list of renderers which are ready.
1006 UpdateNodes( bufferIndex );
1007 UpdateRenderers( bufferIndex );
1009 // 13) Process the RenderTasks; this creates the instructions for rendering the next frame.
1010 // reset the update buffer index and make sure there is enough room in the instruction container
1011 mImpl->renderInstructions.ResetAndReserve( bufferIndex,
1012 mImpl->taskList.GetTasks().Count() + mImpl->systemLevelTaskList.GetTasks().Count() );
1014 if ( NULL != mImpl->root )
1016 ProcessRenderTasks( bufferIndex,
1019 mImpl->sortedLayers,
1020 mImpl->renderSortingHelper,
1021 mImpl->renderInstructions );
1023 // Process the system-level RenderTasks last
1024 if ( NULL != mImpl->systemLevelRoot )
1026 ProcessRenderTasks( bufferIndex,
1027 mImpl->systemLevelTaskList,
1028 *mImpl->systemLevelRoot,
1029 mImpl->systemLevelSortedLayers,
1030 mImpl->renderSortingHelper,
1031 mImpl->renderInstructions );
1036 // check the countdown and notify (note, at the moment this is only done for normal tasks, not for systemlevel tasks)
1037 bool doRenderOnceNotify = false;
1038 mImpl->renderTaskWaiting = false;
1039 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
1040 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(), endIter = tasks.End();
1041 endIter != iter; ++iter )
1043 RenderTask& renderTask(*(*iter));
1045 renderTask.UpdateState();
1047 if( renderTask.IsWaitingToRender() &&
1048 renderTask.ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
1050 mImpl->renderTaskWaiting = true; // keep update/render threads alive
1053 if( renderTask.HasRendered() )
1055 doRenderOnceNotify = true;
1059 if( doRenderOnceNotify )
1061 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
1062 mImpl->notificationManager.QueueCompleteNotification( mImpl->taskList.GetCompleteNotificationInterface() );
1065 // Macro is undefined in release build.
1066 SNAPSHOT_NODE_LOGGING;
1068 // A ResetProperties() may be required in the next frame
1069 mImpl->previousUpdateScene = updateScene;
1071 // Check whether further updates are required
1072 unsigned int keepUpdating = KeepUpdatingCheck( elapsedSeconds );
1074 // tell the update manager that we're done so the queue can be given to event thread
1075 mImpl->notificationManager.UpdateCompleted();
1077 // The update has finished; swap the double-buffering indices
1078 mSceneGraphBuffers.Swap();
1080 return keepUpdating;
1083 unsigned int UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
1085 // Update the duration set via Stage::KeepRendering()
1086 if ( mImpl->keepRenderingSeconds > 0.0f )
1088 mImpl->keepRenderingSeconds -= elapsedSeconds;
1091 unsigned int keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
1093 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
1094 // Keep updating until no messages are received and no animations are running.
1095 // If an animation has just finished, update at least once more for Discard end-actions.
1096 // No need to check for renderQueue as there is always a render after update and if that
1097 // render needs another update it will tell the adaptor to call update again
1099 if ( mImpl->keepRenderingSeconds > 0.0f )
1101 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
1104 if ( IsAnimationRunning() ||
1105 mImpl->animationFinishedDuringUpdate )
1107 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
1110 if ( mImpl->renderTaskWaiting )
1112 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
1115 return keepUpdatingRequest;
1118 void UpdateManager::SetBackgroundColor( const Vector4& color )
1120 typedef MessageValue1< RenderManager, Vector4 > DerivedType;
1122 // Reserve some memory inside the render queue
1123 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1125 // Construct message in the render queue memory; note that delete should not be called on the return value
1126 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
1129 void UpdateManager::SetDefaultSurfaceRect( const Rect<int>& rect )
1131 typedef MessageValue1< RenderManager, Rect<int> > DerivedType;
1133 // Reserve some memory inside the render queue
1134 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1136 // Construct message in the render queue memory; note that delete should not be called on the return value
1137 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1140 void UpdateManager::KeepRendering( float durationSeconds )
1142 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1145 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, bool systemLevel )
1149 // just copy the vector of pointers
1150 mImpl->sortedLayers = layers;
1154 mImpl->systemLevelSortedLayers = layers;
1158 void UpdateManager::SetShaderSaver( ShaderSaver& upstream )
1160 mImpl->shaderSaver = &upstream;
1163 void UpdateManager::AddSampler( Render::Sampler* sampler )
1165 typedef MessageValue1< RenderManager, Render::Sampler* > DerivedType;
1167 // Reserve some memory inside the render queue
1168 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1170 // Construct message in the render queue memory; note that delete should not be called on the return value
1171 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddSampler, sampler );
1174 void UpdateManager::RemoveSampler( Render::Sampler* sampler )
1176 typedef MessageValue1< RenderManager, Render::Sampler* > DerivedType;
1178 // Reserve some memory inside the render queue
1179 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1181 // Construct message in the render queue memory; note that delete should not be called on the return value
1182 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveSampler, sampler );
1185 void UpdateManager::SetFilterMode( Render::Sampler* sampler, unsigned int minFilterMode, unsigned int magFilterMode )
1187 typedef MessageValue3< RenderManager, Render::Sampler*, unsigned int, unsigned int > DerivedType;
1189 // Reserve some memory inside the render queue
1190 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1192 // Construct message in the render queue memory; note that delete should not be called on the return value
1193 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetFilterMode, sampler, minFilterMode, magFilterMode );
1196 void UpdateManager::SetWrapMode( Render::Sampler* sampler, unsigned int uWrapMode, unsigned int vWrapMode )
1198 typedef MessageValue3< RenderManager, Render::Sampler*, unsigned int, unsigned int > DerivedType;
1200 // Reserve some memory inside the render queue
1201 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1203 // Construct message in the render queue memory; note that delete should not be called on the return value
1204 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetWrapMode, sampler, uWrapMode, vWrapMode );
1207 void UpdateManager::AddPropertyBuffer( Render::PropertyBuffer* propertyBuffer )
1209 typedef MessageValue1< RenderManager, Render::PropertyBuffer* > DerivedType;
1211 // Reserve some memory inside the render queue
1212 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1214 // Construct message in the render queue memory; note that delete should not be called on the return value
1215 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddPropertyBuffer, propertyBuffer );
1218 void UpdateManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer )
1220 typedef MessageValue1< RenderManager, Render::PropertyBuffer* > DerivedType;
1222 // Reserve some memory inside the render queue
1223 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1225 // Construct message in the render queue memory; note that delete should not be called on the return value
1226 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemovePropertyBuffer, propertyBuffer );
1229 void UpdateManager::SetPropertyBufferFormat(Render::PropertyBuffer* propertyBuffer, Render::PropertyBuffer::Format* format )
1231 typedef MessageValue2< RenderManager, Render::PropertyBuffer*, Render::PropertyBuffer::Format* > DerivedType;
1233 // Reserve some memory inside the render queue
1234 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1236 // Construct message in the render queue memory; note that delete should not be called on the return value
1237 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferFormat, propertyBuffer, format );
1240 void UpdateManager::SetPropertyBufferData(Render::PropertyBuffer* propertyBuffer, Dali::Vector<char>* data)
1242 typedef MessageValue2< RenderManager, Render::PropertyBuffer*, Dali::Vector<char>* > DerivedType;
1244 // Reserve some memory inside the render queue
1245 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1247 // Construct message in the render queue memory; note that delete should not be called on the return value
1248 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferData, propertyBuffer, data );
1251 void UpdateManager::SetPropertyBufferSize(Render::PropertyBuffer* propertyBuffer, size_t size )
1253 typedef MessageValue2< RenderManager, Render::PropertyBuffer*, size_t > DerivedType;
1255 // Reserve some memory inside the render queue
1256 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1258 // Construct message in the render queue memory; note that delete should not be called on the return value
1259 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferSize, propertyBuffer, size );
1262 } // namespace SceneGraph
1264 } // namespace Internal