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>
25 #include <dali/devel-api/common/owner-container.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/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-geometry.h>
63 #include <dali/internal/update/resources/resource-manager.h>
64 #include <dali/internal/update/resources/complete-status-manager.h>
65 #include <dali/internal/update/touch/touch-resampler.h>
67 #include <dali/internal/render/common/render-instruction-container.h>
68 #include <dali/internal/render/common/render-manager.h>
69 #include <dali/internal/render/queue/render-queue.h>
70 #include <dali/internal/render/common/performance-monitor.h>
71 #include <dali/internal/render/gl-resources/texture-cache.h>
72 #include <dali/internal/render/shaders/scene-graph-shader.h>
73 #include <dali/internal/render/renderers/render-sampler.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 propertyBuffers( sceneGraphBuffers, discardQueue ),
182 messageQueue( renderController, sceneGraphBuffers ),
183 keepRenderingSeconds( 0.0f ),
184 animationFinishedDuringUpdate( false ),
185 nodeDirtyFlags( TransformFlag ), // set to TransformFlag to ensure full update the first time through Update()
186 previousUpdateScene( false ),
188 renderSortingHelper(),
189 renderTaskWaiting( false )
191 sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue, textureCache, completeStatusManager );
193 renderers.SetSceneController( *sceneController );
194 geometries.SetSceneController( *sceneController );
195 materials.SetSceneController( *sceneController );
196 propertyBuffers.SetSceneController( *sceneController );
201 // Disconnect render tasks from nodes, before destroying the nodes
202 RenderTaskList::RenderTaskContainer& tasks = taskList.GetTasks();
203 for (RenderTaskList::RenderTaskContainer::Iterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
205 (*iter)->SetSourceNode( NULL );
207 // ..repeat for system level RenderTasks
208 RenderTaskList::RenderTaskContainer& systemLevelTasks = systemLevelTaskList.GetTasks();
209 for (RenderTaskList::RenderTaskContainer::Iterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
211 (*iter)->SetSourceNode( NULL );
214 // UpdateManager owns the Nodes
215 DestroyNodeSet( activeDisconnectedNodes );
216 DestroyNodeSet( connectedNodes );
217 DestroyNodeSet( disconnectedNodes );
219 // If there is root, reset it, otherwise do nothing as rendering was never started
228 if( systemLevelRoot )
230 systemLevelRoot->OnDestroy();
232 delete systemLevelRoot;
233 systemLevelRoot = NULL;
236 sceneController->GetTextureCache().SetBufferIndices(NULL); // TODO - Remove
237 delete sceneController;
240 SceneGraphBuffers sceneGraphBuffers; ///< Used to keep track of which buffers are being written or read
241 RenderMessageDispatcher renderMessageDispatcher; ///< Used for passing messages to the render-thread
242 NotificationManager& notificationManager; ///< Queues notification messages for the event-thread.
243 CompleteNotificationInterface& animationFinishedNotifier; ///< Provides notification to applications when animations are finished.
244 PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
245 ShaderSaver* shaderSaver; ///< Saves shader binaries.
246 ResourceManager& resourceManager; ///< resource manager
247 DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
248 RenderController& renderController; ///< render controller
249 SceneControllerImpl* sceneController; ///< scene controller
250 RenderManager& renderManager; ///< This is responsible for rendering the results of each "update"
251 RenderQueue& renderQueue; ///< Used to queue messages for the next render
252 RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions
253 CompleteStatusManager completeStatusManager; ///< Complete Status Manager
254 TouchResampler& touchResampler; ///< Used to resample touch events on every update.
256 Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
258 RenderTaskList taskList; ///< The list of scene graph render-tasks
259 RenderTaskList systemLevelTaskList; ///< Separate render-tasks for system-level content
261 Layer* root; ///< The root node (root is a layer)
262 Layer* systemLevelRoot; ///< A separate root-node for system-level content
263 std::set< Node* > activeDisconnectedNodes; ///< A container of new or modified nodes (without parent) owned by UpdateManager
264 std::set< Node* > connectedNodes; ///< A container of connected (with parent) nodes owned by UpdateManager
265 std::set< Node* > disconnectedNodes; ///< A container of inactive disconnected nodes (without parent) owned by UpdateManager
267 SortedLayerPointers sortedLayers; ///< A container of Layer pointers sorted by depth
268 SortedLayerPointers systemLevelSortedLayers; ///< A separate container of system-level Layers
270 OwnerContainer< PropertyOwner* > customObjects; ///< A container of owned objects (with custom properties)
272 AnimationContainer animations; ///< A container of owned animations
273 PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
275 ObjectOwnerContainer<Renderer> renderers;
276 ObjectOwnerContainer<Geometry> geometries; ///< A container of geometries
277 ObjectOwnerContainer<Material> materials; ///< A container of materials
278 ObjectOwnerContainer<PropertyBuffer> propertyBuffers; ///< A container of property buffers
280 ShaderContainer shaders; ///< A container of owned shaders
282 MessageQueue messageQueue; ///< The messages queued from the event-thread
283 ShaderDataBinaryQueue renderCompiledShaders; ///< Shaders compiled on Render thread are inserted here for update thread to pass on to event thread.
284 ShaderDataBinaryQueue updateCompiledShaders; ///< Shaders to be sent from Update to Event
285 Mutex compiledShaderMutex; ///< lock to ensure no corruption on the renderCompiledShaders
287 float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
288 bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
290 int nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
291 bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
293 int frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
294 RendererSortingHelper renderSortingHelper; ///< helper used to sort transparent renderers
296 GestureContainer gestures; ///< A container of owned gesture detectors
297 bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
300 UpdateManager::UpdateManager( NotificationManager& notificationManager,
301 GlSyncAbstraction& glSyncAbstraction,
302 CompleteNotificationInterface& animationFinishedNotifier,
303 PropertyNotifier& propertyNotifier,
304 ResourceManager& resourceManager,
305 DiscardQueue& discardQueue,
306 RenderController& controller,
307 RenderManager& renderManager,
308 RenderQueue& renderQueue,
309 TextureCache& textureCache,
310 TouchResampler& touchResampler )
313 mImpl = new Impl( notificationManager,
315 animationFinishedNotifier,
324 mSceneGraphBuffers );
326 textureCache.SetBufferIndices( &mSceneGraphBuffers );
329 UpdateManager::~UpdateManager()
334 void UpdateManager::InstallRoot( SceneGraph::Layer* layer, bool systemLevel )
336 DALI_ASSERT_DEBUG( layer->IsLayer() );
337 DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
341 DALI_ASSERT_DEBUG( mImpl->root == NULL && "Root Node already installed" );
346 DALI_ASSERT_DEBUG( mImpl->systemLevelRoot == NULL && "System-level Root Node already installed" );
347 mImpl->systemLevelRoot = layer;
350 layer->SetRoot(true);
353 void UpdateManager::AddNode( Node* node )
355 DALI_ASSERT_ALWAYS( NULL != node );
356 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
358 mImpl->activeDisconnectedNodes.insert( node ); // Takes ownership of node
361 void UpdateManager::ConnectNode( Node* parent, Node* node )
363 DALI_ASSERT_ALWAYS( NULL != parent );
364 DALI_ASSERT_ALWAYS( NULL != node );
365 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
367 // Move from active/disconnectedNodes to connectedNodes
368 std::set<Node*>::size_type removed = mImpl->activeDisconnectedNodes.erase( node );
371 removed = mImpl->disconnectedNodes.erase( node );
372 DALI_ASSERT_ALWAYS( removed );
374 mImpl->connectedNodes.insert( node );
376 node->SetActive( true );
378 parent->ConnectChild( node );
381 void UpdateManager::DisconnectNode( Node* node )
383 Node* parent = node->GetParent();
384 DALI_ASSERT_ALWAYS( NULL != parent );
385 parent->SetDirtyFlag( ChildDeletedFlag ); // make parent dirty so that render items dont get reused
387 // Move from connectedNodes to activeDisconnectedNodes (reset properties next frame)
388 parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node, mImpl->connectedNodes, mImpl->activeDisconnectedNodes );
391 void UpdateManager::SetNodeActive( Node* node )
393 DALI_ASSERT_ALWAYS( NULL != node );
394 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
396 // Move from disconnectedNodes to activeDisconnectedNodes (reset properties next frame)
397 std::set<Node*>::size_type removed = mImpl->disconnectedNodes.erase( node );
398 DALI_ASSERT_ALWAYS( removed );
399 mImpl->activeDisconnectedNodes.insert( node );
401 node->SetActive( true );
404 void UpdateManager::DestroyNode( Node* node )
406 DALI_ASSERT_ALWAYS( NULL != node );
407 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
409 // Transfer ownership from new/disconnectedNodes to the discard queue
410 // This keeps the nodes alive, until the render-thread has finished with them
411 std::set<Node*>::size_type removed = mImpl->activeDisconnectedNodes.erase( node );
414 removed = mImpl->disconnectedNodes.erase( node );
415 DALI_ASSERT_ALWAYS( removed );
417 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
419 // Notify the Node about impending destruction
423 //@todo MESH_REWORK Extend to allow arbitrary scene objects to connect to each other
424 void UpdateManager::AttachToNode( Node* node, NodeAttachment* attachment )
426 DALI_ASSERT_DEBUG( node != NULL );
427 DALI_ASSERT_DEBUG( attachment != NULL );
429 // attach node to attachment first so that parent is known by the time attachment is connected
430 node->Attach( *attachment ); // node takes ownership
432 // @todo MESH_REWORK Remove after merge of SceneGraph::RenderableAttachment and SceneGraph::RendererAttachment
433 if( dynamic_cast<SceneGraph::ImageAttachment*>( attachment ) != NULL )
435 attachment->Initialize( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
439 void UpdateManager::AddObject( PropertyOwner* object )
441 DALI_ASSERT_DEBUG( NULL != object );
443 mImpl->customObjects.PushBack( object );
446 void UpdateManager::RemoveObject( PropertyOwner* object )
448 DALI_ASSERT_DEBUG( NULL != object );
450 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
452 // Find the object and destroy it
453 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); iter != customObjects.End(); ++iter )
455 PropertyOwner* current = *iter;
456 if ( current == object )
458 customObjects.Erase( iter );
463 // Should not reach here
464 DALI_ASSERT_DEBUG(false);
467 void UpdateManager::AddAnimation( Animation* animation )
469 mImpl->animations.PushBack( animation );
472 void UpdateManager::StopAnimation( Animation* animation )
474 DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
476 bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
478 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
481 void UpdateManager::RemoveAnimation( Animation* animation )
483 DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
485 animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
487 DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
490 bool UpdateManager::IsAnimationRunning() const
492 bool isRunning(false);
493 AnimationContainer& animations = mImpl->animations;
495 // Find any animation that isn't stopped or paused
497 const AnimationIter endIter = animations.End();
498 for ( AnimationIter iter = animations.Begin(); !isRunning && iter != endIter; ++iter )
500 const Animation::State state = (*iter)->GetState();
502 if (state != Animation::Stopped &&
503 state != Animation::Paused)
512 void UpdateManager::AddPropertyNotification( PropertyNotification* propertyNotification )
514 mImpl->propertyNotifications.PushBack( propertyNotification );
517 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
519 PropertyNotificationContainer &propertyNotifications = mImpl->propertyNotifications;
520 PropertyNotificationIter iter = propertyNotifications.Begin();
522 while ( iter != propertyNotifications.End() )
524 if( *iter == propertyNotification )
526 propertyNotifications.Erase(iter);
533 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
535 DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
536 propertyNotification->SetNotifyMode( notifyMode );
539 ObjectOwnerContainer<Geometry>& UpdateManager::GetGeometryOwner()
541 return mImpl->geometries;
544 ObjectOwnerContainer<Renderer>& UpdateManager::GetRendererOwner()
546 return mImpl->renderers;
550 ObjectOwnerContainer<Material>& UpdateManager::GetMaterialOwner()
552 return mImpl->materials;
555 ObjectOwnerContainer<PropertyBuffer>& UpdateManager::GetPropertyBufferOwner()
557 return mImpl->propertyBuffers;
560 void UpdateManager::AddShader( Shader* shader )
562 DALI_ASSERT_DEBUG( NULL != shader );
564 if( mImpl->shaders.Count() == 0 )
566 // the first added shader becomes our default shader
567 // Construct message in the render queue memory; note that delete should not be called on the return value
568 typedef MessageValue1< RenderManager, Shader* > DerivedType;
570 // Reserve some memory inside the render queue
571 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
573 // Construct message in the render queue memory; note that delete should not be called on the return value
574 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultShader, shader );
577 mImpl->shaders.PushBack( shader );
579 // Allows the shader to dispatch texture requests to the cache
580 shader->Initialize( mImpl->renderQueue, mImpl->sceneController->GetTextureCache() );
583 void UpdateManager::RemoveShader( Shader* shader )
585 DALI_ASSERT_DEBUG(shader != NULL);
587 ShaderContainer& shaders = mImpl->shaders;
589 // Find the shader and destroy it
590 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
592 Shader& current = **iter;
593 if ( ¤t == shader )
595 // Transfer ownership to the discard queue
596 // This keeps the shader alive, until the render-thread has finished with it
597 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), shaders.Release( iter ) );
602 // Should not reach here
603 DALI_ASSERT_DEBUG(false);
606 void UpdateManager::SetShaderProgram( Shader* shader,
607 Internal::ShaderDataPtr shaderData, bool modifiesGeometry )
612 typedef MessageValue3< Shader, Internal::ShaderDataPtr, ProgramCache*, bool> DerivedType;
614 // Reserve some memory inside the render queue
615 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
617 // Construct message in the render queue memory; note that delete should not be called on the return value
618 new (slot) DerivedType( shader, &Shader::SetProgram, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
622 void UpdateManager::SaveBinary( Internal::ShaderDataPtr shaderData )
624 DALI_ASSERT_DEBUG( shaderData && "No NULL shader data pointers please." );
625 DALI_ASSERT_DEBUG( shaderData->GetBufferSize() > 0 && "Shader binary empty so nothing to save." );
627 // lock as update might be sending previously compiled shaders to event thread
628 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
629 mImpl->renderCompiledShaders.push_back( shaderData );
633 RenderTaskList* UpdateManager::GetRenderTaskList( bool systemLevel )
637 // copy the list, this is only likely to happen once in application life cycle
638 return &(mImpl->taskList);
642 // copy the list, this is only likely to happen once in application life cycle
643 return &(mImpl->systemLevelTaskList);
647 void UpdateManager::AddGesture( PanGesture* gesture )
649 DALI_ASSERT_DEBUG( NULL != gesture );
651 mImpl->gestures.PushBack( gesture );
654 void UpdateManager::RemoveGesture( PanGesture* gesture )
656 DALI_ASSERT_DEBUG( gesture != NULL );
658 GestureContainer& gestures = mImpl->gestures;
660 // Find the gesture and destroy it
661 for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
663 PanGesture& current = **iter;
664 if ( ¤t == gesture )
666 mImpl->gestures.Erase( iter );
670 // Should not reach here
671 DALI_ASSERT_DEBUG(false);
674 unsigned int* UpdateManager::ReserveMessageSlot( std::size_t size, bool updateScene )
676 return mImpl->messageQueue.ReserveMessageSlot( size, updateScene );
679 void UpdateManager::EventProcessingStarted()
681 mImpl->messageQueue.EventProcessingStarted();
684 bool UpdateManager::FlushQueue()
686 return mImpl->messageQueue.FlushQueue();
689 void UpdateManager::ResetProperties( BufferIndex bufferIndex )
691 PERF_MONITOR_START(PerformanceMonitor::RESET_PROPERTIES);
693 // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
694 mImpl->animationFinishedDuringUpdate = false;
696 // Animated properties have to be reset to their original value each frame
698 // Reset root properties
701 mImpl->root->ResetToBaseValues( bufferIndex );
703 if ( mImpl->systemLevelRoot )
705 mImpl->systemLevelRoot->ResetToBaseValues( bufferIndex );
708 // Reset the Connected Nodes
709 const std::set<Node*>::iterator endIter = mImpl->connectedNodes.end();
710 for( std::set<Node*>::iterator iter = mImpl->connectedNodes.begin(); endIter != iter; ++iter )
712 (*iter)->ResetToBaseValues( bufferIndex );
715 // If a Node is disconnected, it may still be "active" (requires a reset in next frame)
716 for( std::set<Node*>::iterator iter = mImpl->activeDisconnectedNodes.begin(); mImpl->activeDisconnectedNodes.end() != iter; iter = mImpl->activeDisconnectedNodes.begin() )
719 node->ResetToBaseValues( bufferIndex );
720 node->SetActive( false );
722 // Move everything from activeDisconnectedNodes to disconnectedNodes (no need to reset again)
723 mImpl->activeDisconnectedNodes.erase( iter );
724 mImpl->disconnectedNodes.insert( node );
727 // Reset system-level render-task list properties to base values
728 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
730 for (RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
732 (*iter)->ResetToBaseValues( bufferIndex );
735 // Reset render-task list properties to base values.
736 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
738 for (RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
740 (*iter)->ResetToBaseValues( bufferIndex );
743 // Reset custom object properties to base values
744 for (OwnerContainer<PropertyOwner*>::Iterator iter = mImpl->customObjects.Begin(); iter != mImpl->customObjects.End(); ++iter)
746 (*iter)->ResetToBaseValues( bufferIndex );
749 mImpl->materials.ResetToBaseValues( bufferIndex );
750 mImpl->geometries.ResetToBaseValues( bufferIndex );
751 mImpl->propertyBuffers.ResetToBaseValues( bufferIndex );
752 mImpl->renderers.ResetToBaseValues( bufferIndex );
755 // Reset animatable shader properties to base values
756 for (ShaderIter iter = mImpl->shaders.Begin(); iter != mImpl->shaders.End(); ++iter)
758 (*iter)->ResetToBaseValues( bufferIndex );
761 PERF_MONITOR_END(PerformanceMonitor::RESET_PROPERTIES);
764 bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds )
766 bool gestureUpdated( false );
768 // constrain gestures... (in construction order)
769 GestureContainer& gestures = mImpl->gestures;
771 for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
773 PanGesture& gesture = **iter;
774 gesture.ResetToBaseValues( bufferIndex ); // Needs to be done every time as gesture data is written directly to an update-buffer rather than via a message
775 gestureUpdated |= gesture.UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
778 return gestureUpdated;
781 void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
783 PERF_MONITOR_START(PerformanceMonitor::ANIMATE_NODES);
785 AnimationContainer &animations = mImpl->animations;
786 AnimationIter iter = animations.Begin();
787 while ( iter != animations.End() )
789 Animation* animation = *iter;
790 bool finished = animation->Update( bufferIndex, elapsedSeconds );
792 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
794 // Remove animations that had been destroyed but were still waiting for an update
795 if (animation->GetState() == Animation::Destroyed)
797 iter = animations.Erase(iter);
805 if ( mImpl->animationFinishedDuringUpdate )
807 // The application should be notified by NotificationManager, in another thread
808 mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationFinishedNotifier );
811 PERF_MONITOR_END(PerformanceMonitor::ANIMATE_NODES);
814 void UpdateManager::ApplyConstraints( BufferIndex bufferIndex )
816 PERF_MONITOR_START(PerformanceMonitor::APPLY_CONSTRAINTS);
818 // constrain custom objects... (in construction order)
819 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
821 const OwnerContainer< PropertyOwner* >::Iterator endIter = customObjects.End();
822 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); endIter != iter; ++iter )
824 PropertyOwner& object = **iter;
825 ConstrainPropertyOwner( object, bufferIndex );
828 // constrain nodes... (in Depth First traversal order)
831 ConstrainNodes( *(mImpl->root), bufferIndex );
834 if ( mImpl->systemLevelRoot )
836 ConstrainNodes( *(mImpl->systemLevelRoot), bufferIndex );
839 // constrain other property-owners after nodes as they are more likely to depend on a node's
840 // current frame property than vice versa. They tend to be final constraints (no further
841 // constraints depend on their properties)
842 // e.g. ShaderEffect uniform a function of Actor's position.
843 // Mesh vertex a function of Actor's position or world position.
845 // TODO: refactor this code (and reset nodes) as these are all just lists of property-owners
846 // they can be all processed in a super-list of property-owners.
848 // Constrain system-level render-tasks
849 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
851 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter )
853 RenderTask& task = **iter;
854 ConstrainPropertyOwner( task, bufferIndex );
857 // Constrain render-tasks
858 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
860 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter )
862 RenderTask& task = **iter;
863 ConstrainPropertyOwner( task, bufferIndex );
866 // Constrain Materials and geometries
867 mImpl->materials.ConstrainObjects( bufferIndex );
868 mImpl->geometries.ConstrainObjects( bufferIndex );
869 mImpl->propertyBuffers.ConstrainObjects( bufferIndex );
870 mImpl->renderers.ConstrainObjects( bufferIndex );
872 // constrain shaders... (in construction order)
873 ShaderContainer& shaders = mImpl->shaders;
875 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
877 Shader& shader = **iter;
878 ConstrainPropertyOwner( shader, bufferIndex );
881 PERF_MONITOR_END(PerformanceMonitor::APPLY_CONSTRAINTS);
884 void UpdateManager::ProcessPropertyNotifications( BufferIndex bufferIndex )
886 PropertyNotificationContainer ¬ifications = mImpl->propertyNotifications;
887 PropertyNotificationIter iter = notifications.Begin();
889 while ( iter != notifications.End() )
891 PropertyNotification* notification = *iter;
892 bool valid = notification->Check( bufferIndex );
895 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
901 void UpdateManager::ForwardCompiledShadersToEventThread()
903 DALI_ASSERT_DEBUG( (mImpl->shaderSaver != 0) && "shaderSaver should be wired-up during startup." );
904 if( mImpl->shaderSaver )
906 // lock and swap the queues
908 // render might be attempting to send us more binaries at the same time
909 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
910 mImpl->renderCompiledShaders.swap( mImpl->updateCompiledShaders );
913 if( mImpl->updateCompiledShaders.size() > 0 )
915 ShaderSaver& factory = *mImpl->shaderSaver;
916 ShaderDataBinaryQueue::iterator i = mImpl->updateCompiledShaders.begin();
917 ShaderDataBinaryQueue::iterator end = mImpl->updateCompiledShaders.end();
918 for( ; i != end; ++i )
920 mImpl->notificationManager.QueueMessage( ShaderCompiledMessage( factory, *i ) );
922 // we don't need them in update anymore
923 mImpl->updateCompiledShaders.clear();
928 void UpdateManager::UpdateRenderers( BufferIndex bufferIndex )
930 const OwnerContainer<Renderer*>& rendererContainer( mImpl->renderers.GetObjectContainer() );
931 unsigned int rendererCount( rendererContainer.Size() );
932 for( unsigned int i(0); i<rendererCount; ++i )
934 if( rendererContainer[i]->IsReferenced() )
936 rendererContainer[i]->PrepareResources(bufferIndex, mImpl->resourceManager);
937 rendererContainer[i]->PrepareRender( bufferIndex );
942 void UpdateManager::UpdateNodes( BufferIndex bufferIndex )
944 mImpl->nodeDirtyFlags = NothingFlag;
951 PERF_MONITOR_START( PerformanceMonitor::UPDATE_NODES );
953 // Prepare resources, update shaders, update attachments, for each node
954 // And add the renderers to the sorted layers. Start from root, which is also a layer
955 mImpl->nodeDirtyFlags = UpdateNodesAndAttachments( *( mImpl->root ),
957 mImpl->resourceManager,
958 mImpl->renderQueue );
960 if ( mImpl->systemLevelRoot )
962 mImpl->nodeDirtyFlags |= UpdateNodesAndAttachments( *( mImpl->systemLevelRoot ),
964 mImpl->resourceManager,
965 mImpl->renderQueue );
968 PERF_MONITOR_END( PerformanceMonitor::UPDATE_NODES );
971 unsigned int UpdateManager::Update( float elapsedSeconds,
972 unsigned int lastVSyncTimeMilliseconds,
973 unsigned int nextVSyncTimeMilliseconds )
975 PERF_MONITOR_END(PerformanceMonitor::FRAME_RATE); // Mark the End of the last frame
976 PERF_MONITOR_NEXT_FRAME(); // Prints out performance info for the last frame (if enabled)
977 PERF_MONITOR_START(PerformanceMonitor::FRAME_RATE); // Mark the start of this current frame
979 // Measure the time spent in UpdateManager::Update
980 PERF_MONITOR_START(PerformanceMonitor::UPDATE);
982 const BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
984 // Update the frame time delta on the render thread.
985 mImpl->renderManager.SetFrameDeltaTime(elapsedSeconds);
987 // 1) Clear nodes/resources which were previously discarded
988 mImpl->discardQueue.Clear( bufferIndex );
990 // 2) Grab any loaded resources
991 bool resourceChanged = mImpl->resourceManager.UpdateCache( bufferIndex );
993 // 3) Process Touches & Gestures
994 mImpl->touchResampler.Update();
995 const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
997 const bool updateScene = // The scene-graph requires an update if..
998 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
999 IsAnimationRunning() || // ..at least one animation is running OR
1000 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
1001 resourceChanged || // ..one or more resources were updated/changed OR
1002 gestureUpdated; // ..a gesture property was updated
1005 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
1006 // values if the scene was updated in the previous frame.
1007 if( updateScene || mImpl->previousUpdateScene )
1009 // 4) Reset properties from the previous update
1010 ResetProperties( bufferIndex );
1013 // 5) Process the queued scene messages
1014 mImpl->messageQueue.ProcessMessages( bufferIndex );
1016 // 6) Post Process Ids of resources updated by renderer
1017 mImpl->resourceManager.PostProcessResources( bufferIndex );
1019 // 6.1) Forward compiled shader programs to event thread for saving
1020 ForwardCompiledShadersToEventThread();
1022 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
1023 // renderer lists if the scene was updated in the previous frame.
1024 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
1025 if( updateScene || mImpl->previousUpdateScene )
1028 Animate( bufferIndex, elapsedSeconds );
1030 // 8) Apply Constraints
1031 ApplyConstraints( bufferIndex );
1033 // 9) Check Property Notifications
1034 ProcessPropertyNotifications( bufferIndex );
1036 // 10) Clear the lists of renderable-attachments from the previous update
1037 ClearRenderables( mImpl->sortedLayers );
1038 ClearRenderables( mImpl->systemLevelSortedLayers );
1040 // 11) Update node hierarchy and perform sorting / culling.
1041 // This will populate each Layer with a list of renderers which are ready.
1042 UpdateNodes( bufferIndex );
1043 UpdateRenderers( bufferIndex );
1046 // 12) Prepare for the next render
1047 PERF_MONITOR_START(PerformanceMonitor::PREPARE_RENDERABLES);
1049 PrepareRenderables( bufferIndex, mImpl->sortedLayers );
1050 PrepareRenderables( bufferIndex, mImpl->systemLevelSortedLayers );
1051 PERF_MONITOR_END(PerformanceMonitor::PREPARE_RENDERABLES);
1053 PERF_MONITOR_START(PerformanceMonitor::PROCESS_RENDER_TASKS);
1055 // 14) Process the RenderTasks; this creates the instructions for rendering the next frame.
1056 // reset the update buffer index and make sure there is enough room in the instruction container
1057 mImpl->renderInstructions.ResetAndReserve( bufferIndex,
1058 mImpl->taskList.GetTasks().Count() + mImpl->systemLevelTaskList.GetTasks().Count() );
1060 if ( NULL != mImpl->root )
1062 ProcessRenderTasks( bufferIndex,
1063 mImpl->completeStatusManager,
1066 mImpl->sortedLayers,
1067 mImpl->renderSortingHelper,
1068 mImpl->renderInstructions );
1070 // Process the system-level RenderTasks last
1071 if ( NULL != mImpl->systemLevelRoot )
1073 ProcessRenderTasks( bufferIndex,
1074 mImpl->completeStatusManager,
1075 mImpl->systemLevelTaskList,
1076 *mImpl->systemLevelRoot,
1077 mImpl->systemLevelSortedLayers,
1078 mImpl->renderSortingHelper,
1079 mImpl->renderInstructions );
1084 // check the countdown and notify (note, at the moment this is only done for normal tasks, not for systemlevel tasks)
1085 bool doRenderOnceNotify = false;
1086 mImpl->renderTaskWaiting = false;
1087 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
1088 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(), endIter = tasks.End();
1089 endIter != iter; ++iter )
1091 RenderTask& renderTask(*(*iter));
1093 renderTask.UpdateState();
1095 if( renderTask.IsWaitingToRender() &&
1096 renderTask.ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
1098 mImpl->renderTaskWaiting = true; // keep update/render threads alive
1101 if( renderTask.HasRendered() )
1103 doRenderOnceNotify = true;
1107 if( doRenderOnceNotify )
1109 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
1110 mImpl->notificationManager.QueueCompleteNotification( mImpl->taskList.GetCompleteNotificationInterface() );
1113 PERF_MONITOR_END(PerformanceMonitor::PROCESS_RENDER_TASKS);
1115 // Macro is undefined in release build.
1116 SNAPSHOT_NODE_LOGGING;
1118 // A ResetProperties() may be required in the next frame
1119 mImpl->previousUpdateScene = updateScene;
1121 // Check whether further updates are required
1122 unsigned int keepUpdating = KeepUpdatingCheck( elapsedSeconds );
1124 #ifdef PERFORMANCE_MONITOR_ENABLED
1125 // Always keep rendering when measuring FPS
1126 keepUpdating |= KeepUpdating::MONITORING_PERFORMANCE;
1129 // tell the update manager that we're done so the queue can be given to event thread
1130 mImpl->notificationManager.UpdateCompleted();
1132 // The update has finished; swap the double-buffering indices
1133 mSceneGraphBuffers.Swap();
1135 PERF_MONITOR_END(PerformanceMonitor::UPDATE);
1137 return keepUpdating;
1140 unsigned int UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
1142 // Update the duration set via Stage::KeepRendering()
1143 if ( mImpl->keepRenderingSeconds > 0.0f )
1145 mImpl->keepRenderingSeconds -= elapsedSeconds;
1148 unsigned int keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
1150 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
1151 // Keep updating until no messages are received and no animations are running.
1152 // If an animation has just finished, update at least once more for Discard end-actions.
1153 // No need to check for renderQueue as there is always a render after update and if that
1154 // render needs another update it will tell the adaptor to call update again
1156 if ( mImpl->keepRenderingSeconds > 0.0f )
1158 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
1161 if ( IsAnimationRunning() ||
1162 mImpl->animationFinishedDuringUpdate )
1164 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
1167 if ( mImpl->renderTaskWaiting )
1169 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
1172 return keepUpdatingRequest;
1175 void UpdateManager::SetBackgroundColor( const Vector4& color )
1177 typedef MessageValue1< RenderManager, Vector4 > DerivedType;
1179 // Reserve some memory inside the render queue
1180 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1182 // Construct message in the render queue memory; note that delete should not be called on the return value
1183 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
1186 void UpdateManager::SetDefaultSurfaceRect( const Rect<int>& rect )
1188 typedef MessageValue1< RenderManager, Rect<int> > DerivedType;
1190 // Reserve some memory inside the render queue
1191 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1193 // Construct message in the render queue memory; note that delete should not be called on the return value
1194 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1197 void UpdateManager::KeepRendering( float durationSeconds )
1199 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1202 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, bool systemLevel )
1206 // just copy the vector of pointers
1207 mImpl->sortedLayers = layers;
1211 mImpl->systemLevelSortedLayers = layers;
1215 void UpdateManager::SetShaderSaver( ShaderSaver& upstream )
1217 mImpl->shaderSaver = &upstream;
1220 void UpdateManager::AddSampler( Render::Sampler* sampler )
1222 typedef MessageValue1< RenderManager, Render::Sampler* > DerivedType;
1224 // Reserve some memory inside the render queue
1225 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1227 // Construct message in the render queue memory; note that delete should not be called on the return value
1228 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddSampler, sampler );
1231 void UpdateManager::RemoveSampler( Render::Sampler* sampler )
1233 typedef MessageValue1< RenderManager, Render::Sampler* > DerivedType;
1235 // Reserve some memory inside the render queue
1236 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1238 // Construct message in the render queue memory; note that delete should not be called on the return value
1239 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveSampler, sampler );
1242 void UpdateManager::SetFilterMode( Render::Sampler* sampler, unsigned int minFilterMode, unsigned int magFilterMode )
1244 typedef MessageValue3< RenderManager, Render::Sampler*, unsigned int, unsigned int > DerivedType;
1246 // Reserve some memory inside the render queue
1247 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1249 // Construct message in the render queue memory; note that delete should not be called on the return value
1250 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetFilterMode, sampler, minFilterMode, magFilterMode );
1253 void UpdateManager::SetWrapMode( Render::Sampler* sampler, unsigned int uWrapMode, unsigned int vWrapMode )
1255 typedef MessageValue3< RenderManager, Render::Sampler*, unsigned int, unsigned int > DerivedType;
1257 // Reserve some memory inside the render queue
1258 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1260 // Construct message in the render queue memory; note that delete should not be called on the return value
1261 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetWrapMode, sampler, uWrapMode, vWrapMode );
1264 } // namespace SceneGraph
1266 } // namespace Internal