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-renderer-attachment.h>
56 #include <dali/internal/update/node-attachments/scene-graph-image-attachment.h>
57 #include <dali/internal/update/nodes/node.h>
58 #include <dali/internal/update/nodes/scene-graph-layer.h>
59 #include <dali/internal/update/queue/update-message-queue.h>
60 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
61 #include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
62 #include <dali/internal/update/rendering/scene-graph-material.h>
63 #include <dali/internal/update/rendering/scene-graph-sampler.h>
64 #include <dali/internal/update/rendering/scene-graph-geometry.h>
65 #include <dali/internal/update/resources/resource-manager.h>
66 #include <dali/internal/update/resources/complete-status-manager.h>
67 #include <dali/internal/update/touch/touch-resampler.h>
69 #include <dali/internal/render/common/render-instruction-container.h>
70 #include <dali/internal/render/common/render-manager.h>
71 #include <dali/internal/render/queue/render-queue.h>
72 #include <dali/internal/render/common/performance-monitor.h>
73 #include <dali/internal/render/gl-resources/texture-cache.h>
74 #include <dali/internal/render/shaders/scene-graph-shader.h>
76 // Un-comment to enable node tree debug logging
77 //#define NODE_TREE_LOGGING 1
79 #if ( defined( DEBUG_ENABLED ) && defined( NODE_TREE_LOGGING ) )
80 #define SNAPSHOT_NODE_LOGGING \
81 const int FRAME_COUNT_TRIGGER = 16;\
82 if( mImpl->frameCounter >= FRAME_COUNT_TRIGGER )\
84 if ( NULL != mImpl->root )\
86 mImpl->frameCounter = 0;\
87 PrintNodeTree( *mImpl->root, mSceneGraphBuffers.GetUpdateBufferIndex(), "" );\
90 mImpl->frameCounter++;
92 #define SNAPSHOT_NODE_LOGGING
95 #if defined(DEBUG_ENABLED)
96 extern Debug::Filter* gRenderTaskLogFilter;
100 using namespace Dali::Integration;
101 using Dali::Internal::Update::MessageQueue;
115 void DestroyNodeSet( std::set<Node*>& nodeSet )
117 for( std::set<Node*>::iterator iter = nodeSet.begin(); iter != nodeSet.end(); ++iter )
121 // Call Node::OnDestroy as each node is destroyed
131 typedef OwnerContainer< Shader* > ShaderContainer;
132 typedef ShaderContainer::Iterator ShaderIter;
133 typedef ShaderContainer::ConstIterator ShaderConstIter;
135 typedef std::vector<Internal::ShaderDataPtr> ShaderDataBinaryQueue;
137 typedef OwnerContainer<PanGesture*> GestureContainer;
138 typedef GestureContainer::Iterator GestureIter;
139 typedef GestureContainer::ConstIterator GestureConstIter;
143 * Structure to contain UpdateManager internal data
145 struct UpdateManager::Impl
147 Impl( NotificationManager& notificationManager,
148 GlSyncAbstraction& glSyncAbstraction,
149 CompleteNotificationInterface& animationFinishedNotifier,
150 PropertyNotifier& propertyNotifier,
151 ResourceManager& resourceManager,
152 DiscardQueue& discardQueue,
153 RenderController& renderController,
154 RenderManager& renderManager,
155 RenderQueue& renderQueue,
156 TextureCache& textureCache,
157 TouchResampler& touchResampler,
158 SceneGraphBuffers& sceneGraphBuffers )
160 renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ),
161 notificationManager( notificationManager ),
162 animationFinishedNotifier( animationFinishedNotifier ),
163 propertyNotifier( propertyNotifier ),
165 resourceManager( resourceManager ),
166 discardQueue( discardQueue ),
167 renderController( renderController ),
168 sceneController( NULL ),
169 renderManager( renderManager ),
170 renderQueue( renderQueue ),
171 renderInstructions( renderManager.GetRenderInstructionContainer() ),
172 completeStatusManager( glSyncAbstraction, renderMessageDispatcher, resourceManager ),
173 touchResampler( touchResampler ),
174 backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
175 taskList ( completeStatusManager ),
176 systemLevelTaskList ( completeStatusManager ),
178 systemLevelRoot( NULL ),
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 geometries.SetSceneController( *sceneController );
195 materials.SetSceneController( *sceneController );
196 propertyBuffers.SetSceneController( *sceneController );
197 samplers.SetSceneController( *sceneController );
202 // Disconnect render tasks from nodes, before destroying the nodes
203 RenderTaskList::RenderTaskContainer& tasks = taskList.GetTasks();
204 for (RenderTaskList::RenderTaskContainer::Iterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
206 (*iter)->SetSourceNode( NULL );
208 // ..repeat for system level RenderTasks
209 RenderTaskList::RenderTaskContainer& systemLevelTasks = systemLevelTaskList.GetTasks();
210 for (RenderTaskList::RenderTaskContainer::Iterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
212 (*iter)->SetSourceNode( NULL );
215 // UpdateManager owns the Nodes
216 DestroyNodeSet( activeDisconnectedNodes );
217 DestroyNodeSet( connectedNodes );
218 DestroyNodeSet( disconnectedNodes );
220 // If there is root, reset it, otherwise do nothing as rendering was never started
229 if( systemLevelRoot )
231 systemLevelRoot->OnDestroy();
233 delete systemLevelRoot;
234 systemLevelRoot = NULL;
237 sceneController->GetTextureCache().SetBufferIndices(NULL); // TODO - Remove
238 delete sceneController;
241 SceneGraphBuffers sceneGraphBuffers; ///< Used to keep track of which buffers are being written or read
242 RenderMessageDispatcher renderMessageDispatcher; ///< Used for passing messages to the render-thread
243 NotificationManager& notificationManager; ///< Queues notification messages for the event-thread.
244 CompleteNotificationInterface& animationFinishedNotifier; ///< Provides notification to applications when animations are finished.
245 PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
246 ShaderSaver* shaderSaver; ///< Saves shader binaries.
247 ResourceManager& resourceManager; ///< resource manager
248 DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
249 RenderController& renderController; ///< render controller
250 SceneControllerImpl* sceneController; ///< scene controller
251 RenderManager& renderManager; ///< This is responsible for rendering the results of each "update"
252 RenderQueue& renderQueue; ///< Used to queue messages for the next render
253 RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions
254 CompleteStatusManager completeStatusManager; ///< Complete Status Manager
255 TouchResampler& touchResampler; ///< Used to resample touch events on every update.
257 Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
259 RenderTaskList taskList; ///< The list of scene graph render-tasks
260 RenderTaskList systemLevelTaskList; ///< Separate render-tasks for system-level content
262 Layer* root; ///< The root node (root is a layer)
263 Layer* systemLevelRoot; ///< A separate root-node for system-level content
264 std::set< Node* > activeDisconnectedNodes; ///< A container of new or modified nodes (without parent) owned by UpdateManager
265 std::set< Node* > connectedNodes; ///< A container of connected (with parent) nodes owned by UpdateManager
266 std::set< Node* > disconnectedNodes; ///< A container of inactive disconnected nodes (without parent) owned by UpdateManager
268 SortedLayerPointers sortedLayers; ///< A container of Layer pointers sorted by depth
269 SortedLayerPointers systemLevelSortedLayers; ///< A separate container of system-level Layers
271 OwnerContainer< PropertyOwner* > customObjects; ///< A container of owned objects (with custom properties)
273 AnimationContainer animations; ///< A container of owned animations
274 PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
276 ObjectOwnerContainer<Geometry> geometries; ///< A container of geometries
277 ObjectOwnerContainer<Material> materials; ///< A container of materials
278 ObjectOwnerContainer<Sampler> samplers; ///< A container of samplers
279 ObjectOwnerContainer<PropertyBuffer> propertyBuffers; ///< A container of property buffers
281 ShaderContainer shaders; ///< A container of owned shaders
283 MessageQueue messageQueue; ///< The messages queued from the event-thread
284 ShaderDataBinaryQueue renderCompiledShaders; ///< Shaders compiled on Render thread are inserted here for update thread to pass on to event thread.
285 ShaderDataBinaryQueue updateCompiledShaders; ///< Shaders to be sent from Update to Event
286 Mutex compiledShaderMutex; ///< lock to ensure no corruption on the renderCompiledShaders
288 float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
289 bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
291 int nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
292 bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
294 int frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
295 RendererSortingHelper renderSortingHelper; ///< helper used to sort transparent renderers
297 GestureContainer gestures; ///< A container of owned gesture detectors
298 bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
301 UpdateManager::UpdateManager( NotificationManager& notificationManager,
302 GlSyncAbstraction& glSyncAbstraction,
303 CompleteNotificationInterface& animationFinishedNotifier,
304 PropertyNotifier& propertyNotifier,
305 ResourceManager& resourceManager,
306 DiscardQueue& discardQueue,
307 RenderController& controller,
308 RenderManager& renderManager,
309 RenderQueue& renderQueue,
310 TextureCache& textureCache,
311 TouchResampler& touchResampler )
314 mImpl = new Impl( notificationManager,
316 animationFinishedNotifier,
325 mSceneGraphBuffers );
327 textureCache.SetBufferIndices( &mSceneGraphBuffers );
330 UpdateManager::~UpdateManager()
335 void UpdateManager::InstallRoot( SceneGraph::Layer* layer, bool systemLevel )
337 DALI_ASSERT_DEBUG( layer->IsLayer() );
338 DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
342 DALI_ASSERT_DEBUG( mImpl->root == NULL && "Root Node already installed" );
347 DALI_ASSERT_DEBUG( mImpl->systemLevelRoot == NULL && "System-level Root Node already installed" );
348 mImpl->systemLevelRoot = layer;
351 layer->SetRoot(true);
354 void UpdateManager::AddNode( Node* node )
356 DALI_ASSERT_ALWAYS( NULL != node );
357 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
359 mImpl->activeDisconnectedNodes.insert( node ); // Takes ownership of node
362 void UpdateManager::ConnectNode( Node* parent, Node* node )
364 DALI_ASSERT_ALWAYS( NULL != parent );
365 DALI_ASSERT_ALWAYS( NULL != node );
366 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
368 // Move from active/disconnectedNodes to connectedNodes
369 std::set<Node*>::size_type removed = mImpl->activeDisconnectedNodes.erase( node );
372 removed = mImpl->disconnectedNodes.erase( node );
373 DALI_ASSERT_ALWAYS( removed );
375 mImpl->connectedNodes.insert( node );
377 node->SetActive( true );
379 parent->ConnectChild( node );
382 void UpdateManager::DisconnectNode( Node* node )
384 Node* parent = node->GetParent();
385 DALI_ASSERT_ALWAYS( NULL != parent );
386 parent->SetDirtyFlag( ChildDeletedFlag ); // make parent dirty so that render items dont get reused
388 // Move from connectedNodes to activeDisconnectedNodes (reset properties next frame)
389 parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node, mImpl->connectedNodes, mImpl->activeDisconnectedNodes );
392 void UpdateManager::SetNodeActive( Node* node )
394 DALI_ASSERT_ALWAYS( NULL != node );
395 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
397 // Move from disconnectedNodes to activeDisconnectedNodes (reset properties next frame)
398 std::set<Node*>::size_type removed = mImpl->disconnectedNodes.erase( node );
399 DALI_ASSERT_ALWAYS( removed );
400 mImpl->activeDisconnectedNodes.insert( node );
402 node->SetActive( true );
405 void UpdateManager::DestroyNode( Node* node )
407 DALI_ASSERT_ALWAYS( NULL != node );
408 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
410 // Transfer ownership from new/disconnectedNodes to the discard queue
411 // This keeps the nodes alive, until the render-thread has finished with them
412 std::set<Node*>::size_type removed = mImpl->activeDisconnectedNodes.erase( node );
415 removed = mImpl->disconnectedNodes.erase( node );
416 DALI_ASSERT_ALWAYS( removed );
418 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
420 // Notify the Node about impending destruction
424 //@todo MESH_REWORK Extend to allow arbitrary scene objects to connect to each other
425 void UpdateManager::AttachToNode( Node* node, NodeAttachment* attachment )
427 DALI_ASSERT_DEBUG( node != NULL );
428 DALI_ASSERT_DEBUG( attachment != NULL );
430 // attach node to attachment first so that parent is known by the time attachment is connected
431 node->Attach( *attachment ); // node takes ownership
433 // @todo MESH_REWORK Remove after merge of SceneGraph::RenderableAttachment and SceneGraph::RendererAttachment
434 if( dynamic_cast<SceneGraph::ImageAttachment*>( attachment ) != NULL )
436 attachment->Initialize( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
440 void UpdateManager::AttachToSceneGraph( RendererAttachment* renderer )
442 // @todo MESH_REWORK Take ownership of this object after merge with SceneGraph::RenderableAttachment
444 SceneGraph::NodeAttachment* attachment = static_cast<SceneGraph::NodeAttachment*>(renderer);
445 attachment->Initialize( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
448 void UpdateManager::AddObject( PropertyOwner* object )
450 DALI_ASSERT_DEBUG( NULL != object );
452 mImpl->customObjects.PushBack( object );
455 void UpdateManager::RemoveObject( PropertyOwner* object )
457 DALI_ASSERT_DEBUG( NULL != object );
459 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
461 // Find the object and destroy it
462 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); iter != customObjects.End(); ++iter )
464 PropertyOwner* current = *iter;
465 if ( current == object )
467 customObjects.Erase( iter );
472 // Should not reach here
473 DALI_ASSERT_DEBUG(false);
476 void UpdateManager::AddAnimation( Animation* animation )
478 mImpl->animations.PushBack( animation );
481 void UpdateManager::StopAnimation( Animation* animation )
483 DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
485 bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
487 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
490 void UpdateManager::RemoveAnimation( Animation* animation )
492 DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
494 animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
496 DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
499 bool UpdateManager::IsAnimationRunning() const
501 bool isRunning(false);
502 AnimationContainer& animations = mImpl->animations;
504 // Find any animation that isn't stopped or paused
506 const AnimationIter endIter = animations.End();
507 for ( AnimationIter iter = animations.Begin(); !isRunning && iter != endIter; ++iter )
509 const Animation::State state = (*iter)->GetState();
511 if (state != Animation::Stopped &&
512 state != Animation::Paused)
521 void UpdateManager::AddPropertyNotification( PropertyNotification* propertyNotification )
523 mImpl->propertyNotifications.PushBack( propertyNotification );
526 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
528 PropertyNotificationContainer &propertyNotifications = mImpl->propertyNotifications;
529 PropertyNotificationIter iter = propertyNotifications.Begin();
531 while ( iter != propertyNotifications.End() )
533 if( *iter == propertyNotification )
535 propertyNotifications.Erase(iter);
542 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
544 DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
545 propertyNotification->SetNotifyMode( notifyMode );
548 ObjectOwnerContainer<Geometry>& UpdateManager::GetGeometryOwner()
550 return mImpl->geometries;
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 );
763 // Reset animatable shader properties to base values
764 for (ShaderIter iter = mImpl->shaders.Begin(); iter != mImpl->shaders.End(); ++iter)
766 (*iter)->ResetToBaseValues( bufferIndex );
769 PERF_MONITOR_END(PerformanceMonitor::RESET_PROPERTIES);
772 bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds )
774 bool gestureUpdated( false );
776 // constrain gestures... (in construction order)
777 GestureContainer& gestures = mImpl->gestures;
779 for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
781 PanGesture& gesture = **iter;
782 gesture.ResetToBaseValues( bufferIndex ); // Needs to be done every time as gesture data is written directly to an update-buffer rather than via a message
783 gestureUpdated |= gesture.UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
786 return gestureUpdated;
789 void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
791 PERF_MONITOR_START(PerformanceMonitor::ANIMATE_NODES);
793 AnimationContainer &animations = mImpl->animations;
794 AnimationIter iter = animations.Begin();
795 while ( iter != animations.End() )
797 Animation* animation = *iter;
798 bool finished = animation->Update( bufferIndex, elapsedSeconds );
800 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
802 // Remove animations that had been destroyed but were still waiting for an update
803 if (animation->GetState() == Animation::Destroyed)
805 iter = animations.Erase(iter);
813 if ( mImpl->animationFinishedDuringUpdate )
815 // The application should be notified by NotificationManager, in another thread
816 mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationFinishedNotifier );
819 PERF_MONITOR_END(PerformanceMonitor::ANIMATE_NODES);
822 void UpdateManager::ApplyConstraints( BufferIndex bufferIndex )
824 PERF_MONITOR_START(PerformanceMonitor::APPLY_CONSTRAINTS);
826 // constrain custom objects... (in construction order)
827 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
829 const OwnerContainer< PropertyOwner* >::Iterator endIter = customObjects.End();
830 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); endIter != iter; ++iter )
832 PropertyOwner& object = **iter;
833 ConstrainPropertyOwner( object, bufferIndex );
836 // constrain nodes... (in Depth First traversal order)
839 ConstrainNodes( *(mImpl->root), bufferIndex );
842 if ( mImpl->systemLevelRoot )
844 ConstrainNodes( *(mImpl->systemLevelRoot), bufferIndex );
847 // constrain other property-owners after nodes as they are more likely to depend on a node's
848 // current frame property than vice versa. They tend to be final constraints (no further
849 // constraints depend on their properties)
850 // e.g. ShaderEffect uniform a function of Actor's position.
851 // Mesh vertex a function of Actor's position or world position.
853 // TODO: refactor this code (and reset nodes) as these are all just lists of property-owners
854 // they can be all processed in a super-list of property-owners.
856 // Constrain system-level render-tasks
857 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
859 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter )
861 RenderTask& task = **iter;
862 ConstrainPropertyOwner( task, bufferIndex );
865 // Constrain render-tasks
866 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
868 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter )
870 RenderTask& task = **iter;
871 ConstrainPropertyOwner( task, bufferIndex );
874 // Constrain Materials and geometries
875 mImpl->materials.ConstrainObjects( bufferIndex );
876 mImpl->geometries.ConstrainObjects( bufferIndex );
877 mImpl->samplers.ConstrainObjects( bufferIndex );
878 mImpl->propertyBuffers.ConstrainObjects( bufferIndex );
880 // constrain shaders... (in construction order)
881 ShaderContainer& shaders = mImpl->shaders;
883 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
885 Shader& shader = **iter;
886 ConstrainPropertyOwner( shader, bufferIndex );
889 PERF_MONITOR_END(PerformanceMonitor::APPLY_CONSTRAINTS);
892 void UpdateManager::ProcessPropertyNotifications( BufferIndex bufferIndex )
894 PropertyNotificationContainer ¬ifications = mImpl->propertyNotifications;
895 PropertyNotificationIter iter = notifications.Begin();
897 while ( iter != notifications.End() )
899 PropertyNotification* notification = *iter;
900 bool valid = notification->Check( bufferIndex );
903 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
909 void UpdateManager::ForwardCompiledShadersToEventThread()
911 DALI_ASSERT_DEBUG( (mImpl->shaderSaver != 0) && "shaderSaver should be wired-up during startup." );
912 if( mImpl->shaderSaver )
914 // lock and swap the queues
916 // render might be attempting to send us more binaries at the same time
917 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
918 mImpl->renderCompiledShaders.swap( mImpl->updateCompiledShaders );
921 if( mImpl->updateCompiledShaders.size() > 0 )
923 ShaderSaver& factory = *mImpl->shaderSaver;
924 ShaderDataBinaryQueue::iterator i = mImpl->updateCompiledShaders.begin();
925 ShaderDataBinaryQueue::iterator end = mImpl->updateCompiledShaders.end();
926 for( ; i != end; ++i )
928 mImpl->notificationManager.QueueMessage( ShaderCompiledMessage( factory, *i ) );
930 // we don't need them in update anymore
931 mImpl->updateCompiledShaders.clear();
936 void UpdateManager::UpdateNodes( BufferIndex bufferIndex )
938 mImpl->nodeDirtyFlags = NothingFlag;
945 PERF_MONITOR_START( PerformanceMonitor::UPDATE_NODES );
947 // Prepare resources, update shaders, update attachments, for each node
948 // And add the renderers to the sorted layers. Start from root, which is also a layer
949 mImpl->nodeDirtyFlags = UpdateNodesAndAttachments( *( mImpl->root ),
951 mImpl->resourceManager,
952 mImpl->renderQueue );
954 if ( mImpl->systemLevelRoot )
956 mImpl->nodeDirtyFlags |= UpdateNodesAndAttachments( *( mImpl->systemLevelRoot ),
958 mImpl->resourceManager,
959 mImpl->renderQueue );
962 PERF_MONITOR_END( PerformanceMonitor::UPDATE_NODES );
965 unsigned int UpdateManager::Update( float elapsedSeconds,
966 unsigned int lastVSyncTimeMilliseconds,
967 unsigned int nextVSyncTimeMilliseconds )
969 PERF_MONITOR_END(PerformanceMonitor::FRAME_RATE); // Mark the End of the last frame
970 PERF_MONITOR_NEXT_FRAME(); // Prints out performance info for the last frame (if enabled)
971 PERF_MONITOR_START(PerformanceMonitor::FRAME_RATE); // Mark the start of this current frame
973 // Measure the time spent in UpdateManager::Update
974 PERF_MONITOR_START(PerformanceMonitor::UPDATE);
976 const BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
978 // Update the frame time delta on the render thread.
979 mImpl->renderManager.SetFrameDeltaTime(elapsedSeconds);
981 // 1) Clear nodes/resources which were previously discarded
982 mImpl->discardQueue.Clear( bufferIndex );
984 // 2) Grab any loaded resources
985 bool resourceChanged = mImpl->resourceManager.UpdateCache( bufferIndex );
987 // 3) Process Touches & Gestures
988 mImpl->touchResampler.Update();
989 const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
991 const bool updateScene = // The scene-graph requires an update if..
992 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
993 IsAnimationRunning() || // ..at least one animation is running OR
994 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
995 resourceChanged || // ..one or more resources were updated/changed OR
996 gestureUpdated; // ..a gesture property was updated
998 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
999 // values if the scene was updated in the previous frame.
1000 if( updateScene || mImpl->previousUpdateScene )
1002 // 4) Reset properties from the previous update
1003 ResetProperties( bufferIndex );
1006 // 5) Process the queued scene messages
1007 mImpl->messageQueue.ProcessMessages( bufferIndex );
1009 // 6) Post Process Ids of resources updated by renderer
1010 mImpl->resourceManager.PostProcessResources( bufferIndex );
1012 // 6.1) Forward compiled shader programs to event thread for saving
1013 ForwardCompiledShadersToEventThread();
1015 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
1016 // renderer lists if the scene was updated in the previous frame.
1017 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
1018 if( updateScene || mImpl->previousUpdateScene )
1021 Animate( bufferIndex, elapsedSeconds );
1023 // 8) Apply Constraints
1024 ApplyConstraints( bufferIndex );
1026 // 9) Check Property Notifications
1027 ProcessPropertyNotifications( bufferIndex );
1029 // 10) Clear the lists of renderable-attachments from the previous update
1030 ClearRenderables( mImpl->sortedLayers );
1031 ClearRenderables( mImpl->systemLevelSortedLayers );
1033 // 11) Update node hierarchy and perform sorting / culling.
1034 // This will populate each Layer with a list of renderers which are ready.
1035 UpdateNodes( bufferIndex );
1037 // 12) Prepare for the next render
1038 PERF_MONITOR_START(PerformanceMonitor::PREPARE_RENDERABLES);
1040 PrepareRenderables( bufferIndex, mImpl->sortedLayers );
1041 PrepareRenderables( bufferIndex, mImpl->systemLevelSortedLayers );
1042 PERF_MONITOR_END(PerformanceMonitor::PREPARE_RENDERABLES);
1044 PERF_MONITOR_START(PerformanceMonitor::PROCESS_RENDER_TASKS);
1046 // 14) Process the RenderTasks; this creates the instructions for rendering the next frame.
1047 // reset the update buffer index and make sure there is enough room in the instruction container
1048 mImpl->renderInstructions.ResetAndReserve( bufferIndex,
1049 mImpl->taskList.GetTasks().Count() + mImpl->systemLevelTaskList.GetTasks().Count() );
1051 if ( NULL != mImpl->root )
1053 ProcessRenderTasks( bufferIndex,
1054 mImpl->completeStatusManager,
1057 mImpl->sortedLayers,
1058 mImpl->renderSortingHelper,
1059 mImpl->renderInstructions );
1061 // Process the system-level RenderTasks last
1062 if ( NULL != mImpl->systemLevelRoot )
1064 ProcessRenderTasks( bufferIndex,
1065 mImpl->completeStatusManager,
1066 mImpl->systemLevelTaskList,
1067 *mImpl->systemLevelRoot,
1068 mImpl->systemLevelSortedLayers,
1069 mImpl->renderSortingHelper,
1070 mImpl->renderInstructions );
1075 // check the countdown and notify (note, at the moment this is only done for normal tasks, not for systemlevel tasks)
1076 bool doRenderOnceNotify = false;
1077 mImpl->renderTaskWaiting = false;
1078 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
1079 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(), endIter = tasks.End();
1080 endIter != iter; ++iter )
1082 RenderTask& renderTask(*(*iter));
1084 renderTask.UpdateState();
1086 if( renderTask.IsWaitingToRender() &&
1087 renderTask.ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
1089 mImpl->renderTaskWaiting = true; // keep update/render threads alive
1092 if( renderTask.HasRendered() )
1094 doRenderOnceNotify = true;
1098 if( doRenderOnceNotify )
1100 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
1101 mImpl->notificationManager.QueueCompleteNotification( mImpl->taskList.GetCompleteNotificationInterface() );
1104 PERF_MONITOR_END(PerformanceMonitor::PROCESS_RENDER_TASKS);
1106 // Macro is undefined in release build.
1107 SNAPSHOT_NODE_LOGGING;
1109 // A ResetProperties() may be required in the next frame
1110 mImpl->previousUpdateScene = updateScene;
1112 // Check whether further updates are required
1113 unsigned int keepUpdating = KeepUpdatingCheck( elapsedSeconds );
1115 #ifdef PERFORMANCE_MONITOR_ENABLED
1116 // Always keep rendering when measuring FPS
1117 keepUpdating |= KeepUpdating::MONITORING_PERFORMANCE;
1120 // tell the update manager that we're done so the queue can be given to event thread
1121 mImpl->notificationManager.UpdateCompleted();
1123 // The update has finished; swap the double-buffering indices
1124 mSceneGraphBuffers.Swap();
1126 PERF_MONITOR_END(PerformanceMonitor::UPDATE);
1128 return keepUpdating;
1131 unsigned int UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
1133 // Update the duration set via Stage::KeepRendering()
1134 if ( mImpl->keepRenderingSeconds > 0.0f )
1136 mImpl->keepRenderingSeconds -= elapsedSeconds;
1139 unsigned int keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
1141 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
1142 // Keep updating until no messages are received and no animations are running.
1143 // If an animation has just finished, update at least once more for Discard end-actions.
1144 // No need to check for renderQueue as there is always a render after update and if that
1145 // render needs another update it will tell the adaptor to call update again
1147 if ( mImpl->keepRenderingSeconds > 0.0f )
1149 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
1152 if ( IsAnimationRunning() ||
1153 mImpl->animationFinishedDuringUpdate )
1155 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
1158 if ( mImpl->renderTaskWaiting )
1160 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
1163 return keepUpdatingRequest;
1166 void UpdateManager::SetBackgroundColor( const Vector4& color )
1168 typedef MessageValue1< RenderManager, Vector4 > DerivedType;
1170 // Reserve some memory inside the render queue
1171 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1173 // Construct message in the render queue memory; note that delete should not be called on the return value
1174 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
1177 void UpdateManager::SetDefaultSurfaceRect( const Rect<int>& rect )
1179 typedef MessageValue1< RenderManager, Rect<int> > DerivedType;
1181 // Reserve some memory inside the render queue
1182 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1184 // Construct message in the render queue memory; note that delete should not be called on the return value
1185 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1188 void UpdateManager::KeepRendering( float durationSeconds )
1190 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1193 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, bool systemLevel )
1197 // just copy the vector of pointers
1198 mImpl->sortedLayers = layers;
1202 mImpl->systemLevelSortedLayers = layers;
1206 void UpdateManager::SetShaderSaver( ShaderSaver& upstream )
1208 mImpl->shaderSaver = &upstream;
1211 } // namespace SceneGraph
1213 } // namespace Internal