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/resources/complete-status-manager.h>
62 #include <dali/internal/update/touch/touch-resampler.h>
64 #include <dali/internal/render/common/render-instruction-container.h>
65 #include <dali/internal/render/common/render-manager.h>
66 #include <dali/internal/render/queue/render-queue.h>
67 #include <dali/internal/render/gl-resources/texture-cache.h>
68 #include <dali/internal/render/shaders/scene-graph-shader.h>
69 #include <dali/internal/render/renderers/render-sampler.h>
71 // Un-comment to enable node tree debug logging
72 //#define NODE_TREE_LOGGING 1
74 #if ( defined( DEBUG_ENABLED ) && defined( NODE_TREE_LOGGING ) )
75 #define SNAPSHOT_NODE_LOGGING \
76 const int FRAME_COUNT_TRIGGER = 16;\
77 if( mImpl->frameCounter >= FRAME_COUNT_TRIGGER )\
79 if ( NULL != mImpl->root )\
81 mImpl->frameCounter = 0;\
82 PrintNodeTree( *mImpl->root, mSceneGraphBuffers.GetUpdateBufferIndex(), "" );\
85 mImpl->frameCounter++;
87 #define SNAPSHOT_NODE_LOGGING
90 #if defined(DEBUG_ENABLED)
91 extern Debug::Filter* gRenderTaskLogFilter;
95 using namespace Dali::Integration;
96 using Dali::Internal::Update::MessageQueue;
110 void DestroyNodeSet( std::set<Node*>& nodeSet )
112 for( std::set<Node*>::iterator iter = nodeSet.begin(); iter != nodeSet.end(); ++iter )
116 // Call Node::OnDestroy as each node is destroyed
126 typedef OwnerContainer< Shader* > ShaderContainer;
127 typedef ShaderContainer::Iterator ShaderIter;
128 typedef ShaderContainer::ConstIterator ShaderConstIter;
130 typedef std::vector<Internal::ShaderDataPtr> ShaderDataBinaryQueue;
132 typedef OwnerContainer<PanGesture*> GestureContainer;
133 typedef GestureContainer::Iterator GestureIter;
134 typedef GestureContainer::ConstIterator GestureConstIter;
138 * Structure to contain UpdateManager internal data
140 struct UpdateManager::Impl
142 Impl( NotificationManager& notificationManager,
143 GlSyncAbstraction& glSyncAbstraction,
144 CompleteNotificationInterface& animationFinishedNotifier,
145 PropertyNotifier& propertyNotifier,
146 ResourceManager& resourceManager,
147 DiscardQueue& discardQueue,
148 RenderController& renderController,
149 RenderManager& renderManager,
150 RenderQueue& renderQueue,
151 TextureCache& textureCache,
152 TouchResampler& touchResampler,
153 SceneGraphBuffers& sceneGraphBuffers )
155 renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ),
156 notificationManager( notificationManager ),
157 animationFinishedNotifier( animationFinishedNotifier ),
158 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 renderers( sceneGraphBuffers, discardQueue ),
175 geometries( sceneGraphBuffers, discardQueue ),
176 materials( sceneGraphBuffers, discardQueue ),
177 messageQueue( renderController, sceneGraphBuffers ),
178 keepRenderingSeconds( 0.0f ),
179 animationFinishedDuringUpdate( false ),
180 nodeDirtyFlags( TransformFlag ), // set to TransformFlag to ensure full update the first time through Update()
181 previousUpdateScene( false ),
183 renderSortingHelper(),
184 renderTaskWaiting( false )
186 sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue, textureCache, completeStatusManager );
188 renderers.SetSceneController( *sceneController );
189 geometries.SetSceneController( *sceneController );
190 materials.SetSceneController( *sceneController );
195 // Disconnect render tasks from nodes, before destroying the nodes
196 RenderTaskList::RenderTaskContainer& tasks = taskList.GetTasks();
197 for (RenderTaskList::RenderTaskContainer::Iterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
199 (*iter)->SetSourceNode( NULL );
201 // ..repeat for system level RenderTasks
202 RenderTaskList::RenderTaskContainer& systemLevelTasks = systemLevelTaskList.GetTasks();
203 for (RenderTaskList::RenderTaskContainer::Iterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
205 (*iter)->SetSourceNode( NULL );
208 // UpdateManager owns the Nodes
209 DestroyNodeSet( activeDisconnectedNodes );
210 DestroyNodeSet( connectedNodes );
211 DestroyNodeSet( disconnectedNodes );
213 // If there is root, reset it, otherwise do nothing as rendering was never started
222 if( systemLevelRoot )
224 systemLevelRoot->OnDestroy();
226 delete systemLevelRoot;
227 systemLevelRoot = NULL;
230 sceneController->GetTextureCache().SetBufferIndices(NULL); // TODO - Remove
231 delete sceneController;
234 SceneGraphBuffers sceneGraphBuffers; ///< Used to keep track of which buffers are being written or read
235 RenderMessageDispatcher renderMessageDispatcher; ///< Used for passing messages to the render-thread
236 NotificationManager& notificationManager; ///< Queues notification messages for the event-thread.
237 CompleteNotificationInterface& animationFinishedNotifier; ///< Provides notification to applications when animations are finished.
238 PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
239 ShaderSaver* shaderSaver; ///< Saves shader binaries.
240 ResourceManager& resourceManager; ///< resource manager
241 DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
242 RenderController& renderController; ///< render controller
243 SceneControllerImpl* sceneController; ///< scene controller
244 RenderManager& renderManager; ///< This is responsible for rendering the results of each "update"
245 RenderQueue& renderQueue; ///< Used to queue messages for the next render
246 RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions
247 CompleteStatusManager completeStatusManager; ///< Complete Status Manager
248 TouchResampler& touchResampler; ///< Used to resample touch events on every update.
250 Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
252 RenderTaskList taskList; ///< The list of scene graph render-tasks
253 RenderTaskList systemLevelTaskList; ///< Separate render-tasks for system-level content
255 Layer* root; ///< The root node (root is a layer)
256 Layer* systemLevelRoot; ///< A separate root-node for system-level content
257 std::set< Node* > activeDisconnectedNodes; ///< A container of new or modified nodes (without parent) owned by UpdateManager
258 std::set< Node* > connectedNodes; ///< A container of connected (with parent) nodes owned by UpdateManager
259 std::set< Node* > disconnectedNodes; ///< A container of inactive disconnected nodes (without parent) owned by UpdateManager
261 SortedLayerPointers sortedLayers; ///< A container of Layer pointers sorted by depth
262 SortedLayerPointers systemLevelSortedLayers; ///< A separate container of system-level Layers
264 OwnerContainer< PropertyOwner* > customObjects; ///< A container of owned objects (with custom properties)
266 AnimationContainer animations; ///< A container of owned animations
267 PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
269 ObjectOwnerContainer<Renderer> renderers;
270 ObjectOwnerContainer<Geometry> geometries; ///< A container of geometries
271 ObjectOwnerContainer<Material> materials; ///< A container of materials
273 ShaderContainer shaders; ///< A container of owned shaders
275 MessageQueue messageQueue; ///< The messages queued from the event-thread
276 ShaderDataBinaryQueue renderCompiledShaders; ///< Shaders compiled on Render thread are inserted here for update thread to pass on to event thread.
277 ShaderDataBinaryQueue updateCompiledShaders; ///< Shaders to be sent from Update to Event
278 Mutex compiledShaderMutex; ///< lock to ensure no corruption on the renderCompiledShaders
280 float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
281 bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
283 int nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
284 bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
286 int frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
287 RendererSortingHelper renderSortingHelper; ///< helper used to sort transparent renderers
289 GestureContainer gestures; ///< A container of owned gesture detectors
290 bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
293 UpdateManager::UpdateManager( NotificationManager& notificationManager,
294 GlSyncAbstraction& glSyncAbstraction,
295 CompleteNotificationInterface& animationFinishedNotifier,
296 PropertyNotifier& propertyNotifier,
297 ResourceManager& resourceManager,
298 DiscardQueue& discardQueue,
299 RenderController& controller,
300 RenderManager& renderManager,
301 RenderQueue& renderQueue,
302 TextureCache& textureCache,
303 TouchResampler& touchResampler )
306 mImpl = new Impl( notificationManager,
308 animationFinishedNotifier,
317 mSceneGraphBuffers );
319 textureCache.SetBufferIndices( &mSceneGraphBuffers );
322 UpdateManager::~UpdateManager()
327 void UpdateManager::InstallRoot( SceneGraph::Layer* layer, bool systemLevel )
329 DALI_ASSERT_DEBUG( layer->IsLayer() );
330 DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
334 DALI_ASSERT_DEBUG( mImpl->root == NULL && "Root Node already installed" );
339 DALI_ASSERT_DEBUG( mImpl->systemLevelRoot == NULL && "System-level Root Node already installed" );
340 mImpl->systemLevelRoot = layer;
343 layer->SetRoot(true);
346 void UpdateManager::AddNode( Node* node )
348 DALI_ASSERT_ALWAYS( NULL != node );
349 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
351 mImpl->activeDisconnectedNodes.insert( node ); // Takes ownership of node
354 void UpdateManager::ConnectNode( Node* parent, Node* node )
356 DALI_ASSERT_ALWAYS( NULL != parent );
357 DALI_ASSERT_ALWAYS( NULL != node );
358 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
360 // Move from active/disconnectedNodes to connectedNodes
361 std::set<Node*>::size_type removed = mImpl->activeDisconnectedNodes.erase( node );
364 removed = mImpl->disconnectedNodes.erase( node );
365 DALI_ASSERT_ALWAYS( removed );
367 mImpl->connectedNodes.insert( node );
369 node->SetActive( true );
371 parent->ConnectChild( node );
374 void UpdateManager::DisconnectNode( Node* node )
376 Node* parent = node->GetParent();
377 DALI_ASSERT_ALWAYS( NULL != parent );
378 parent->SetDirtyFlag( ChildDeletedFlag ); // make parent dirty so that render items dont get reused
380 // Move from connectedNodes to activeDisconnectedNodes (reset properties next frame)
381 parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node, mImpl->connectedNodes, mImpl->activeDisconnectedNodes );
384 void UpdateManager::SetNodeActive( Node* node )
386 DALI_ASSERT_ALWAYS( NULL != node );
387 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
389 // Move from disconnectedNodes to activeDisconnectedNodes (reset properties next frame)
390 std::set<Node*>::size_type removed = mImpl->disconnectedNodes.erase( node );
391 DALI_ASSERT_ALWAYS( removed );
392 mImpl->activeDisconnectedNodes.insert( node );
394 node->SetActive( true );
397 void UpdateManager::DestroyNode( Node* node )
399 DALI_ASSERT_ALWAYS( NULL != node );
400 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
402 // Transfer ownership from new/disconnectedNodes to the discard queue
403 // This keeps the nodes alive, until the render-thread has finished with them
404 std::set<Node*>::size_type removed = mImpl->activeDisconnectedNodes.erase( node );
407 removed = mImpl->disconnectedNodes.erase( node );
408 DALI_ASSERT_ALWAYS( removed );
410 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
412 // Notify the Node about impending destruction
416 //@todo MESH_REWORK Extend to allow arbitrary scene objects to connect to each other
417 void UpdateManager::AttachToNode( Node* node, NodeAttachment* attachment )
419 DALI_ASSERT_DEBUG( node != NULL );
420 DALI_ASSERT_DEBUG( attachment != NULL );
422 // attach node to attachment first so that parent is known by the time attachment is connected
423 node->Attach( *attachment ); // node takes ownership
426 void UpdateManager::AddObject( PropertyOwner* object )
428 DALI_ASSERT_DEBUG( NULL != object );
430 mImpl->customObjects.PushBack( object );
433 void UpdateManager::RemoveObject( PropertyOwner* object )
435 DALI_ASSERT_DEBUG( NULL != object );
437 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
439 // Find the object and destroy it
440 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); iter != customObjects.End(); ++iter )
442 PropertyOwner* current = *iter;
443 if ( current == object )
445 customObjects.Erase( iter );
450 // Should not reach here
451 DALI_ASSERT_DEBUG(false);
454 void UpdateManager::AddAnimation( Animation* animation )
456 mImpl->animations.PushBack( animation );
459 void UpdateManager::StopAnimation( Animation* animation )
461 DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
463 bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
465 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
468 void UpdateManager::RemoveAnimation( Animation* animation )
470 DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
472 animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
474 DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
477 bool UpdateManager::IsAnimationRunning() const
479 bool isRunning(false);
480 AnimationContainer& animations = mImpl->animations;
482 // Find any animation that isn't stopped or paused
484 const AnimationIter endIter = animations.End();
485 for ( AnimationIter iter = animations.Begin(); !isRunning && iter != endIter; ++iter )
487 const Animation::State state = (*iter)->GetState();
489 if (state != Animation::Stopped &&
490 state != Animation::Paused)
499 void UpdateManager::AddPropertyNotification( PropertyNotification* propertyNotification )
501 mImpl->propertyNotifications.PushBack( propertyNotification );
504 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
506 PropertyNotificationContainer &propertyNotifications = mImpl->propertyNotifications;
507 PropertyNotificationIter iter = propertyNotifications.Begin();
509 while ( iter != propertyNotifications.End() )
511 if( *iter == propertyNotification )
513 propertyNotifications.Erase(iter);
520 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
522 DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
523 propertyNotification->SetNotifyMode( notifyMode );
526 ObjectOwnerContainer<Geometry>& UpdateManager::GetGeometryOwner()
528 return mImpl->geometries;
531 ObjectOwnerContainer<Renderer>& UpdateManager::GetRendererOwner()
533 return mImpl->renderers;
537 ObjectOwnerContainer<Material>& UpdateManager::GetMaterialOwner()
539 return mImpl->materials;
542 void UpdateManager::AddShader( Shader* shader )
544 DALI_ASSERT_DEBUG( NULL != shader );
546 if( mImpl->shaders.Count() == 0 )
548 // the first added shader becomes our default shader
549 // Construct message in the render queue memory; note that delete should not be called on the return value
550 typedef MessageValue1< RenderManager, Shader* > DerivedType;
552 // Reserve some memory inside the render queue
553 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
555 // Construct message in the render queue memory; note that delete should not be called on the return value
556 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultShader, shader );
559 mImpl->shaders.PushBack( shader );
561 // Allows the shader to dispatch texture requests to the cache
562 shader->Initialize( mImpl->renderQueue, mImpl->sceneController->GetTextureCache() );
565 void UpdateManager::RemoveShader( Shader* shader )
567 DALI_ASSERT_DEBUG(shader != NULL);
569 ShaderContainer& shaders = mImpl->shaders;
571 // Find the shader and destroy it
572 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
574 Shader& current = **iter;
575 if ( ¤t == shader )
577 // Transfer ownership to the discard queue
578 // This keeps the shader alive, until the render-thread has finished with it
579 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), shaders.Release( iter ) );
584 // Should not reach here
585 DALI_ASSERT_DEBUG(false);
588 void UpdateManager::SetShaderProgram( Shader* shader,
589 Internal::ShaderDataPtr shaderData, bool modifiesGeometry )
594 typedef MessageValue3< Shader, Internal::ShaderDataPtr, ProgramCache*, bool> DerivedType;
596 // Reserve some memory inside the render queue
597 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
599 // Construct message in the render queue memory; note that delete should not be called on the return value
600 new (slot) DerivedType( shader, &Shader::SetProgram, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
604 void UpdateManager::SaveBinary( Internal::ShaderDataPtr shaderData )
606 DALI_ASSERT_DEBUG( shaderData && "No NULL shader data pointers please." );
607 DALI_ASSERT_DEBUG( shaderData->GetBufferSize() > 0 && "Shader binary empty so nothing to save." );
609 // lock as update might be sending previously compiled shaders to event thread
610 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
611 mImpl->renderCompiledShaders.push_back( shaderData );
615 RenderTaskList* UpdateManager::GetRenderTaskList( bool systemLevel )
619 // copy the list, this is only likely to happen once in application life cycle
620 return &(mImpl->taskList);
624 // copy the list, this is only likely to happen once in application life cycle
625 return &(mImpl->systemLevelTaskList);
629 void UpdateManager::AddGesture( PanGesture* gesture )
631 DALI_ASSERT_DEBUG( NULL != gesture );
633 mImpl->gestures.PushBack( gesture );
636 void UpdateManager::RemoveGesture( PanGesture* gesture )
638 DALI_ASSERT_DEBUG( gesture != NULL );
640 GestureContainer& gestures = mImpl->gestures;
642 // Find the gesture and destroy it
643 for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
645 PanGesture& current = **iter;
646 if ( ¤t == gesture )
648 mImpl->gestures.Erase( iter );
652 // Should not reach here
653 DALI_ASSERT_DEBUG(false);
656 unsigned int* UpdateManager::ReserveMessageSlot( std::size_t size, bool updateScene )
658 return mImpl->messageQueue.ReserveMessageSlot( size, updateScene );
661 void UpdateManager::EventProcessingStarted()
663 mImpl->messageQueue.EventProcessingStarted();
666 bool UpdateManager::FlushQueue()
668 return mImpl->messageQueue.FlushQueue();
671 void UpdateManager::ResetProperties( BufferIndex bufferIndex )
673 // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
674 mImpl->animationFinishedDuringUpdate = false;
676 // Animated properties have to be reset to their original value each frame
678 // Reset root properties
681 mImpl->root->ResetToBaseValues( bufferIndex );
683 if ( mImpl->systemLevelRoot )
685 mImpl->systemLevelRoot->ResetToBaseValues( bufferIndex );
688 // Reset the Connected Nodes
689 const std::set<Node*>::iterator endIter = mImpl->connectedNodes.end();
690 for( std::set<Node*>::iterator iter = mImpl->connectedNodes.begin(); endIter != iter; ++iter )
692 (*iter)->ResetToBaseValues( bufferIndex );
695 // If a Node is disconnected, it may still be "active" (requires a reset in next frame)
696 for( std::set<Node*>::iterator iter = mImpl->activeDisconnectedNodes.begin(); mImpl->activeDisconnectedNodes.end() != iter; iter = mImpl->activeDisconnectedNodes.begin() )
699 node->ResetToBaseValues( bufferIndex );
700 node->SetActive( false );
702 // Move everything from activeDisconnectedNodes to disconnectedNodes (no need to reset again)
703 mImpl->activeDisconnectedNodes.erase( iter );
704 mImpl->disconnectedNodes.insert( node );
707 // Reset system-level render-task list properties to base values
708 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
710 for (RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
712 (*iter)->ResetToBaseValues( bufferIndex );
715 // Reset render-task list properties to base values.
716 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
718 for (RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
720 (*iter)->ResetToBaseValues( bufferIndex );
723 // Reset custom object properties to base values
724 for (OwnerContainer<PropertyOwner*>::Iterator iter = mImpl->customObjects.Begin(); iter != mImpl->customObjects.End(); ++iter)
726 (*iter)->ResetToBaseValues( bufferIndex );
729 mImpl->materials.ResetToBaseValues( bufferIndex );
730 mImpl->geometries.ResetToBaseValues( bufferIndex );
731 mImpl->renderers.ResetToBaseValues( bufferIndex );
734 // Reset animatable shader properties to base values
735 for (ShaderIter iter = mImpl->shaders.Begin(); iter != mImpl->shaders.End(); ++iter)
737 (*iter)->ResetToBaseValues( bufferIndex );
741 bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds )
743 bool gestureUpdated( false );
745 // constrain gestures... (in construction order)
746 GestureContainer& gestures = mImpl->gestures;
748 for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
750 PanGesture& gesture = **iter;
751 gesture.ResetToBaseValues( bufferIndex ); // Needs to be done every time as gesture data is written directly to an update-buffer rather than via a message
752 gestureUpdated |= gesture.UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
755 return gestureUpdated;
758 void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
760 AnimationContainer &animations = mImpl->animations;
761 AnimationIter iter = animations.Begin();
762 while ( iter != animations.End() )
764 Animation* animation = *iter;
765 bool finished = animation->Update( bufferIndex, elapsedSeconds );
767 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
769 // Remove animations that had been destroyed but were still waiting for an update
770 if (animation->GetState() == Animation::Destroyed)
772 iter = animations.Erase(iter);
780 if ( mImpl->animationFinishedDuringUpdate )
782 // The application should be notified by NotificationManager, in another thread
783 mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationFinishedNotifier );
787 void UpdateManager::ApplyConstraints( BufferIndex bufferIndex )
789 // constrain custom objects... (in construction order)
790 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
792 const OwnerContainer< PropertyOwner* >::Iterator endIter = customObjects.End();
793 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); endIter != iter; ++iter )
795 PropertyOwner& object = **iter;
796 ConstrainPropertyOwner( object, bufferIndex );
799 // constrain nodes... (in Depth First traversal order)
802 ConstrainNodes( *(mImpl->root), bufferIndex );
805 if ( mImpl->systemLevelRoot )
807 ConstrainNodes( *(mImpl->systemLevelRoot), bufferIndex );
810 // constrain other property-owners after nodes as they are more likely to depend on a node's
811 // current frame property than vice versa. They tend to be final constraints (no further
812 // constraints depend on their properties)
813 // e.g. ShaderEffect uniform a function of Actor's position.
814 // Mesh vertex a function of Actor's position or world position.
816 // Constrain system-level render-tasks
817 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
819 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter )
821 RenderTask& task = **iter;
822 ConstrainPropertyOwner( task, bufferIndex );
825 // Constrain render-tasks
826 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
828 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter )
830 RenderTask& task = **iter;
831 ConstrainPropertyOwner( task, bufferIndex );
834 // Constrain Materials and geometries
835 mImpl->materials.ConstrainObjects( bufferIndex );
836 mImpl->geometries.ConstrainObjects( bufferIndex );
837 mImpl->renderers.ConstrainObjects( bufferIndex );
839 // constrain shaders... (in construction order)
840 ShaderContainer& shaders = mImpl->shaders;
842 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
844 Shader& shader = **iter;
845 ConstrainPropertyOwner( shader, bufferIndex );
849 void UpdateManager::ProcessPropertyNotifications( BufferIndex bufferIndex )
851 PropertyNotificationContainer ¬ifications = mImpl->propertyNotifications;
852 PropertyNotificationIter iter = notifications.Begin();
854 while ( iter != notifications.End() )
856 PropertyNotification* notification = *iter;
857 bool valid = notification->Check( bufferIndex );
860 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
866 void UpdateManager::ForwardCompiledShadersToEventThread()
868 DALI_ASSERT_DEBUG( (mImpl->shaderSaver != 0) && "shaderSaver should be wired-up during startup." );
869 if( mImpl->shaderSaver )
871 // lock and swap the queues
873 // render might be attempting to send us more binaries at the same time
874 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
875 mImpl->renderCompiledShaders.swap( mImpl->updateCompiledShaders );
878 if( mImpl->updateCompiledShaders.size() > 0 )
880 ShaderSaver& factory = *mImpl->shaderSaver;
881 ShaderDataBinaryQueue::iterator i = mImpl->updateCompiledShaders.begin();
882 ShaderDataBinaryQueue::iterator end = mImpl->updateCompiledShaders.end();
883 for( ; i != end; ++i )
885 mImpl->notificationManager.QueueMessage( ShaderCompiledMessage( factory, *i ) );
887 // we don't need them in update anymore
888 mImpl->updateCompiledShaders.clear();
893 void UpdateManager::UpdateRenderers( BufferIndex bufferIndex )
895 const OwnerContainer<Renderer*>& rendererContainer( mImpl->renderers.GetObjectContainer() );
896 unsigned int rendererCount( rendererContainer.Size() );
897 for( unsigned int i(0); i<rendererCount; ++i )
899 if( rendererContainer[i]->IsReferenced() )
901 rendererContainer[i]->PrepareResources(bufferIndex, mImpl->resourceManager);
902 rendererContainer[i]->PrepareRender( bufferIndex );
907 void UpdateManager::UpdateNodes( BufferIndex bufferIndex )
909 mImpl->nodeDirtyFlags = NothingFlag;
916 // Prepare resources, update shaders, update attachments, for each node
917 // And add the renderers to the sorted layers. Start from root, which is also a layer
918 mImpl->nodeDirtyFlags = UpdateNodesAndAttachments( *( mImpl->root ),
920 mImpl->resourceManager,
921 mImpl->renderQueue );
923 if ( mImpl->systemLevelRoot )
925 mImpl->nodeDirtyFlags |= UpdateNodesAndAttachments( *( mImpl->systemLevelRoot ),
927 mImpl->resourceManager,
928 mImpl->renderQueue );
932 unsigned int UpdateManager::Update( float elapsedSeconds,
933 unsigned int lastVSyncTimeMilliseconds,
934 unsigned int nextVSyncTimeMilliseconds )
936 const BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
938 // 1) Clear nodes/resources which were previously discarded
939 mImpl->discardQueue.Clear( bufferIndex );
941 // 2) Grab any loaded resources
942 bool resourceChanged = mImpl->resourceManager.UpdateCache( bufferIndex );
944 // 3) Process Touches & Gestures
945 mImpl->touchResampler.Update();
946 const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
948 const bool updateScene = // The scene-graph requires an update if..
949 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
950 IsAnimationRunning() || // ..at least one animation is running OR
951 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
952 resourceChanged || // ..one or more resources were updated/changed OR
953 gestureUpdated; // ..a gesture property was updated
956 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
957 // values if the scene was updated in the previous frame.
958 if( updateScene || mImpl->previousUpdateScene )
960 // 4) Reset properties from the previous update
961 ResetProperties( bufferIndex );
964 // 5) Process the queued scene messages
965 mImpl->messageQueue.ProcessMessages( bufferIndex );
967 // 6) Post Process Ids of resources updated by renderer
968 mImpl->resourceManager.PostProcessResources( bufferIndex );
970 // 6.1) Forward compiled shader programs to event thread for saving
971 ForwardCompiledShadersToEventThread();
973 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
974 // renderer lists if the scene was updated in the previous frame.
975 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
976 if( updateScene || mImpl->previousUpdateScene )
979 Animate( bufferIndex, elapsedSeconds );
981 // 8) Apply Constraints
982 ApplyConstraints( bufferIndex );
984 // 9) Check Property Notifications
985 ProcessPropertyNotifications( bufferIndex );
987 // 10) Clear the lists of renderable-attachments from the previous update
988 for( size_t i(0); i<mImpl->sortedLayers.size(); ++i )
990 mImpl->sortedLayers[i]->ClearRenderables();
993 for( size_t i(0); i<mImpl->systemLevelSortedLayers.size(); ++i )
995 mImpl->systemLevelSortedLayers[i]->ClearRenderables();
998 // 11) Update node hierarchy and perform sorting / culling.
999 // This will populate each Layer with a list of renderers which are ready.
1000 UpdateNodes( bufferIndex );
1001 UpdateRenderers( bufferIndex );
1003 // 13) Process the RenderTasks; this creates the instructions for rendering the next frame.
1004 // reset the update buffer index and make sure there is enough room in the instruction container
1005 mImpl->renderInstructions.ResetAndReserve( bufferIndex,
1006 mImpl->taskList.GetTasks().Count() + mImpl->systemLevelTaskList.GetTasks().Count() );
1008 if ( NULL != mImpl->root )
1010 ProcessRenderTasks( bufferIndex,
1011 mImpl->completeStatusManager,
1014 mImpl->sortedLayers,
1015 mImpl->renderSortingHelper,
1016 mImpl->renderInstructions );
1018 // Process the system-level RenderTasks last
1019 if ( NULL != mImpl->systemLevelRoot )
1021 ProcessRenderTasks( bufferIndex,
1022 mImpl->completeStatusManager,
1023 mImpl->systemLevelTaskList,
1024 *mImpl->systemLevelRoot,
1025 mImpl->systemLevelSortedLayers,
1026 mImpl->renderSortingHelper,
1027 mImpl->renderInstructions );
1032 // check the countdown and notify (note, at the moment this is only done for normal tasks, not for systemlevel tasks)
1033 bool doRenderOnceNotify = false;
1034 mImpl->renderTaskWaiting = false;
1035 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
1036 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(), endIter = tasks.End();
1037 endIter != iter; ++iter )
1039 RenderTask& renderTask(*(*iter));
1041 renderTask.UpdateState();
1043 if( renderTask.IsWaitingToRender() &&
1044 renderTask.ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
1046 mImpl->renderTaskWaiting = true; // keep update/render threads alive
1049 if( renderTask.HasRendered() )
1051 doRenderOnceNotify = true;
1055 if( doRenderOnceNotify )
1057 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
1058 mImpl->notificationManager.QueueCompleteNotification( mImpl->taskList.GetCompleteNotificationInterface() );
1061 // Macro is undefined in release build.
1062 SNAPSHOT_NODE_LOGGING;
1064 // A ResetProperties() may be required in the next frame
1065 mImpl->previousUpdateScene = updateScene;
1067 // Check whether further updates are required
1068 unsigned int keepUpdating = KeepUpdatingCheck( elapsedSeconds );
1070 // tell the update manager that we're done so the queue can be given to event thread
1071 mImpl->notificationManager.UpdateCompleted();
1073 // The update has finished; swap the double-buffering indices
1074 mSceneGraphBuffers.Swap();
1076 return keepUpdating;
1079 unsigned int UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
1081 // Update the duration set via Stage::KeepRendering()
1082 if ( mImpl->keepRenderingSeconds > 0.0f )
1084 mImpl->keepRenderingSeconds -= elapsedSeconds;
1087 unsigned int keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
1089 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
1090 // Keep updating until no messages are received and no animations are running.
1091 // If an animation has just finished, update at least once more for Discard end-actions.
1092 // No need to check for renderQueue as there is always a render after update and if that
1093 // render needs another update it will tell the adaptor to call update again
1095 if ( mImpl->keepRenderingSeconds > 0.0f )
1097 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
1100 if ( IsAnimationRunning() ||
1101 mImpl->animationFinishedDuringUpdate )
1103 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
1106 if ( mImpl->renderTaskWaiting )
1108 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
1111 return keepUpdatingRequest;
1114 void UpdateManager::SetBackgroundColor( const Vector4& color )
1116 typedef MessageValue1< RenderManager, Vector4 > DerivedType;
1118 // Reserve some memory inside the render queue
1119 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1121 // Construct message in the render queue memory; note that delete should not be called on the return value
1122 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
1125 void UpdateManager::SetDefaultSurfaceRect( const Rect<int>& rect )
1127 typedef MessageValue1< RenderManager, Rect<int> > DerivedType;
1129 // Reserve some memory inside the render queue
1130 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1132 // Construct message in the render queue memory; note that delete should not be called on the return value
1133 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1136 void UpdateManager::KeepRendering( float durationSeconds )
1138 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1141 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, bool systemLevel )
1145 // just copy the vector of pointers
1146 mImpl->sortedLayers = layers;
1150 mImpl->systemLevelSortedLayers = layers;
1154 void UpdateManager::SetShaderSaver( ShaderSaver& upstream )
1156 mImpl->shaderSaver = &upstream;
1159 void UpdateManager::AddSampler( Render::Sampler* sampler )
1161 typedef MessageValue1< RenderManager, Render::Sampler* > DerivedType;
1163 // Reserve some memory inside the render queue
1164 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1166 // Construct message in the render queue memory; note that delete should not be called on the return value
1167 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddSampler, sampler );
1170 void UpdateManager::RemoveSampler( Render::Sampler* sampler )
1172 typedef MessageValue1< RenderManager, Render::Sampler* > DerivedType;
1174 // Reserve some memory inside the render queue
1175 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1177 // Construct message in the render queue memory; note that delete should not be called on the return value
1178 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveSampler, sampler );
1181 void UpdateManager::SetFilterMode( Render::Sampler* sampler, unsigned int minFilterMode, unsigned int magFilterMode )
1183 typedef MessageValue3< RenderManager, Render::Sampler*, unsigned int, unsigned int > DerivedType;
1185 // Reserve some memory inside the render queue
1186 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1188 // Construct message in the render queue memory; note that delete should not be called on the return value
1189 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetFilterMode, sampler, minFilterMode, magFilterMode );
1192 void UpdateManager::SetWrapMode( Render::Sampler* sampler, unsigned int uWrapMode, unsigned int vWrapMode )
1194 typedef MessageValue3< RenderManager, Render::Sampler*, unsigned int, unsigned int > DerivedType;
1196 // Reserve some memory inside the render queue
1197 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1199 // Construct message in the render queue memory; note that delete should not be called on the return value
1200 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetWrapMode, sampler, uWrapMode, vWrapMode );
1203 void UpdateManager::AddPropertyBuffer( Render::PropertyBuffer* propertyBuffer )
1205 typedef MessageValue1< RenderManager, Render::PropertyBuffer* > DerivedType;
1207 // Reserve some memory inside the render queue
1208 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1210 // Construct message in the render queue memory; note that delete should not be called on the return value
1211 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddPropertyBuffer, propertyBuffer );
1214 void UpdateManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer )
1216 typedef MessageValue1< RenderManager, Render::PropertyBuffer* > DerivedType;
1218 // Reserve some memory inside the render queue
1219 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1221 // Construct message in the render queue memory; note that delete should not be called on the return value
1222 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemovePropertyBuffer, propertyBuffer );
1225 void UpdateManager::SetPropertyBufferFormat(Render::PropertyBuffer* propertyBuffer, Render::PropertyBuffer::Format* format )
1227 typedef MessageValue2< RenderManager, Render::PropertyBuffer*, Render::PropertyBuffer::Format* > DerivedType;
1229 // Reserve some memory inside the render queue
1230 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1232 // Construct message in the render queue memory; note that delete should not be called on the return value
1233 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferFormat, propertyBuffer, format );
1236 void UpdateManager::SetPropertyBufferData(Render::PropertyBuffer* propertyBuffer, Dali::Vector<char>* data)
1238 typedef MessageValue2< RenderManager, Render::PropertyBuffer*, Dali::Vector<char>* > DerivedType;
1240 // Reserve some memory inside the render queue
1241 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1243 // Construct message in the render queue memory; note that delete should not be called on the return value
1244 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferData, propertyBuffer, data );
1247 void UpdateManager::SetPropertyBufferSize(Render::PropertyBuffer* propertyBuffer, size_t size )
1249 typedef MessageValue2< RenderManager, Render::PropertyBuffer*, size_t > DerivedType;
1251 // Reserve some memory inside the render queue
1252 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1254 // Construct message in the render queue memory; note that delete should not be called on the return value
1255 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferSize, propertyBuffer, size );
1258 } // namespace SceneGraph
1260 } // namespace Internal