2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/update/manager/update-manager.h>
22 #include <dali/public-api/common/stage.h>
23 #include <dali/devel-api/common/set-wrapper.h>
24 #include <dali/devel-api/common/owner-container.h>
25 #include <dali/devel-api/threading/mutex.h>
27 #include <dali/integration-api/core.h>
28 #include <dali/integration-api/render-controller.h>
29 #include <dali/internal/common/shader-data.h>
30 #include <dali/integration-api/debug.h>
32 #include <dali/internal/common/core-impl.h>
33 #include <dali/internal/common/message.h>
35 #include <dali/internal/event/common/notification-manager.h>
36 #include <dali/internal/event/common/property-notification-impl.h>
37 #include <dali/internal/event/common/property-notifier.h>
38 #include <dali/internal/event/effects/shader-factory.h>
40 #include <dali/internal/update/animation/scene-graph-animator.h>
41 #include <dali/internal/update/animation/scene-graph-animation.h>
42 #include <dali/internal/update/common/discard-queue.h>
43 #include <dali/internal/update/common/scene-graph-buffers.h>
44 #include <dali/internal/update/controllers/render-message-dispatcher.h>
45 #include <dali/internal/update/controllers/scene-controller-impl.h>
46 #include <dali/internal/update/gestures/scene-graph-pan-gesture.h>
47 #include <dali/internal/update/manager/object-owner-container.h>
48 #include <dali/internal/update/manager/process-render-tasks.h>
49 #include <dali/internal/update/manager/sorted-layers.h>
50 #include <dali/internal/update/manager/update-algorithms.h>
51 #include <dali/internal/update/manager/update-manager-debug.h>
52 #include <dali/internal/update/manager/transform-manager.h>
53 #include <dali/internal/update/node-attachments/scene-graph-camera-attachment.h>
54 #include <dali/internal/update/nodes/node.h>
55 #include <dali/internal/update/nodes/scene-graph-layer.h>
56 #include <dali/internal/update/queue/update-message-queue.h>
57 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
58 #include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
59 #include <dali/internal/update/rendering/scene-graph-texture-set.h>
60 #include <dali/internal/update/resources/resource-manager.h>
61 #include <dali/internal/update/touch/touch-resampler.h>
63 #include <dali/internal/render/common/render-instruction-container.h>
64 #include <dali/internal/render/common/render-manager.h>
65 #include <dali/internal/render/queue/render-queue.h>
66 #include <dali/internal/render/gl-resources/texture-cache.h>
67 #include <dali/internal/render/shaders/scene-graph-shader.h>
68 #include <dali/internal/render/renderers/render-sampler.h>
70 // Un-comment to enable node tree debug logging
71 //#define NODE_TREE_LOGGING 1
73 #if ( defined( DEBUG_ENABLED ) && defined( NODE_TREE_LOGGING ) )
74 #define SNAPSHOT_NODE_LOGGING \
75 const int FRAME_COUNT_TRIGGER = 16;\
76 if( mImpl->frameCounter >= FRAME_COUNT_TRIGGER )\
78 if ( NULL != mImpl->root )\
80 mImpl->frameCounter = 0;\
81 PrintNodeTree( *mImpl->root, mSceneGraphBuffers.GetUpdateBufferIndex(), "" );\
84 mImpl->frameCounter++;
86 #define SNAPSHOT_NODE_LOGGING
89 #if defined(DEBUG_ENABLED)
90 extern Debug::Filter* gRenderTaskLogFilter;
94 using namespace Dali::Integration;
95 using Dali::Internal::Update::MessageQueue;
106 typedef OwnerContainer< Shader* > ShaderContainer;
107 typedef ShaderContainer::Iterator ShaderIter;
108 typedef ShaderContainer::ConstIterator ShaderConstIter;
110 typedef std::vector<Internal::ShaderDataPtr> ShaderDataBinaryQueue;
112 typedef OwnerContainer<PanGesture*> GestureContainer;
113 typedef GestureContainer::Iterator GestureIter;
114 typedef GestureContainer::ConstIterator GestureConstIter;
118 * Structure to contain UpdateManager internal data
120 struct UpdateManager::Impl
122 Impl( NotificationManager& notificationManager,
123 CompleteNotificationInterface& animationFinishedNotifier,
124 PropertyNotifier& propertyNotifier,
125 ResourceManager& resourceManager,
126 DiscardQueue& discardQueue,
127 RenderController& renderController,
128 RenderManager& renderManager,
129 RenderQueue& renderQueue,
130 TextureCache& textureCache,
131 TouchResampler& touchResampler,
132 SceneGraphBuffers& sceneGraphBuffers )
133 : renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ),
134 notificationManager( notificationManager ),
136 animationFinishedNotifier( animationFinishedNotifier ),
137 propertyNotifier( propertyNotifier ),
139 resourceManager( resourceManager ),
140 discardQueue( discardQueue ),
141 renderController( renderController ),
142 sceneController( NULL ),
143 renderManager( renderManager ),
144 renderQueue( renderQueue ),
145 renderInstructions( renderManager.GetRenderInstructionContainer() ),
146 touchResampler( touchResampler ),
147 backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
148 taskList( renderMessageDispatcher, resourceManager ),
149 systemLevelTaskList( renderMessageDispatcher, resourceManager ),
151 systemLevelRoot( NULL ),
152 renderers( sceneGraphBuffers, discardQueue ),
153 textureSets( sceneGraphBuffers, discardQueue ),
154 messageQueue( renderController, sceneGraphBuffers ),
155 keepRenderingSeconds( 0.0f ),
156 animationFinishedDuringUpdate( false ),
157 nodeDirtyFlags( TransformFlag ), // set to TransformFlag to ensure full update the first time through Update()
158 previousUpdateScene( false ),
160 renderSortingHelper(),
161 renderTaskWaiting( false )
163 sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue, textureCache );
165 renderers.SetSceneController( *sceneController );
166 textureSets.SetSceneController( *sceneController );
168 // create first 'dummy' node
174 // Disconnect render tasks from nodes, before destroying the nodes
175 RenderTaskList::RenderTaskContainer& tasks = taskList.GetTasks();
176 for (RenderTaskList::RenderTaskContainer::Iterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
178 (*iter)->SetSourceNode( NULL );
180 // ..repeat for system level RenderTasks
181 RenderTaskList::RenderTaskContainer& systemLevelTasks = systemLevelTaskList.GetTasks();
182 for (RenderTaskList::RenderTaskContainer::Iterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
184 (*iter)->SetSourceNode( NULL );
187 // UpdateManager owns the Nodes
188 Vector<Node*>::Iterator iter = nodes.Begin()+1;
189 Vector<Node*>::Iterator endIter = nodes.End();
190 for(;iter!=endIter;++iter)
192 (*iter)->OnDestroy();
196 // If there is root, reset it, otherwise do nothing as rendering was never started
205 if( systemLevelRoot )
207 systemLevelRoot->OnDestroy();
209 delete systemLevelRoot;
210 systemLevelRoot = NULL;
213 sceneController->GetTextureCache().SetBufferIndices(NULL); // TODO - Remove
214 delete sceneController;
217 SceneGraphBuffers sceneGraphBuffers; ///< Used to keep track of which buffers are being written or read
218 RenderMessageDispatcher renderMessageDispatcher; ///< Used for passing messages to the render-thread
219 NotificationManager& notificationManager; ///< Queues notification messages for the event-thread.
220 TransformManager transformManager; ///< Used to update the transformation matrices of the nodes
221 CompleteNotificationInterface& animationFinishedNotifier; ///< Provides notification to applications when animations are finished.
222 PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
223 ShaderSaver* shaderSaver; ///< Saves shader binaries.
224 ResourceManager& resourceManager; ///< resource manager
225 DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
226 RenderController& renderController; ///< render controller
227 SceneControllerImpl* sceneController; ///< scene controller
228 RenderManager& renderManager; ///< This is responsible for rendering the results of each "update"
229 RenderQueue& renderQueue; ///< Used to queue messages for the next render
230 RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions
231 TouchResampler& touchResampler; ///< Used to resample touch events on every update.
233 Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
235 RenderTaskList taskList; ///< The list of scene graph render-tasks
236 RenderTaskList systemLevelTaskList; ///< Separate render-tasks for system-level content
238 Layer* root; ///< The root node (root is a layer)
239 Layer* systemLevelRoot; ///< A separate root-node for system-level content
241 Vector<Node*> nodes; ///< A container of all instantiated nodes
243 SortedLayerPointers sortedLayers; ///< A container of Layer pointers sorted by depth
244 SortedLayerPointers systemLevelSortedLayers; ///< A separate container of system-level Layers
246 OwnerContainer< PropertyOwner* > customObjects; ///< A container of owned objects (with custom properties)
248 AnimationContainer animations; ///< A container of owned animations
249 PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
251 ObjectOwnerContainer<Renderer> renderers;
252 ObjectOwnerContainer<TextureSet> textureSets; ///< A container of texture sets
254 ShaderContainer shaders; ///< A container of owned shaders
256 MessageQueue messageQueue; ///< The messages queued from the event-thread
257 ShaderDataBinaryQueue renderCompiledShaders; ///< Shaders compiled on Render thread are inserted here for update thread to pass on to event thread.
258 ShaderDataBinaryQueue updateCompiledShaders; ///< Shaders to be sent from Update to Event
259 Mutex compiledShaderMutex; ///< lock to ensure no corruption on the renderCompiledShaders
261 float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
262 bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
264 int nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
265 bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
267 int frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
268 RendererSortingHelper renderSortingHelper; ///< helper used to sort transparent renderers
270 GestureContainer gestures; ///< A container of owned gesture detectors
271 bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
274 UpdateManager::UpdateManager( NotificationManager& notificationManager,
275 CompleteNotificationInterface& animationFinishedNotifier,
276 PropertyNotifier& propertyNotifier,
277 ResourceManager& resourceManager,
278 DiscardQueue& discardQueue,
279 RenderController& controller,
280 RenderManager& renderManager,
281 RenderQueue& renderQueue,
282 TextureCache& textureCache,
283 TouchResampler& touchResampler )
286 mImpl = new Impl( notificationManager,
287 animationFinishedNotifier,
296 mSceneGraphBuffers );
298 textureCache.SetBufferIndices( &mSceneGraphBuffers );
301 UpdateManager::~UpdateManager()
306 void UpdateManager::InstallRoot( SceneGraph::Layer* layer, bool systemLevel )
308 DALI_ASSERT_DEBUG( layer->IsLayer() );
309 DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
313 DALI_ASSERT_DEBUG( mImpl->root == NULL && "Root Node already installed" );
315 mImpl->root->CreateTransform( &mImpl->transformManager);
319 DALI_ASSERT_DEBUG( mImpl->systemLevelRoot == NULL && "System-level Root Node already installed" );
320 mImpl->systemLevelRoot = layer;
321 mImpl->systemLevelRoot->CreateTransform( &mImpl->transformManager);
324 layer->SetRoot(true);
327 void UpdateManager::AddNode( Node* node )
329 DALI_ASSERT_ALWAYS( NULL != node );
330 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
332 // Nodes must be sorted by pointer
333 Vector<Node*>::Iterator begin = mImpl->nodes.Begin();
334 for(Vector<Node*>::Iterator iter = mImpl->nodes.End()-1; iter >= begin; --iter)
338 mImpl->nodes.Insert((iter+1), node);
339 node->CreateTransform( &mImpl->transformManager);
345 void UpdateManager::ConnectNode( Node* parent, Node* node )
347 DALI_ASSERT_ALWAYS( NULL != parent );
348 DALI_ASSERT_ALWAYS( NULL != node );
349 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
351 parent->ConnectChild( node );
354 void UpdateManager::DisconnectNode( Node* node )
356 Node* parent = node->GetParent();
357 DALI_ASSERT_ALWAYS( NULL != parent );
358 parent->SetDirtyFlag( ChildDeletedFlag ); // make parent dirty so that render items dont get reused
360 parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node );
363 void UpdateManager::DestroyNode( Node* node )
365 DALI_ASSERT_ALWAYS( NULL != node );
366 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
368 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
369 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
370 for(;iter!=endIter;++iter)
374 mImpl->nodes.Erase(iter);
379 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
381 // Notify the Node about impending destruction
385 //@todo MESH_REWORK Extend to allow arbitrary scene objects to connect to each other
386 void UpdateManager::AttachToNode( Node* node, NodeAttachment* attachment )
388 DALI_ASSERT_DEBUG( node != NULL );
389 DALI_ASSERT_DEBUG( attachment != NULL );
391 // attach node to attachment first so that parent is known by the time attachment is connected
392 node->Attach( *attachment ); // node takes ownership
395 void UpdateManager::AddObject( PropertyOwner* object )
397 DALI_ASSERT_DEBUG( NULL != object );
399 mImpl->customObjects.PushBack( object );
402 void UpdateManager::RemoveObject( PropertyOwner* object )
404 DALI_ASSERT_DEBUG( NULL != object );
406 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
408 // Find the object and destroy it
409 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); iter != customObjects.End(); ++iter )
411 PropertyOwner* current = *iter;
412 if ( current == object )
414 customObjects.Erase( iter );
419 // Should not reach here
420 DALI_ASSERT_DEBUG(false);
423 void UpdateManager::AddAnimation( Animation* animation )
425 mImpl->animations.PushBack( animation );
428 void UpdateManager::StopAnimation( Animation* animation )
430 DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
432 bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
434 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
437 void UpdateManager::RemoveAnimation( Animation* animation )
439 DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
441 animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
443 DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
446 bool UpdateManager::IsAnimationRunning() const
448 bool isRunning(false);
449 AnimationContainer& animations = mImpl->animations;
451 // Find any animation that isn't stopped or paused
453 const AnimationIter endIter = animations.End();
454 for ( AnimationIter iter = animations.Begin(); !isRunning && iter != endIter; ++iter )
456 const Animation::State state = (*iter)->GetState();
458 if (state != Animation::Stopped &&
459 state != Animation::Paused)
468 void UpdateManager::AddPropertyNotification( PropertyNotification* propertyNotification )
470 mImpl->propertyNotifications.PushBack( propertyNotification );
473 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
475 PropertyNotificationContainer &propertyNotifications = mImpl->propertyNotifications;
476 PropertyNotificationIter iter = propertyNotifications.Begin();
478 while ( iter != propertyNotifications.End() )
480 if( *iter == propertyNotification )
482 propertyNotifications.Erase(iter);
489 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
491 DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
492 propertyNotification->SetNotifyMode( notifyMode );
495 ObjectOwnerContainer<Renderer>& UpdateManager::GetRendererOwner()
497 return mImpl->renderers;
501 ObjectOwnerContainer<TextureSet>& UpdateManager::GetTexturesOwner()
503 return mImpl->textureSets;
506 void UpdateManager::AddShader( Shader* shader )
508 DALI_ASSERT_DEBUG( NULL != shader );
510 if( mImpl->shaders.Count() == 0 )
512 // the first added shader becomes our default shader
513 // Construct message in the render queue memory; note that delete should not be called on the return value
514 typedef MessageValue1< RenderManager, Shader* > DerivedType;
516 // Reserve some memory inside the render queue
517 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
519 // Construct message in the render queue memory; note that delete should not be called on the return value
520 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultShader, shader );
523 mImpl->shaders.PushBack( shader );
526 void UpdateManager::RemoveShader( Shader* shader )
528 DALI_ASSERT_DEBUG(shader != NULL);
530 ShaderContainer& shaders = mImpl->shaders;
532 // Find the shader and destroy it
533 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
535 Shader& current = **iter;
536 if ( ¤t == shader )
538 // Transfer ownership to the discard queue
539 // This keeps the shader alive, until the render-thread has finished with it
540 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), shaders.Release( iter ) );
545 // Should not reach here
546 DALI_ASSERT_DEBUG(false);
549 void UpdateManager::SetShaderProgram( Shader* shader,
550 Internal::ShaderDataPtr shaderData, bool modifiesGeometry )
555 typedef MessageValue3< Shader, Internal::ShaderDataPtr, ProgramCache*, bool> DerivedType;
557 // Reserve some memory inside the render queue
558 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
560 // Construct message in the render queue memory; note that delete should not be called on the return value
561 new (slot) DerivedType( shader, &Shader::SetProgram, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
565 void UpdateManager::SaveBinary( Internal::ShaderDataPtr shaderData )
567 DALI_ASSERT_DEBUG( shaderData && "No NULL shader data pointers please." );
568 DALI_ASSERT_DEBUG( shaderData->GetBufferSize() > 0 && "Shader binary empty so nothing to save." );
570 // lock as update might be sending previously compiled shaders to event thread
571 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
572 mImpl->renderCompiledShaders.push_back( shaderData );
576 RenderTaskList* UpdateManager::GetRenderTaskList( bool systemLevel )
580 // copy the list, this is only likely to happen once in application life cycle
581 return &(mImpl->taskList);
585 // copy the list, this is only likely to happen once in application life cycle
586 return &(mImpl->systemLevelTaskList);
590 void UpdateManager::AddGesture( PanGesture* gesture )
592 DALI_ASSERT_DEBUG( NULL != gesture );
594 mImpl->gestures.PushBack( gesture );
597 void UpdateManager::RemoveGesture( PanGesture* gesture )
599 DALI_ASSERT_DEBUG( gesture != NULL );
601 GestureContainer& gestures = mImpl->gestures;
603 // Find the gesture and destroy it
604 for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
606 PanGesture& current = **iter;
607 if ( ¤t == gesture )
609 mImpl->gestures.Erase( iter );
613 // Should not reach here
614 DALI_ASSERT_DEBUG(false);
617 unsigned int* UpdateManager::ReserveMessageSlot( std::size_t size, bool updateScene )
619 return mImpl->messageQueue.ReserveMessageSlot( size, updateScene );
622 void UpdateManager::EventProcessingStarted()
624 mImpl->messageQueue.EventProcessingStarted();
627 bool UpdateManager::FlushQueue()
629 return mImpl->messageQueue.FlushQueue();
632 void UpdateManager::ResetProperties( BufferIndex bufferIndex )
634 // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
635 mImpl->animationFinishedDuringUpdate = false;
637 // Animated properties have to be reset to their original value each frame
639 // Reset root properties
642 mImpl->root->ResetToBaseValues( bufferIndex );
644 if ( mImpl->systemLevelRoot )
646 mImpl->systemLevelRoot->ResetToBaseValues( bufferIndex );
649 // Reset all the nodes
650 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
651 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
652 for(;iter != endIter; ++iter)
654 (*iter)->ResetToBaseValues( bufferIndex );
657 // Reset system-level render-task list properties to base values
658 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
660 for (RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
662 (*iter)->ResetToBaseValues( bufferIndex );
665 // Reset render-task list properties to base values.
666 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
668 for (RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
670 (*iter)->ResetToBaseValues( bufferIndex );
673 // Reset custom object properties to base values
674 for (OwnerContainer<PropertyOwner*>::Iterator iter = mImpl->customObjects.Begin(); iter != mImpl->customObjects.End(); ++iter)
676 (*iter)->ResetToBaseValues( bufferIndex );
679 mImpl->textureSets.ResetToBaseValues( bufferIndex );
680 mImpl->renderers.ResetToBaseValues( bufferIndex );
682 // Reset animatable shader properties to base values
683 for (ShaderIter iter = mImpl->shaders.Begin(); iter != mImpl->shaders.End(); ++iter)
685 (*iter)->ResetToBaseValues( bufferIndex );
689 bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds )
691 bool gestureUpdated( false );
693 // constrain gestures... (in construction order)
694 GestureContainer& gestures = mImpl->gestures;
696 for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
698 PanGesture& gesture = **iter;
699 gesture.ResetToBaseValues( bufferIndex ); // Needs to be done every time as gesture data is written directly to an update-buffer rather than via a message
700 gestureUpdated |= gesture.UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
703 return gestureUpdated;
706 void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
708 AnimationContainer &animations = mImpl->animations;
709 AnimationIter iter = animations.Begin();
710 bool animationLooped = false;
711 while ( iter != animations.End() )
713 Animation* animation = *iter;
714 bool finished = false;
716 animation->Update( bufferIndex, elapsedSeconds, looped, finished );
718 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
719 animationLooped = animationLooped || looped;
721 // Remove animations that had been destroyed but were still waiting for an update
722 if (animation->GetState() == Animation::Destroyed)
724 iter = animations.Erase(iter);
732 // queue the notification on finished or looped (to update loop count)
733 if ( mImpl->animationFinishedDuringUpdate || animationLooped )
735 // The application should be notified by NotificationManager, in another thread
736 mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationFinishedNotifier );
740 void UpdateManager::ConstrainCustomObjects( BufferIndex bufferIndex )
742 //Constrain custom objects (in construction order)
743 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
744 const OwnerContainer< PropertyOwner* >::Iterator endIter = customObjects.End();
745 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); endIter != iter; ++iter )
747 PropertyOwner& object = **iter;
748 ConstrainPropertyOwner( object, bufferIndex );
752 void UpdateManager::ConstrainRenderTasks( BufferIndex bufferIndex )
754 // Constrain system-level render-tasks
755 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
756 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter )
758 RenderTask& task = **iter;
759 ConstrainPropertyOwner( task, bufferIndex );
762 // Constrain render-tasks
763 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
764 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter )
766 RenderTask& task = **iter;
767 ConstrainPropertyOwner( task, bufferIndex );
771 void UpdateManager::ConstrainShaders( BufferIndex bufferIndex )
773 // constrain shaders... (in construction order)
774 ShaderContainer& shaders = mImpl->shaders;
775 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
777 Shader& shader = **iter;
778 ConstrainPropertyOwner( shader, bufferIndex );
782 void UpdateManager::ProcessPropertyNotifications( BufferIndex bufferIndex )
784 PropertyNotificationContainer ¬ifications = mImpl->propertyNotifications;
785 PropertyNotificationIter iter = notifications.Begin();
787 while ( iter != notifications.End() )
789 PropertyNotification* notification = *iter;
790 bool valid = notification->Check( bufferIndex );
793 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
799 void UpdateManager::PrepareTextureSets( BufferIndex bufferIndex )
801 ObjectOwnerContainer<TextureSet>::Iterator iter = mImpl->textureSets.GetObjectContainer().Begin();
802 const ObjectOwnerContainer<TextureSet>::Iterator end = mImpl->textureSets.GetObjectContainer().End();
803 for( ; iter != end; ++iter )
806 ConstrainPropertyOwner( *(*iter), bufferIndex );
808 //Prepare texture set
809 (*iter)->Prepare( mImpl->resourceManager );
813 void UpdateManager::ForwardCompiledShadersToEventThread()
815 DALI_ASSERT_DEBUG( (mImpl->shaderSaver != 0) && "shaderSaver should be wired-up during startup." );
816 if( mImpl->shaderSaver )
818 // lock and swap the queues
820 // render might be attempting to send us more binaries at the same time
821 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
822 mImpl->renderCompiledShaders.swap( mImpl->updateCompiledShaders );
825 if( mImpl->updateCompiledShaders.size() > 0 )
827 ShaderSaver& factory = *mImpl->shaderSaver;
828 ShaderDataBinaryQueue::iterator i = mImpl->updateCompiledShaders.begin();
829 ShaderDataBinaryQueue::iterator end = mImpl->updateCompiledShaders.end();
830 for( ; i != end; ++i )
832 mImpl->notificationManager.QueueMessage( ShaderCompiledMessage( factory, *i ) );
834 // we don't need them in update anymore
835 mImpl->updateCompiledShaders.clear();
840 void UpdateManager::UpdateRenderers( BufferIndex bufferIndex )
842 const OwnerContainer<Renderer*>& rendererContainer( mImpl->renderers.GetObjectContainer() );
843 unsigned int rendererCount( rendererContainer.Size() );
844 for( unsigned int i(0); i<rendererCount; ++i )
847 ConstrainPropertyOwner( *rendererContainer[i], bufferIndex );
849 if( rendererContainer[i]->IsReferenced() )
851 rendererContainer[i]->PrepareRender( bufferIndex );
856 void UpdateManager::UpdateNodes( BufferIndex bufferIndex )
858 mImpl->nodeDirtyFlags = NothingFlag;
865 // Prepare resources, update shaders, update attachments, for each node
866 // And add the renderers to the sorted layers. Start from root, which is also a layer
867 mImpl->nodeDirtyFlags = UpdateNodesAndAttachments( *( mImpl->root ),
869 mImpl->resourceManager,
870 mImpl->renderQueue );
872 if ( mImpl->systemLevelRoot )
874 mImpl->nodeDirtyFlags |= UpdateNodesAndAttachments( *( mImpl->systemLevelRoot ),
876 mImpl->resourceManager,
877 mImpl->renderQueue );
881 unsigned int UpdateManager::Update( float elapsedSeconds,
882 unsigned int lastVSyncTimeMilliseconds,
883 unsigned int nextVSyncTimeMilliseconds )
885 const BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
887 //Clear nodes/resources which were previously discarded
888 mImpl->discardQueue.Clear( bufferIndex );
890 //Grab any loaded resources
891 bool resourceChanged = mImpl->resourceManager.UpdateCache( bufferIndex );
893 //Process Touches & Gestures
894 mImpl->touchResampler.Update();
895 const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
897 const bool updateScene = // The scene-graph requires an update if..
898 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
899 IsAnimationRunning() || // ..at least one animation is running OR
900 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
901 resourceChanged || // ..one or more resources were updated/changed OR
902 gestureUpdated; // ..a gesture property was updated
905 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
906 // values if the scene was updated in the previous frame.
907 if( updateScene || mImpl->previousUpdateScene )
909 //Reset properties from the previous update
910 ResetProperties( bufferIndex );
911 mImpl->transformManager.ResetToBaseValue();
914 //Process the queued scene messages
915 mImpl->messageQueue.ProcessMessages( bufferIndex );
917 //Post Process Ids of resources updated by renderer
918 mImpl->resourceManager.PostProcessResources( bufferIndex );
920 //Forward compiled shader programs to event thread for saving
921 ForwardCompiledShadersToEventThread();
923 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
924 // renderer lists if the scene was updated in the previous frame.
925 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
926 if( updateScene || mImpl->previousUpdateScene )
929 Animate( bufferIndex, elapsedSeconds );
931 //Constraint custom objects
932 ConstrainCustomObjects( bufferIndex );
934 //Prepare texture sets and apply constraints to them
935 PrepareTextureSets( bufferIndex );
937 //Clear the lists of renderable-attachments from the previous update
938 for( size_t i(0); i<mImpl->sortedLayers.size(); ++i )
940 mImpl->sortedLayers[i]->ClearRenderables();
943 for( size_t i(0); i<mImpl->systemLevelSortedLayers.size(); ++i )
945 mImpl->systemLevelSortedLayers[i]->ClearRenderables();
948 //Update node hierarchy, apply constraints and perform sorting / culling.
949 //This will populate each Layer with a list of renderers which are ready.
950 UpdateNodes( bufferIndex );
952 //Apply constraints to RenderTasks, shaders
953 ConstrainRenderTasks( bufferIndex );
954 ConstrainShaders( bufferIndex );
956 //Update renderers and apply constraints
957 UpdateRenderers( bufferIndex );
959 //Update the trnasformations of all the nodes
960 mImpl->transformManager.Update();
962 //Process Property Notifications
963 ProcessPropertyNotifications( bufferIndex );
965 //Process the RenderTasks; this creates the instructions for rendering the next frame.
966 //reset the update buffer index and make sure there is enough room in the instruction container
967 mImpl->renderInstructions.ResetAndReserve( bufferIndex,
968 mImpl->taskList.GetTasks().Count() + mImpl->systemLevelTaskList.GetTasks().Count() );
970 if ( NULL != mImpl->root )
972 ProcessRenderTasks( bufferIndex,
976 mImpl->renderSortingHelper,
977 mImpl->renderInstructions );
979 // Process the system-level RenderTasks last
980 if ( NULL != mImpl->systemLevelRoot )
982 ProcessRenderTasks( bufferIndex,
983 mImpl->systemLevelTaskList,
984 *mImpl->systemLevelRoot,
985 mImpl->systemLevelSortedLayers,
986 mImpl->renderSortingHelper,
987 mImpl->renderInstructions );
992 // check the countdown and notify (note, at the moment this is only done for normal tasks, not for systemlevel tasks)
993 bool doRenderOnceNotify = false;
994 mImpl->renderTaskWaiting = false;
995 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
996 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(), endIter = tasks.End();
997 endIter != iter; ++iter )
999 RenderTask& renderTask(*(*iter));
1001 renderTask.UpdateState();
1003 if( renderTask.IsWaitingToRender() &&
1004 renderTask.ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
1006 mImpl->renderTaskWaiting = true; // keep update/render threads alive
1009 if( renderTask.HasRendered() )
1011 doRenderOnceNotify = true;
1015 if( doRenderOnceNotify )
1017 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
1018 mImpl->notificationManager.QueueCompleteNotification( mImpl->taskList.GetCompleteNotificationInterface() );
1021 // Macro is undefined in release build.
1022 SNAPSHOT_NODE_LOGGING;
1024 // A ResetProperties() may be required in the next frame
1025 mImpl->previousUpdateScene = updateScene;
1027 // Check whether further updates are required
1028 unsigned int keepUpdating = KeepUpdatingCheck( elapsedSeconds );
1030 // tell the update manager that we're done so the queue can be given to event thread
1031 mImpl->notificationManager.UpdateCompleted();
1033 // The update has finished; swap the double-buffering indices
1034 mSceneGraphBuffers.Swap();
1036 return keepUpdating;
1039 unsigned int UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
1041 // Update the duration set via Stage::KeepRendering()
1042 if ( mImpl->keepRenderingSeconds > 0.0f )
1044 mImpl->keepRenderingSeconds -= elapsedSeconds;
1047 unsigned int keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
1049 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
1050 // Keep updating until no messages are received and no animations are running.
1051 // If an animation has just finished, update at least once more for Discard end-actions.
1052 // No need to check for renderQueue as there is always a render after update and if that
1053 // render needs another update it will tell the adaptor to call update again
1055 if ( mImpl->keepRenderingSeconds > 0.0f )
1057 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
1060 if ( IsAnimationRunning() ||
1061 mImpl->animationFinishedDuringUpdate )
1063 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
1066 if ( mImpl->renderTaskWaiting )
1068 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
1071 return keepUpdatingRequest;
1074 void UpdateManager::SetBackgroundColor( const Vector4& color )
1076 typedef MessageValue1< RenderManager, Vector4 > DerivedType;
1078 // Reserve some memory inside the render queue
1079 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1081 // Construct message in the render queue memory; note that delete should not be called on the return value
1082 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
1085 void UpdateManager::SetDefaultSurfaceRect( const Rect<int>& rect )
1087 typedef MessageValue1< RenderManager, Rect<int> > DerivedType;
1089 // Reserve some memory inside the render queue
1090 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1092 // Construct message in the render queue memory; note that delete should not be called on the return value
1093 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1096 void UpdateManager::KeepRendering( float durationSeconds )
1098 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1101 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, bool systemLevel )
1105 // just copy the vector of pointers
1106 mImpl->sortedLayers = layers;
1110 mImpl->systemLevelSortedLayers = layers;
1114 void UpdateManager::SetShaderSaver( ShaderSaver& upstream )
1116 mImpl->shaderSaver = &upstream;
1119 void UpdateManager::AddSampler( Render::Sampler* sampler )
1121 typedef MessageValue1< RenderManager, Render::Sampler* > DerivedType;
1123 // Reserve some memory inside the render queue
1124 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1126 // Construct message in the render queue memory; note that delete should not be called on the return value
1127 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddSampler, sampler );
1130 void UpdateManager::RemoveSampler( Render::Sampler* sampler )
1132 typedef MessageValue1< RenderManager, Render::Sampler* > DerivedType;
1134 // Reserve some memory inside the render queue
1135 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1137 // Construct message in the render queue memory; note that delete should not be called on the return value
1138 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveSampler, sampler );
1141 void UpdateManager::SetFilterMode( Render::Sampler* sampler, unsigned int minFilterMode, unsigned int magFilterMode )
1143 typedef MessageValue3< RenderManager, Render::Sampler*, unsigned int, unsigned int > DerivedType;
1145 // Reserve some memory inside the render queue
1146 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1148 // Construct message in the render queue memory; note that delete should not be called on the return value
1149 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetFilterMode, sampler, minFilterMode, magFilterMode );
1152 void UpdateManager::SetWrapMode( Render::Sampler* sampler, unsigned int uWrapMode, unsigned int vWrapMode )
1154 typedef MessageValue3< RenderManager, Render::Sampler*, unsigned int, unsigned int > DerivedType;
1156 // Reserve some memory inside the render queue
1157 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1159 // Construct message in the render queue memory; note that delete should not be called on the return value
1160 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetWrapMode, sampler, uWrapMode, vWrapMode );
1163 void UpdateManager::AddPropertyBuffer( Render::PropertyBuffer* propertyBuffer )
1165 typedef MessageValue1< RenderManager, Render::PropertyBuffer* > DerivedType;
1167 // Reserve some memory inside the render queue
1168 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1170 // Construct message in the render queue memory; note that delete should not be called on the return value
1171 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddPropertyBuffer, propertyBuffer );
1174 void UpdateManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer )
1176 typedef MessageValue1< RenderManager, Render::PropertyBuffer* > DerivedType;
1178 // Reserve some memory inside the render queue
1179 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1181 // Construct message in the render queue memory; note that delete should not be called on the return value
1182 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemovePropertyBuffer, propertyBuffer );
1185 void UpdateManager::SetPropertyBufferFormat(Render::PropertyBuffer* propertyBuffer, Render::PropertyBuffer::Format* format )
1187 typedef MessageValue2< RenderManager, Render::PropertyBuffer*, Render::PropertyBuffer::Format* > 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::SetPropertyBufferFormat, propertyBuffer, format );
1196 void UpdateManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffer, Dali::Vector<char>* data, size_t size )
1198 typedef MessageValue3< RenderManager, Render::PropertyBuffer*, Dali::Vector<char>*, size_t > 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::SetPropertyBufferData, propertyBuffer, data, size );
1207 void UpdateManager::AddGeometry( Render::Geometry* geometry )
1209 typedef MessageValue1< RenderManager, Render::Geometry* > DerivedType;
1211 // Reserve some memory inside the render queue
1212 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1214 // Construct message in the render queue memory; note that delete should not be called on the return value
1215 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddGeometry, geometry );
1218 void UpdateManager::RemoveGeometry( Render::Geometry* geometry )
1220 typedef MessageValue1< RenderManager, Render::Geometry* > DerivedType;
1222 // Reserve some memory inside the render queue
1223 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1225 // Construct message in the render queue memory; note that delete should not be called on the return value
1226 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveGeometry, geometry );
1229 void UpdateManager::SetGeometryRequiresDepthTest( Render::Geometry* geometry, bool requiresDepthTest )
1231 typedef MessageValue2< RenderManager, Render::Geometry*, bool > DerivedType;
1233 // Reserve some memory inside the render queue
1234 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1236 // Construct message in the render queue memory; note that delete should not be called on the return value
1237 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetGeometryRequiresDepthTest, geometry, requiresDepthTest );
1240 void UpdateManager::SetGeometryType( Render::Geometry* geometry, unsigned int geometryType )
1242 typedef MessageValue2< RenderManager, Render::Geometry*, unsigned int > DerivedType;
1244 // Reserve some memory inside the render queue
1245 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1247 // Construct message in the render queue memory; note that delete should not be called on the return value
1248 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetGeometryType, geometry, geometryType );
1251 void UpdateManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector<unsigned short>& indices )
1253 typedef IndexBufferMessage< RenderManager > DerivedType;
1255 // Reserve some memory inside the render queue
1256 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1258 // Construct message in the render queue memory; note that delete should not be called on the return value
1259 new (slot) DerivedType( &mImpl->renderManager, geometry, indices );
1262 void UpdateManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1264 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1266 // Reserve some memory inside the render queue
1267 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1269 // Construct message in the render queue memory; note that delete should not be called on the return value
1270 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveVertexBuffer, geometry, propertyBuffer );
1273 void UpdateManager::AddVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1275 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1277 // Reserve some memory inside the render queue
1278 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1280 // Construct message in the render queue memory; note that delete should not be called on the return value
1281 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddVertexBuffer, geometry, propertyBuffer );
1285 } // namespace SceneGraph
1287 } // namespace Internal