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/mutex.h>
26 #include <dali/integration-api/core.h>
27 #include <dali/integration-api/render-controller.h>
28 #include <dali/internal/common/shader-data.h>
29 #include <dali/integration-api/debug.h>
31 #include <dali/internal/common/core-impl.h>
32 #include <dali/internal/common/owner-container.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/common/scene-graph-property-buffer.h>
45 #include <dali/internal/update/controllers/render-message-dispatcher.h>
46 #include <dali/internal/update/controllers/scene-controller-impl.h>
47 #include <dali/internal/update/gestures/scene-graph-pan-gesture.h>
48 #include <dali/internal/update/manager/object-owner-container.h>
49 #include <dali/internal/update/manager/prepare-render-algorithms.h>
50 #include <dali/internal/update/manager/process-render-tasks.h>
51 #include <dali/internal/update/manager/sorted-layers.h>
52 #include <dali/internal/update/manager/update-algorithms.h>
53 #include <dali/internal/update/manager/update-manager-debug.h>
54 #include <dali/internal/update/node-attachments/scene-graph-camera-attachment.h>
55 #include <dali/internal/update/node-attachments/scene-graph-image-attachment.h>
56 #include <dali/internal/update/nodes/node.h>
57 #include <dali/internal/update/nodes/scene-graph-layer.h>
58 #include <dali/internal/update/queue/update-message-queue.h>
59 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
60 #include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
61 #include <dali/internal/update/rendering/scene-graph-material.h>
62 #include <dali/internal/update/rendering/scene-graph-sampler.h>
63 #include <dali/internal/update/rendering/scene-graph-geometry.h>
64 #include <dali/internal/update/resources/resource-manager.h>
65 #include <dali/internal/update/resources/complete-status-manager.h>
66 #include <dali/internal/update/touch/touch-resampler.h>
68 #include <dali/internal/render/common/render-instruction-container.h>
69 #include <dali/internal/render/common/render-manager.h>
70 #include <dali/internal/render/queue/render-queue.h>
71 #include <dali/internal/render/common/performance-monitor.h>
72 #include <dali/internal/render/gl-resources/texture-cache.h>
73 #include <dali/internal/render/shaders/scene-graph-shader.h>
75 // Un-comment to enable node tree debug logging
76 //#define NODE_TREE_LOGGING 1
78 #if ( defined( DEBUG_ENABLED ) && defined( NODE_TREE_LOGGING ) )
79 #define SNAPSHOT_NODE_LOGGING \
80 const int FRAME_COUNT_TRIGGER = 16;\
81 if( mImpl->frameCounter >= FRAME_COUNT_TRIGGER )\
83 if ( NULL != mImpl->root )\
85 mImpl->frameCounter = 0;\
86 PrintNodeTree( *mImpl->root, mSceneGraphBuffers.GetUpdateBufferIndex(), "" );\
89 mImpl->frameCounter++;
91 #define SNAPSHOT_NODE_LOGGING
94 #if defined(DEBUG_ENABLED)
95 extern Debug::Filter* gRenderTaskLogFilter;
99 using namespace Dali::Integration;
100 using Dali::Internal::Update::MessageQueue;
114 void DestroyNodeSet( std::set<Node*>& nodeSet )
116 for( std::set<Node*>::iterator iter = nodeSet.begin(); iter != nodeSet.end(); ++iter )
120 // Call Node::OnDestroy as each node is destroyed
130 typedef OwnerContainer< Shader* > ShaderContainer;
131 typedef ShaderContainer::Iterator ShaderIter;
132 typedef ShaderContainer::ConstIterator ShaderConstIter;
134 typedef std::vector<Internal::ShaderDataPtr> ShaderDataBinaryQueue;
136 typedef OwnerContainer<PanGesture*> GestureContainer;
137 typedef GestureContainer::Iterator GestureIter;
138 typedef GestureContainer::ConstIterator GestureConstIter;
142 * Structure to contain UpdateManager internal data
144 struct UpdateManager::Impl
146 Impl( NotificationManager& notificationManager,
147 GlSyncAbstraction& glSyncAbstraction,
148 CompleteNotificationInterface& animationFinishedNotifier,
149 PropertyNotifier& propertyNotifier,
150 ResourceManager& resourceManager,
151 DiscardQueue& discardQueue,
152 RenderController& renderController,
153 RenderManager& renderManager,
154 RenderQueue& renderQueue,
155 TextureCache& textureCache,
156 TouchResampler& touchResampler,
157 SceneGraphBuffers& sceneGraphBuffers )
159 renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ),
160 notificationManager( notificationManager ),
161 animationFinishedNotifier( animationFinishedNotifier ),
162 propertyNotifier( propertyNotifier ),
164 resourceManager( resourceManager ),
165 discardQueue( discardQueue ),
166 renderController( renderController ),
167 sceneController( NULL ),
168 renderManager( renderManager ),
169 renderQueue( renderQueue ),
170 renderInstructions( renderManager.GetRenderInstructionContainer() ),
171 completeStatusManager( glSyncAbstraction, renderMessageDispatcher, resourceManager ),
172 touchResampler( touchResampler ),
173 backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
174 taskList ( completeStatusManager ),
175 systemLevelTaskList ( completeStatusManager ),
177 systemLevelRoot( NULL ),
178 renderers( sceneGraphBuffers, discardQueue ),
179 geometries( sceneGraphBuffers, discardQueue ),
180 materials( sceneGraphBuffers, discardQueue ),
181 samplers( sceneGraphBuffers, discardQueue ),
182 propertyBuffers( sceneGraphBuffers, discardQueue ),
183 messageQueue( renderController, sceneGraphBuffers ),
184 keepRenderingSeconds( 0.0f ),
185 animationFinishedDuringUpdate( false ),
186 nodeDirtyFlags( TransformFlag ), // set to TransformFlag to ensure full update the first time through Update()
187 previousUpdateScene( false ),
189 renderSortingHelper(),
190 renderTaskWaiting( false )
192 sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue, textureCache, completeStatusManager );
194 renderers.SetSceneController( *sceneController );
195 geometries.SetSceneController( *sceneController );
196 materials.SetSceneController( *sceneController );
197 propertyBuffers.SetSceneController( *sceneController );
198 samplers.SetSceneController( *sceneController );
203 // Disconnect render tasks from nodes, before destroying the nodes
204 RenderTaskList::RenderTaskContainer& tasks = taskList.GetTasks();
205 for (RenderTaskList::RenderTaskContainer::Iterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
207 (*iter)->SetSourceNode( NULL );
209 // ..repeat for system level RenderTasks
210 RenderTaskList::RenderTaskContainer& systemLevelTasks = systemLevelTaskList.GetTasks();
211 for (RenderTaskList::RenderTaskContainer::Iterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
213 (*iter)->SetSourceNode( NULL );
216 // UpdateManager owns the Nodes
217 DestroyNodeSet( activeDisconnectedNodes );
218 DestroyNodeSet( connectedNodes );
219 DestroyNodeSet( disconnectedNodes );
221 // If there is root, reset it, otherwise do nothing as rendering was never started
230 if( systemLevelRoot )
232 systemLevelRoot->OnDestroy();
234 delete systemLevelRoot;
235 systemLevelRoot = NULL;
238 sceneController->GetTextureCache().SetBufferIndices(NULL); // TODO - Remove
239 delete sceneController;
242 SceneGraphBuffers sceneGraphBuffers; ///< Used to keep track of which buffers are being written or read
243 RenderMessageDispatcher renderMessageDispatcher; ///< Used for passing messages to the render-thread
244 NotificationManager& notificationManager; ///< Queues notification messages for the event-thread.
245 CompleteNotificationInterface& animationFinishedNotifier; ///< Provides notification to applications when animations are finished.
246 PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
247 ShaderSaver* shaderSaver; ///< Saves shader binaries.
248 ResourceManager& resourceManager; ///< resource manager
249 DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
250 RenderController& renderController; ///< render controller
251 SceneControllerImpl* sceneController; ///< scene controller
252 RenderManager& renderManager; ///< This is responsible for rendering the results of each "update"
253 RenderQueue& renderQueue; ///< Used to queue messages for the next render
254 RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions
255 CompleteStatusManager completeStatusManager; ///< Complete Status Manager
256 TouchResampler& touchResampler; ///< Used to resample touch events on every update.
258 Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
260 RenderTaskList taskList; ///< The list of scene graph render-tasks
261 RenderTaskList systemLevelTaskList; ///< Separate render-tasks for system-level content
263 Layer* root; ///< The root node (root is a layer)
264 Layer* systemLevelRoot; ///< A separate root-node for system-level content
265 std::set< Node* > activeDisconnectedNodes; ///< A container of new or modified nodes (without parent) owned by UpdateManager
266 std::set< Node* > connectedNodes; ///< A container of connected (with parent) nodes owned by UpdateManager
267 std::set< Node* > disconnectedNodes; ///< A container of inactive disconnected nodes (without parent) owned by UpdateManager
269 SortedLayerPointers sortedLayers; ///< A container of Layer pointers sorted by depth
270 SortedLayerPointers systemLevelSortedLayers; ///< A separate container of system-level Layers
272 OwnerContainer< PropertyOwner* > customObjects; ///< A container of owned objects (with custom properties)
274 AnimationContainer animations; ///< A container of owned animations
275 PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
277 ObjectOwnerContainer<Renderer> renderers;
278 ObjectOwnerContainer<Geometry> geometries; ///< A container of geometries
279 ObjectOwnerContainer<Material> materials; ///< A container of materials
280 ObjectOwnerContainer<Sampler> samplers; ///< A container of samplers
281 ObjectOwnerContainer<PropertyBuffer> propertyBuffers; ///< A container of property buffers
283 ShaderContainer shaders; ///< A container of owned shaders
285 MessageQueue messageQueue; ///< The messages queued from the event-thread
286 ShaderDataBinaryQueue renderCompiledShaders; ///< Shaders compiled on Render thread are inserted here for update thread to pass on to event thread.
287 ShaderDataBinaryQueue updateCompiledShaders; ///< Shaders to be sent from Update to Event
288 Mutex compiledShaderMutex; ///< lock to ensure no corruption on the renderCompiledShaders
290 float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
291 bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
293 int nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
294 bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
296 int frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
297 RendererSortingHelper renderSortingHelper; ///< helper used to sort transparent renderers
299 GestureContainer gestures; ///< A container of owned gesture detectors
300 bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
303 UpdateManager::UpdateManager( NotificationManager& notificationManager,
304 GlSyncAbstraction& glSyncAbstraction,
305 CompleteNotificationInterface& animationFinishedNotifier,
306 PropertyNotifier& propertyNotifier,
307 ResourceManager& resourceManager,
308 DiscardQueue& discardQueue,
309 RenderController& controller,
310 RenderManager& renderManager,
311 RenderQueue& renderQueue,
312 TextureCache& textureCache,
313 TouchResampler& touchResampler )
316 mImpl = new Impl( notificationManager,
318 animationFinishedNotifier,
327 mSceneGraphBuffers );
329 textureCache.SetBufferIndices( &mSceneGraphBuffers );
332 UpdateManager::~UpdateManager()
337 void UpdateManager::InstallRoot( SceneGraph::Layer* layer, bool systemLevel )
339 DALI_ASSERT_DEBUG( layer->IsLayer() );
340 DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
344 DALI_ASSERT_DEBUG( mImpl->root == NULL && "Root Node already installed" );
349 DALI_ASSERT_DEBUG( mImpl->systemLevelRoot == NULL && "System-level Root Node already installed" );
350 mImpl->systemLevelRoot = layer;
353 layer->SetRoot(true);
356 void UpdateManager::AddNode( Node* node )
358 DALI_ASSERT_ALWAYS( NULL != node );
359 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
361 mImpl->activeDisconnectedNodes.insert( node ); // Takes ownership of node
364 void UpdateManager::ConnectNode( Node* parent, Node* node )
366 DALI_ASSERT_ALWAYS( NULL != parent );
367 DALI_ASSERT_ALWAYS( NULL != node );
368 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
370 // Move from active/disconnectedNodes to connectedNodes
371 std::set<Node*>::size_type removed = mImpl->activeDisconnectedNodes.erase( node );
374 removed = mImpl->disconnectedNodes.erase( node );
375 DALI_ASSERT_ALWAYS( removed );
377 mImpl->connectedNodes.insert( node );
379 node->SetActive( true );
381 parent->ConnectChild( node );
384 void UpdateManager::DisconnectNode( Node* node )
386 Node* parent = node->GetParent();
387 DALI_ASSERT_ALWAYS( NULL != parent );
388 parent->SetDirtyFlag( ChildDeletedFlag ); // make parent dirty so that render items dont get reused
390 // Move from connectedNodes to activeDisconnectedNodes (reset properties next frame)
391 parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node, mImpl->connectedNodes, mImpl->activeDisconnectedNodes );
394 void UpdateManager::SetNodeActive( Node* node )
396 DALI_ASSERT_ALWAYS( NULL != node );
397 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
399 // Move from disconnectedNodes to activeDisconnectedNodes (reset properties next frame)
400 std::set<Node*>::size_type removed = mImpl->disconnectedNodes.erase( node );
401 DALI_ASSERT_ALWAYS( removed );
402 mImpl->activeDisconnectedNodes.insert( node );
404 node->SetActive( true );
407 void UpdateManager::DestroyNode( Node* node )
409 DALI_ASSERT_ALWAYS( NULL != node );
410 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
412 // Transfer ownership from new/disconnectedNodes to the discard queue
413 // This keeps the nodes alive, until the render-thread has finished with them
414 std::set<Node*>::size_type removed = mImpl->activeDisconnectedNodes.erase( node );
417 removed = mImpl->disconnectedNodes.erase( node );
418 DALI_ASSERT_ALWAYS( removed );
420 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
422 // Notify the Node about impending destruction
426 //@todo MESH_REWORK Extend to allow arbitrary scene objects to connect to each other
427 void UpdateManager::AttachToNode( Node* node, NodeAttachment* attachment )
429 DALI_ASSERT_DEBUG( node != NULL );
430 DALI_ASSERT_DEBUG( attachment != NULL );
432 // attach node to attachment first so that parent is known by the time attachment is connected
433 node->Attach( *attachment ); // node takes ownership
435 // @todo MESH_REWORK Remove after merge of SceneGraph::RenderableAttachment and SceneGraph::RendererAttachment
436 if( dynamic_cast<SceneGraph::ImageAttachment*>( attachment ) != NULL )
438 attachment->Initialize( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
442 void UpdateManager::AddObject( PropertyOwner* object )
444 DALI_ASSERT_DEBUG( NULL != object );
446 mImpl->customObjects.PushBack( object );
449 void UpdateManager::RemoveObject( PropertyOwner* object )
451 DALI_ASSERT_DEBUG( NULL != object );
453 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
455 // Find the object and destroy it
456 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); iter != customObjects.End(); ++iter )
458 PropertyOwner* current = *iter;
459 if ( current == object )
461 customObjects.Erase( iter );
466 // Should not reach here
467 DALI_ASSERT_DEBUG(false);
470 void UpdateManager::AddAnimation( Animation* animation )
472 mImpl->animations.PushBack( animation );
475 void UpdateManager::StopAnimation( Animation* animation )
477 DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
479 bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
481 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
484 void UpdateManager::RemoveAnimation( Animation* animation )
486 DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
488 animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
490 DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
493 bool UpdateManager::IsAnimationRunning() const
495 bool isRunning(false);
496 AnimationContainer& animations = mImpl->animations;
498 // Find any animation that isn't stopped or paused
500 const AnimationIter endIter = animations.End();
501 for ( AnimationIter iter = animations.Begin(); !isRunning && iter != endIter; ++iter )
503 const Animation::State state = (*iter)->GetState();
505 if (state != Animation::Stopped &&
506 state != Animation::Paused)
515 void UpdateManager::AddPropertyNotification( PropertyNotification* propertyNotification )
517 mImpl->propertyNotifications.PushBack( propertyNotification );
520 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
522 PropertyNotificationContainer &propertyNotifications = mImpl->propertyNotifications;
523 PropertyNotificationIter iter = propertyNotifications.Begin();
525 while ( iter != propertyNotifications.End() )
527 if( *iter == propertyNotification )
529 propertyNotifications.Erase(iter);
536 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
538 DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
539 propertyNotification->SetNotifyMode( notifyMode );
542 ObjectOwnerContainer<Geometry>& UpdateManager::GetGeometryOwner()
544 return mImpl->geometries;
547 ObjectOwnerContainer<Renderer>& UpdateManager::GetRendererOwner()
549 return mImpl->renderers;
553 ObjectOwnerContainer<Material>& UpdateManager::GetMaterialOwner()
555 return mImpl->materials;
558 ObjectOwnerContainer<Sampler>& UpdateManager::GetSamplerOwner()
560 return mImpl->samplers;
563 ObjectOwnerContainer<PropertyBuffer>& UpdateManager::GetPropertyBufferOwner()
565 return mImpl->propertyBuffers;
568 void UpdateManager::AddShader( Shader* shader )
570 DALI_ASSERT_DEBUG( NULL != shader );
572 if( mImpl->shaders.Count() == 0 )
574 // the first added shader becomes our default shader
575 // Construct message in the render queue memory; note that delete should not be called on the return value
576 typedef MessageValue1< RenderManager, Shader* > DerivedType;
578 // Reserve some memory inside the render queue
579 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
581 // Construct message in the render queue memory; note that delete should not be called on the return value
582 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultShader, shader );
585 mImpl->shaders.PushBack( shader );
587 // Allows the shader to dispatch texture requests to the cache
588 shader->Initialize( mImpl->renderQueue, mImpl->sceneController->GetTextureCache() );
591 void UpdateManager::RemoveShader( Shader* shader )
593 DALI_ASSERT_DEBUG(shader != NULL);
595 ShaderContainer& shaders = mImpl->shaders;
597 // Find the shader and destroy it
598 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
600 Shader& current = **iter;
601 if ( ¤t == shader )
603 // Transfer ownership to the discard queue
604 // This keeps the shader alive, until the render-thread has finished with it
605 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), shaders.Release( iter ) );
610 // Should not reach here
611 DALI_ASSERT_DEBUG(false);
614 void UpdateManager::SetShaderProgram( Shader* shader,
615 Internal::ShaderDataPtr shaderData, bool modifiesGeometry )
620 typedef MessageValue3< Shader, Internal::ShaderDataPtr, ProgramCache*, bool> DerivedType;
622 // Reserve some memory inside the render queue
623 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
625 // Construct message in the render queue memory; note that delete should not be called on the return value
626 new (slot) DerivedType( shader, &Shader::SetProgram, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
630 void UpdateManager::SaveBinary( Internal::ShaderDataPtr shaderData )
632 DALI_ASSERT_DEBUG( shaderData && "No NULL shader data pointers please." );
633 DALI_ASSERT_DEBUG( shaderData->GetBufferSize() > 0 && "Shader binary empty so nothing to save." );
635 // lock as update might be sending previously compiled shaders to event thread
636 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
637 mImpl->renderCompiledShaders.push_back( shaderData );
641 RenderTaskList* UpdateManager::GetRenderTaskList( bool systemLevel )
645 // copy the list, this is only likely to happen once in application life cycle
646 return &(mImpl->taskList);
650 // copy the list, this is only likely to happen once in application life cycle
651 return &(mImpl->systemLevelTaskList);
655 void UpdateManager::AddGesture( PanGesture* gesture )
657 DALI_ASSERT_DEBUG( NULL != gesture );
659 mImpl->gestures.PushBack( gesture );
662 void UpdateManager::RemoveGesture( PanGesture* gesture )
664 DALI_ASSERT_DEBUG( gesture != NULL );
666 GestureContainer& gestures = mImpl->gestures;
668 // Find the gesture and destroy it
669 for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
671 PanGesture& current = **iter;
672 if ( ¤t == gesture )
674 mImpl->gestures.Erase( iter );
678 // Should not reach here
679 DALI_ASSERT_DEBUG(false);
682 unsigned int* UpdateManager::ReserveMessageSlot( std::size_t size, bool updateScene )
684 return mImpl->messageQueue.ReserveMessageSlot( size, updateScene );
687 void UpdateManager::EventProcessingStarted()
689 mImpl->messageQueue.EventProcessingStarted();
692 bool UpdateManager::FlushQueue()
694 return mImpl->messageQueue.FlushQueue();
697 void UpdateManager::ResetProperties( BufferIndex bufferIndex )
699 PERF_MONITOR_START(PerformanceMonitor::RESET_PROPERTIES);
701 // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
702 mImpl->animationFinishedDuringUpdate = false;
704 // Animated properties have to be reset to their original value each frame
706 // Reset root properties
709 mImpl->root->ResetToBaseValues( bufferIndex );
711 if ( mImpl->systemLevelRoot )
713 mImpl->systemLevelRoot->ResetToBaseValues( bufferIndex );
716 // Reset the Connected Nodes
717 const std::set<Node*>::iterator endIter = mImpl->connectedNodes.end();
718 for( std::set<Node*>::iterator iter = mImpl->connectedNodes.begin(); endIter != iter; ++iter )
720 (*iter)->ResetToBaseValues( bufferIndex );
723 // If a Node is disconnected, it may still be "active" (requires a reset in next frame)
724 for( std::set<Node*>::iterator iter = mImpl->activeDisconnectedNodes.begin(); mImpl->activeDisconnectedNodes.end() != iter; iter = mImpl->activeDisconnectedNodes.begin() )
727 node->ResetToBaseValues( bufferIndex );
728 node->SetActive( false );
730 // Move everything from activeDisconnectedNodes to disconnectedNodes (no need to reset again)
731 mImpl->activeDisconnectedNodes.erase( iter );
732 mImpl->disconnectedNodes.insert( node );
735 // Reset system-level render-task list properties to base values
736 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
738 for (RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
740 (*iter)->ResetToBaseValues( bufferIndex );
743 // Reset render-task list properties to base values.
744 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
746 for (RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
748 (*iter)->ResetToBaseValues( bufferIndex );
751 // Reset custom object properties to base values
752 for (OwnerContainer<PropertyOwner*>::Iterator iter = mImpl->customObjects.Begin(); iter != mImpl->customObjects.End(); ++iter)
754 (*iter)->ResetToBaseValues( bufferIndex );
757 mImpl->materials.ResetToBaseValues( bufferIndex );
758 mImpl->geometries.ResetToBaseValues( bufferIndex );
759 mImpl->propertyBuffers.ResetToBaseValues( bufferIndex );
760 mImpl->samplers.ResetToBaseValues( bufferIndex );
761 mImpl->renderers.ResetToBaseValues( bufferIndex );
764 // Reset animatable shader properties to base values
765 for (ShaderIter iter = mImpl->shaders.Begin(); iter != mImpl->shaders.End(); ++iter)
767 (*iter)->ResetToBaseValues( bufferIndex );
770 PERF_MONITOR_END(PerformanceMonitor::RESET_PROPERTIES);
773 bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds )
775 bool gestureUpdated( false );
777 // constrain gestures... (in construction order)
778 GestureContainer& gestures = mImpl->gestures;
780 for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
782 PanGesture& gesture = **iter;
783 gesture.ResetToBaseValues( bufferIndex ); // Needs to be done every time as gesture data is written directly to an update-buffer rather than via a message
784 gestureUpdated |= gesture.UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
787 return gestureUpdated;
790 void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
792 PERF_MONITOR_START(PerformanceMonitor::ANIMATE_NODES);
794 AnimationContainer &animations = mImpl->animations;
795 AnimationIter iter = animations.Begin();
796 while ( iter != animations.End() )
798 Animation* animation = *iter;
799 bool finished = animation->Update( bufferIndex, elapsedSeconds );
801 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
803 // Remove animations that had been destroyed but were still waiting for an update
804 if (animation->GetState() == Animation::Destroyed)
806 iter = animations.Erase(iter);
814 if ( mImpl->animationFinishedDuringUpdate )
816 // The application should be notified by NotificationManager, in another thread
817 mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationFinishedNotifier );
820 PERF_MONITOR_END(PerformanceMonitor::ANIMATE_NODES);
823 void UpdateManager::ApplyConstraints( BufferIndex bufferIndex )
825 PERF_MONITOR_START(PerformanceMonitor::APPLY_CONSTRAINTS);
827 // constrain custom objects... (in construction order)
828 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
830 const OwnerContainer< PropertyOwner* >::Iterator endIter = customObjects.End();
831 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); endIter != iter; ++iter )
833 PropertyOwner& object = **iter;
834 ConstrainPropertyOwner( object, bufferIndex );
837 // constrain nodes... (in Depth First traversal order)
840 ConstrainNodes( *(mImpl->root), bufferIndex );
843 if ( mImpl->systemLevelRoot )
845 ConstrainNodes( *(mImpl->systemLevelRoot), bufferIndex );
848 // constrain other property-owners after nodes as they are more likely to depend on a node's
849 // current frame property than vice versa. They tend to be final constraints (no further
850 // constraints depend on their properties)
851 // e.g. ShaderEffect uniform a function of Actor's position.
852 // Mesh vertex a function of Actor's position or world position.
854 // TODO: refactor this code (and reset nodes) as these are all just lists of property-owners
855 // they can be all processed in a super-list of property-owners.
857 // Constrain system-level render-tasks
858 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
860 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter )
862 RenderTask& task = **iter;
863 ConstrainPropertyOwner( task, bufferIndex );
866 // Constrain render-tasks
867 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
869 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter )
871 RenderTask& task = **iter;
872 ConstrainPropertyOwner( task, bufferIndex );
875 // Constrain Materials and geometries
876 mImpl->materials.ConstrainObjects( bufferIndex );
877 mImpl->geometries.ConstrainObjects( bufferIndex );
878 mImpl->samplers.ConstrainObjects( bufferIndex );
879 mImpl->propertyBuffers.ConstrainObjects( bufferIndex );
880 mImpl->renderers.ConstrainObjects( bufferIndex );
882 // constrain shaders... (in construction order)
883 ShaderContainer& shaders = mImpl->shaders;
885 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
887 Shader& shader = **iter;
888 ConstrainPropertyOwner( shader, bufferIndex );
891 PERF_MONITOR_END(PerformanceMonitor::APPLY_CONSTRAINTS);
894 void UpdateManager::ProcessPropertyNotifications( BufferIndex bufferIndex )
896 PropertyNotificationContainer ¬ifications = mImpl->propertyNotifications;
897 PropertyNotificationIter iter = notifications.Begin();
899 while ( iter != notifications.End() )
901 PropertyNotification* notification = *iter;
902 bool valid = notification->Check( bufferIndex );
905 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
911 void UpdateManager::ForwardCompiledShadersToEventThread()
913 DALI_ASSERT_DEBUG( (mImpl->shaderSaver != 0) && "shaderSaver should be wired-up during startup." );
914 if( mImpl->shaderSaver )
916 // lock and swap the queues
918 // render might be attempting to send us more binaries at the same time
919 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
920 mImpl->renderCompiledShaders.swap( mImpl->updateCompiledShaders );
923 if( mImpl->updateCompiledShaders.size() > 0 )
925 ShaderSaver& factory = *mImpl->shaderSaver;
926 ShaderDataBinaryQueue::iterator i = mImpl->updateCompiledShaders.begin();
927 ShaderDataBinaryQueue::iterator end = mImpl->updateCompiledShaders.end();
928 for( ; i != end; ++i )
930 mImpl->notificationManager.QueueMessage( ShaderCompiledMessage( factory, *i ) );
932 // we don't need them in update anymore
933 mImpl->updateCompiledShaders.clear();
938 void UpdateManager::UpdateRenderers( BufferIndex bufferIndex )
940 const Internal::OwnerContainer<Renderer*>& rendererContainer( mImpl->renderers.GetObjectContainer() );
941 unsigned int rendererCount( rendererContainer.Size() );
942 for( unsigned int i(0); i<rendererCount; ++i )
944 if( rendererContainer[i]->IsReferenced() )
946 rendererContainer[i]->PrepareResources(bufferIndex, mImpl->resourceManager);
947 rendererContainer[i]->PrepareRender( bufferIndex );
952 void UpdateManager::UpdateNodes( BufferIndex bufferIndex )
954 mImpl->nodeDirtyFlags = NothingFlag;
961 PERF_MONITOR_START( PerformanceMonitor::UPDATE_NODES );
963 // Prepare resources, update shaders, update attachments, for each node
964 // And add the renderers to the sorted layers. Start from root, which is also a layer
965 mImpl->nodeDirtyFlags = UpdateNodesAndAttachments( *( mImpl->root ),
967 mImpl->resourceManager,
968 mImpl->renderQueue );
970 if ( mImpl->systemLevelRoot )
972 mImpl->nodeDirtyFlags |= UpdateNodesAndAttachments( *( mImpl->systemLevelRoot ),
974 mImpl->resourceManager,
975 mImpl->renderQueue );
978 PERF_MONITOR_END( PerformanceMonitor::UPDATE_NODES );
981 unsigned int UpdateManager::Update( float elapsedSeconds,
982 unsigned int lastVSyncTimeMilliseconds,
983 unsigned int nextVSyncTimeMilliseconds )
985 PERF_MONITOR_END(PerformanceMonitor::FRAME_RATE); // Mark the End of the last frame
986 PERF_MONITOR_NEXT_FRAME(); // Prints out performance info for the last frame (if enabled)
987 PERF_MONITOR_START(PerformanceMonitor::FRAME_RATE); // Mark the start of this current frame
989 // Measure the time spent in UpdateManager::Update
990 PERF_MONITOR_START(PerformanceMonitor::UPDATE);
992 const BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
994 // Update the frame time delta on the render thread.
995 mImpl->renderManager.SetFrameDeltaTime(elapsedSeconds);
997 // 1) Clear nodes/resources which were previously discarded
998 mImpl->discardQueue.Clear( bufferIndex );
1000 // 2) Grab any loaded resources
1001 bool resourceChanged = mImpl->resourceManager.UpdateCache( bufferIndex );
1003 // 3) Process Touches & Gestures
1004 mImpl->touchResampler.Update();
1005 const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
1007 const bool updateScene = // The scene-graph requires an update if..
1008 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
1009 IsAnimationRunning() || // ..at least one animation is running OR
1010 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
1011 resourceChanged || // ..one or more resources were updated/changed OR
1012 gestureUpdated; // ..a gesture property was updated
1015 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
1016 // values if the scene was updated in the previous frame.
1017 if( updateScene || mImpl->previousUpdateScene )
1019 // 4) Reset properties from the previous update
1020 ResetProperties( bufferIndex );
1023 // 5) Process the queued scene messages
1024 mImpl->messageQueue.ProcessMessages( bufferIndex );
1026 // 6) Post Process Ids of resources updated by renderer
1027 mImpl->resourceManager.PostProcessResources( bufferIndex );
1029 // 6.1) Forward compiled shader programs to event thread for saving
1030 ForwardCompiledShadersToEventThread();
1032 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
1033 // renderer lists if the scene was updated in the previous frame.
1034 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
1035 if( updateScene || mImpl->previousUpdateScene )
1038 Animate( bufferIndex, elapsedSeconds );
1040 // 8) Apply Constraints
1041 ApplyConstraints( bufferIndex );
1043 // 9) Check Property Notifications
1044 ProcessPropertyNotifications( bufferIndex );
1046 // 10) Clear the lists of renderable-attachments from the previous update
1047 ClearRenderables( mImpl->sortedLayers );
1048 ClearRenderables( mImpl->systemLevelSortedLayers );
1050 // 11) Update node hierarchy and perform sorting / culling.
1051 // This will populate each Layer with a list of renderers which are ready.
1052 UpdateNodes( bufferIndex );
1053 UpdateRenderers( bufferIndex );
1056 // 12) Prepare for the next render
1057 PERF_MONITOR_START(PerformanceMonitor::PREPARE_RENDERABLES);
1059 PrepareRenderables( bufferIndex, mImpl->sortedLayers );
1060 PrepareRenderables( bufferIndex, mImpl->systemLevelSortedLayers );
1061 PERF_MONITOR_END(PerformanceMonitor::PREPARE_RENDERABLES);
1063 PERF_MONITOR_START(PerformanceMonitor::PROCESS_RENDER_TASKS);
1065 // 14) Process the RenderTasks; this creates the instructions for rendering the next frame.
1066 // reset the update buffer index and make sure there is enough room in the instruction container
1067 mImpl->renderInstructions.ResetAndReserve( bufferIndex,
1068 mImpl->taskList.GetTasks().Count() + mImpl->systemLevelTaskList.GetTasks().Count() );
1070 if ( NULL != mImpl->root )
1072 ProcessRenderTasks( bufferIndex,
1073 mImpl->completeStatusManager,
1076 mImpl->sortedLayers,
1077 mImpl->renderSortingHelper,
1078 mImpl->renderInstructions );
1080 // Process the system-level RenderTasks last
1081 if ( NULL != mImpl->systemLevelRoot )
1083 ProcessRenderTasks( bufferIndex,
1084 mImpl->completeStatusManager,
1085 mImpl->systemLevelTaskList,
1086 *mImpl->systemLevelRoot,
1087 mImpl->systemLevelSortedLayers,
1088 mImpl->renderSortingHelper,
1089 mImpl->renderInstructions );
1094 // check the countdown and notify (note, at the moment this is only done for normal tasks, not for systemlevel tasks)
1095 bool doRenderOnceNotify = false;
1096 mImpl->renderTaskWaiting = false;
1097 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
1098 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(), endIter = tasks.End();
1099 endIter != iter; ++iter )
1101 RenderTask& renderTask(*(*iter));
1103 renderTask.UpdateState();
1105 if( renderTask.IsWaitingToRender() &&
1106 renderTask.ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
1108 mImpl->renderTaskWaiting = true; // keep update/render threads alive
1111 if( renderTask.HasRendered() )
1113 doRenderOnceNotify = true;
1117 if( doRenderOnceNotify )
1119 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
1120 mImpl->notificationManager.QueueCompleteNotification( mImpl->taskList.GetCompleteNotificationInterface() );
1123 PERF_MONITOR_END(PerformanceMonitor::PROCESS_RENDER_TASKS);
1125 // Macro is undefined in release build.
1126 SNAPSHOT_NODE_LOGGING;
1128 // A ResetProperties() may be required in the next frame
1129 mImpl->previousUpdateScene = updateScene;
1131 // Check whether further updates are required
1132 unsigned int keepUpdating = KeepUpdatingCheck( elapsedSeconds );
1134 #ifdef PERFORMANCE_MONITOR_ENABLED
1135 // Always keep rendering when measuring FPS
1136 keepUpdating |= KeepUpdating::MONITORING_PERFORMANCE;
1139 // tell the update manager that we're done so the queue can be given to event thread
1140 mImpl->notificationManager.UpdateCompleted();
1142 // The update has finished; swap the double-buffering indices
1143 mSceneGraphBuffers.Swap();
1145 PERF_MONITOR_END(PerformanceMonitor::UPDATE);
1147 return keepUpdating;
1150 unsigned int UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
1152 // Update the duration set via Stage::KeepRendering()
1153 if ( mImpl->keepRenderingSeconds > 0.0f )
1155 mImpl->keepRenderingSeconds -= elapsedSeconds;
1158 unsigned int keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
1160 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
1161 // Keep updating until no messages are received and no animations are running.
1162 // If an animation has just finished, update at least once more for Discard end-actions.
1163 // No need to check for renderQueue as there is always a render after update and if that
1164 // render needs another update it will tell the adaptor to call update again
1166 if ( mImpl->keepRenderingSeconds > 0.0f )
1168 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
1171 if ( IsAnimationRunning() ||
1172 mImpl->animationFinishedDuringUpdate )
1174 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
1177 if ( mImpl->renderTaskWaiting )
1179 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
1182 return keepUpdatingRequest;
1185 void UpdateManager::SetBackgroundColor( const Vector4& color )
1187 typedef MessageValue1< RenderManager, Vector4 > 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::SetBackgroundColor, color );
1196 void UpdateManager::SetDefaultSurfaceRect( const Rect<int>& rect )
1198 typedef MessageValue1< RenderManager, Rect<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::SetDefaultSurfaceRect, rect );
1207 void UpdateManager::KeepRendering( float durationSeconds )
1209 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1212 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, bool systemLevel )
1216 // just copy the vector of pointers
1217 mImpl->sortedLayers = layers;
1221 mImpl->systemLevelSortedLayers = layers;
1225 void UpdateManager::SetShaderSaver( ShaderSaver& upstream )
1227 mImpl->shaderSaver = &upstream;
1230 } // namespace SceneGraph
1232 } // namespace Internal