2 * Copyright (c) 2018 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.
20 #include <dali/internal/update/manager/update-manager.h>
23 #include <dali/graphics/graphics-controller.h>
26 #include <dali/public-api/common/stage.h>
28 #include <dali/integration-api/core.h>
29 #include <dali/integration-api/debug.h>
30 #include <dali/integration-api/render-controller.h>
31 #include <dali/integration-api/graphics/graphics.h>
33 #include <dali/devel-api/common/owner-container.h>
34 #include <dali/devel-api/threading/mutex.h>
35 #include <dali/internal/common/core-impl.h>
36 #include <dali/internal/common/message.h>
37 #include <dali/internal/common/shader-data.h>
38 #include <dali/internal/event/animation/animation-playlist.h>
39 #include <dali/internal/event/common/notification-manager.h>
40 #include <dali/internal/event/common/property-notification-impl.h>
41 #include <dali/internal/event/common/property-notifier.h>
42 #include <dali/internal/event/effects/shader-factory.h>
43 #include <dali/internal/update/animation/scene-graph-animation.h>
44 #include <dali/internal/update/animation/scene-graph-animator.h>
45 #include <dali/internal/update/common/discard-queue.h>
46 #include <dali/internal/update/common/scene-graph-buffers.h>
47 #include <dali/internal/update/controllers/scene-controller-impl.h>
48 #include <dali/internal/update/gestures/scene-graph-pan-gesture.h>
49 #include <dali/internal/update/graphics/graphics-algorithms.h>
50 #include <dali/internal/update/manager/render-task-processor.h>
51 #include <dali/internal/update/manager/sorted-layers.h>
52 #include <dali/internal/update/manager/transform-manager.h>
53 #include <dali/internal/update/manager/update-algorithms.h>
54 #include <dali/internal/update/manager/update-manager-debug.h>
55 #include <dali/internal/update/nodes/node.h>
56 #include <dali/internal/update/nodes/scene-graph-layer.h>
57 #include <dali/internal/update/queue/update-message-queue.h>
58 #include <dali/internal/update/render-tasks/scene-graph-camera.h>
59 #include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
60 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
61 #include <dali/internal/update/rendering/render-instruction-container.h>
62 #include <dali/internal/update/rendering/shader-cache.h>
64 #include <dali/graphics-api/graphics-api-buffer-factory.h>
65 #include <dali/graphics-api/graphics-api-buffer.h>
67 // Un-comment to enable node tree debug logging
68 //#define NODE_TREE_LOGGING 1
70 #if ( defined( DEBUG_ENABLED ) && defined( NODE_TREE_LOGGING ) )
71 #define SNAPSHOT_NODE_LOGGING \
72 const int FRAME_COUNT_TRIGGER = 16;\
73 if( mImpl->frameCounter >= FRAME_COUNT_TRIGGER )\
75 if ( NULL != mImpl->root )\
77 mImpl->frameCounter = 0;\
78 PrintNodeTree( *mImpl->root, mSceneGraphBuffers.GetUpdateBufferIndex(), "" );\
81 mImpl->frameCounter++;
83 #define SNAPSHOT_NODE_LOGGING
86 #if defined(DEBUG_ENABLED)
87 extern Debug::Filter* gRenderTaskLogFilter;
91 using namespace Dali::Integration;
92 using Dali::Internal::Update::MessageQueue;
106 * Helper to reset animate-able objects to base values
107 * @param container to iterate over
108 * @param updateBufferIndex to use
111 inline void ResetToBaseValues( OwnerContainer<T*>& container, BufferIndex updateBufferIndex )
113 // Reset animatable properties to base values
114 // use reference to avoid extra copies of the iterator
115 for( auto&& iter : container )
117 iter->ResetToBaseValues( updateBufferIndex );
122 * Helper to Erase an object from OwnerContainer using discard queue
123 * @param container to remove from
124 * @param object to remove
125 * @param discardQueue to put the object to
126 * @param updateBufferIndex to use
129 inline void EraseUsingDiscardQueue( OwnerContainer<T*>& container, T* object, DiscardQueue& discardQueue, BufferIndex updateBufferIndex )
131 DALI_ASSERT_DEBUG( object && "NULL object not allowed" );
133 // need to use the reference version of auto as we need the pointer to the pointer for the Release call below
134 for( auto&& iter : container )
136 if ( iter == object )
138 // Transfer ownership to the discard queue, this keeps the object alive, until the render-thread has finished with it
139 discardQueue.Add( updateBufferIndex, container.Release( &iter ) ); // take the address of the reference to a pointer (iter)
140 return; // return as we only ever remove one object. Iterators to container are now invalidated as well so cannot continue
146 * Descends into node's hierarchy and sorts the children of each child according to their depth-index.
147 * @param[in] node The node whose hierarchy to descend
149 void SortSiblingNodesRecursively( Node& node )
151 NodeContainer& container = node.GetChildren();
152 std::sort( container.Begin(), container.End(),
153 []( Node* a, Node* b ) { return a->GetDepthIndex() < b->GetDepthIndex(); } );
155 // Descend tree and sort as well
156 for( auto&& iter : container )
158 SortSiblingNodesRecursively( *iter );
162 } // unnamed namespace
166 * Structure to contain UpdateManager internal data
168 struct UpdateManager::Impl
170 Impl( NotificationManager& notificationManager,
171 CompleteNotificationInterface& animationPlaylist,
172 PropertyNotifier& propertyNotifier,
173 DiscardQueue& discardQueue,
174 RenderController& renderController,
175 SceneGraphBuffers& sceneGraphBuffers,
176 RenderTaskProcessor& renderTaskProcessor,
177 Integration::Graphics::Graphics& graphics )
178 : notificationManager( notificationManager ),
180 animationPlaylist( animationPlaylist ),
181 propertyNotifier( propertyNotifier ),
182 discardQueue( discardQueue ),
183 renderController( renderController ),
184 sceneController( NULL ),
185 renderInstructions( ),
186 renderTaskProcessor( renderTaskProcessor ),
187 graphics( graphics ),
188 backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
189 taskList( /*renderMessageDispatcher*/ ),
190 systemLevelTaskList( /*renderMessageDispatcher*/ ),
192 systemLevelRoot( NULL ),
196 panGestureProcessor( NULL ),
197 messageQueue( renderController, sceneGraphBuffers ),
198 keepRenderingSeconds( 0.0f ),
199 nodeDirtyFlags( TransformFlag ), // set to TransformFlag to ensure full update the first time through Update()
201 animationFinishedDuringUpdate( false ),
202 previousUpdateScene( false ),
203 renderTaskWaiting( false ),
204 renderersAdded( false ),
205 shaderCache( graphics.GetController() )
207 sceneController = new SceneControllerImpl( discardQueue );
209 // create first 'dummy' node
215 // Disconnect render tasks from nodes, before destroying the nodes
216 RenderTaskList::RenderTaskContainer& tasks = taskList.GetTasks();
217 for ( auto&& iter : tasks )
219 iter->SetSourceNode( NULL );
221 // ..repeat for system level RenderTasks
222 RenderTaskList::RenderTaskContainer& systemLevelTasks = systemLevelTaskList.GetTasks();
223 for ( auto&& iter : systemLevelTasks )
225 iter->SetSourceNode( NULL );
228 // UpdateManager owns the Nodes. Although Nodes are pool allocated they contain heap allocated parts
229 // like custom properties, which get released here
230 Vector<Node*>::Iterator iter = nodes.Begin()+1;
231 Vector<Node*>::Iterator endIter = nodes.End();
232 for(;iter!=endIter;++iter)
234 (*iter)->OnDestroy();
238 // If there is root, reset it, otherwise do nothing as rendering was never started
243 Node::Delete( root );
247 if( systemLevelRoot )
249 systemLevelRoot->OnDestroy();
251 Node::Delete( systemLevelRoot );
252 systemLevelRoot = NULL;
255 delete sceneController;
258 SceneGraphBuffers sceneGraphBuffers; ///< Used to keep track of which buffers are being written or read
259 NotificationManager& notificationManager; ///< Queues notification messages for the event-thread.
260 TransformManager transformManager; ///< Used to update the transformation matrices of the nodes
261 CompleteNotificationInterface& animationPlaylist; ///< Holds handles to all the animations
262 PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
264 DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
265 RenderController& renderController; ///< render controller
266 SceneControllerImpl* sceneController; ///< scene controller
267 RenderInstructionContainer renderInstructions; ///< Used to prepare the render instructions @todo GRAPHICS Remove
268 RenderTaskProcessor& renderTaskProcessor; ///< Handles RenderTasks and RenderInstrucitons
270 Integration::Graphics::Graphics& graphics; ///< Graphics
272 Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
274 RenderTaskList taskList; ///< The list of scene graph render-tasks
275 RenderTaskList systemLevelTaskList; ///< Separate render-tasks for system-level content
277 Layer* root; ///< The root node (root is a layer)
278 Layer* systemLevelRoot; ///< A separate root-node for system-level content
280 Vector<Node*> nodes; ///< A container of all instantiated nodes
282 SortedLayerPointers sortedLayers; ///< A container of Layer pointers sorted by depth
283 SortedLayerPointers systemLevelSortedLayers; ///< A separate container of system-level Layers
285 OwnerContainer< Camera* > cameras; ///< A container of cameras
286 OwnerContainer< PropertyOwner* > customObjects; ///< A container of owned objects (with custom properties)
288 AnimationContainer animations; ///< A container of owned animations
289 PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
291 OwnerContainer< Renderer* > renderers; ///< A container of owned renderers
292 OwnerContainer< TextureSet* > textureSets; ///< A container of owned texture sets
293 OwnerContainer< Shader* > shaders; ///< A container of owned shaders
294 OwnerContainer< Sampler* > samplerContainer; ///< A container of owned samplers
295 OwnerContainer< Texture* > textureContainer; ///< A container of owned textures
296 OwnerContainer< FrameBuffer* > frameBufferContainer; ///< A container of owned framebuffers
297 OwnerContainer< PropertyBuffer* > propertyBufferContainer; ///< A container of owned property buffers
298 OwnerContainer< Geometry* > geometryContainer; ///< A container of owned Geometries
300 OwnerPointer< PanGesture > panGestureProcessor; ///< Owned pan gesture processor; it lives for the lifecycle of UpdateManager
302 MessageQueue messageQueue; ///< The messages queued from the event-thread
304 float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
305 int nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
306 int frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
308 bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
309 bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
310 bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
311 bool renderersAdded; ///< Flag to keep track when renderers have been added to avoid unnecessary processing
313 ShaderCache shaderCache;
317 Impl( const Impl& ); ///< Undefined
318 Impl& operator=( const Impl& ); ///< Undefined
321 UpdateManager::UpdateManager( NotificationManager& notificationManager,
322 CompleteNotificationInterface& animationFinishedNotifier,
323 PropertyNotifier& propertyNotifier,
324 DiscardQueue& discardQueue,
325 RenderController& controller,
326 RenderTaskProcessor& renderTaskProcessor,
327 Integration::Graphics::Graphics& graphics )
328 : mImpl( new Impl( notificationManager,
329 animationFinishedNotifier,
339 UpdateManager::~UpdateManager()
341 // required due to unique_ptr to mImpl
345 void UpdateManager::InstallRoot( OwnerPointer<Layer>& layer, bool systemLevel )
347 DALI_ASSERT_DEBUG( layer->IsLayer() );
348 DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
352 DALI_ASSERT_DEBUG( mImpl->root == NULL && "Root Node already installed" );
353 mImpl->root = layer.Release();
354 mImpl->root->CreateTransform( &mImpl->transformManager );
355 mImpl->root->SetRoot(true);
359 DALI_ASSERT_DEBUG( mImpl->systemLevelRoot == NULL && "System-level Root Node already installed" );
360 mImpl->systemLevelRoot = layer.Release();
361 mImpl->systemLevelRoot->CreateTransform( &mImpl->transformManager );
362 mImpl->systemLevelRoot->SetRoot(true);
366 void UpdateManager::AddNode( OwnerPointer<Node>& node )
368 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
370 // Nodes must be sorted by pointer
371 Node* rawNode = node.Release();
372 Vector<Node*>::Iterator begin = mImpl->nodes.Begin();
373 for( Vector<Node*>::Iterator iter = mImpl->nodes.End()-1; iter >= begin; --iter )
375 if( rawNode > (*iter) )
377 mImpl->nodes.Insert((iter+1), rawNode );
378 rawNode->CreateTransform( &mImpl->transformManager );
384 void UpdateManager::ConnectNode( Node* parent, Node* node )
386 DALI_ASSERT_ALWAYS( NULL != parent );
387 DALI_ASSERT_ALWAYS( NULL != node );
388 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
390 parent->ConnectChild( node );
393 void UpdateManager::DisconnectNode( Node* node )
395 Node* parent = node->GetParent();
396 DALI_ASSERT_ALWAYS( NULL != parent );
397 parent->SetDirtyFlag( ChildDeletedFlag ); // make parent dirty so that render items dont get reused
399 parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node );
402 void UpdateManager::DestroyNode( Node* node )
404 DALI_ASSERT_ALWAYS( NULL != node );
405 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
407 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
408 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
409 for(;iter!=endIter;++iter)
413 mImpl->nodes.Erase(iter);
418 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
420 // Notify the Node about impending destruction
424 void UpdateManager::AddCamera( OwnerPointer< Camera >& camera )
426 mImpl->cameras.PushBack( camera.Release() ); // takes ownership
429 void UpdateManager::RemoveCamera( const Camera* camera )
431 // Find the camera and destroy it
432 EraseUsingDiscardQueue( mImpl->cameras, const_cast<Camera*>( camera ), mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
435 void UpdateManager::AddObject( OwnerPointer<PropertyOwner>& object )
437 mImpl->customObjects.PushBack( object.Release() );
440 void UpdateManager::RemoveObject( PropertyOwner* object )
442 mImpl->customObjects.EraseObject( object );
445 void UpdateManager::AddAnimation( OwnerPointer< SceneGraph::Animation >& animation )
447 mImpl->animations.PushBack( animation.Release() );
450 void UpdateManager::StopAnimation( Animation* animation )
452 DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
454 bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
456 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
459 void UpdateManager::RemoveAnimation( Animation* animation )
461 DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
463 animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
465 DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
468 bool UpdateManager::IsAnimationRunning() const
470 // Find any animation that isn't stopped or paused
471 for ( auto&& iter : mImpl->animations )
473 const Animation::State state = iter->GetState();
475 if (state != Animation::Stopped &&
476 state != Animation::Paused)
478 return true; // stop iteration as soon as first one is found
485 void UpdateManager::AddPropertyNotification( OwnerPointer< PropertyNotification >& propertyNotification )
487 mImpl->propertyNotifications.PushBack( propertyNotification.Release() );
490 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
492 mImpl->propertyNotifications.EraseObject( propertyNotification );
495 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
497 DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
498 propertyNotification->SetNotifyMode( notifyMode );
501 void UpdateManager::AddShader( OwnerPointer< Shader >& shader )
503 shader->Initialize( mImpl->graphics, mImpl->shaderCache );
504 mImpl->shaders.PushBack( shader.Release() );
507 void UpdateManager::RemoveShader( Shader* shader )
509 // Find the shader and destroy it
510 EraseUsingDiscardQueue( mImpl->shaders, shader, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
513 void UpdateManager::AddRenderer( OwnerPointer< Renderer >& renderer )
515 renderer->Initialize( mImpl->graphics );
516 mImpl->renderers.PushBack( renderer.Release() );
517 mImpl->renderersAdded = true;
520 void UpdateManager::RemoveRenderer( Renderer* renderer )
522 // Find the renderer and destroy it
523 // @todo Don't need to use discard queue for SceneGraph::Renderer any more ( No dependency from Graphics::RenderCommand )
524 EraseUsingDiscardQueue( mImpl->renderers, renderer, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
527 void UpdateManager::SetPanGestureProcessor( PanGesture* panGestureProcessor )
529 DALI_ASSERT_DEBUG( NULL != panGestureProcessor );
531 mImpl->panGestureProcessor = panGestureProcessor;
534 void UpdateManager::AddTextureSet( OwnerPointer< TextureSet >& textureSet )
536 mImpl->textureSets.PushBack( textureSet.Release() );
539 void UpdateManager::RemoveTextureSet( TextureSet* textureSet )
541 mImpl->textureSets.EraseObject( textureSet );
544 RenderTaskList* UpdateManager::GetRenderTaskList( bool systemLevel )
548 // copy the list, this is only likely to happen once in application life cycle
549 return &(mImpl->taskList);
553 // copy the list, this is only likely to happen once in application life cycle
554 return &(mImpl->systemLevelTaskList);
558 unsigned int* UpdateManager::ReserveMessageSlot( std::size_t size, bool updateScene )
560 return mImpl->messageQueue.ReserveMessageSlot( size, updateScene );
563 void UpdateManager::EventProcessingStarted()
565 mImpl->messageQueue.EventProcessingStarted();
568 bool UpdateManager::FlushQueue()
570 return mImpl->messageQueue.FlushQueue();
573 void UpdateManager::ResetProperties( BufferIndex bufferIndex )
575 // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
576 mImpl->animationFinishedDuringUpdate = false;
578 // Animated properties have to be reset to their original value each frame
580 // Reset root properties
583 mImpl->root->ResetToBaseValues( bufferIndex );
585 if ( mImpl->systemLevelRoot )
587 mImpl->systemLevelRoot->ResetToBaseValues( bufferIndex );
590 // Reset all the nodes
591 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
592 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
593 for( ;iter != endIter; ++iter )
595 (*iter)->ResetToBaseValues( bufferIndex );
598 // Reset system-level render-task list properties to base values
599 ResetToBaseValues( mImpl->systemLevelTaskList.GetTasks(), bufferIndex );
601 // Reset render-task list properties to base values.
602 ResetToBaseValues( mImpl->taskList.GetTasks(), bufferIndex );
604 // Reset custom object properties to base values
605 ResetToBaseValues( mImpl->customObjects, bufferIndex );
607 // Reset animatable renderer properties to base values
608 ResetToBaseValues( mImpl->renderers, bufferIndex );
610 // Reset animatable shader properties to base values
611 ResetToBaseValues( mImpl->shaders, bufferIndex );
614 bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds )
616 bool gestureUpdated( false );
618 if( mImpl->panGestureProcessor )
620 // gesture processor only supports default properties
621 mImpl->panGestureProcessor->ResetDefaultProperties( bufferIndex ); // Needs to be done every time as gesture data is written directly to an update-buffer rather than via a message
622 gestureUpdated |= mImpl->panGestureProcessor->UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
625 return gestureUpdated;
628 void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
630 AnimationContainer &animations = mImpl->animations;
631 AnimationIter iter = animations.Begin();
632 bool animationLooped = false;
634 while ( iter != animations.End() )
636 Animation* animation = *iter;
637 bool finished = false;
639 bool progressMarkerReached = false;
640 animation->Update( bufferIndex, elapsedSeconds, looped, finished, progressMarkerReached );
642 if ( progressMarkerReached )
644 mImpl->notificationManager.QueueMessage( Internal::NotifyProgressReachedMessage( mImpl->animationPlaylist, animation ) );
647 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
648 animationLooped = animationLooped || looped;
650 // Remove animations that had been destroyed but were still waiting for an update
651 if (animation->GetState() == Animation::Destroyed)
653 iter = animations.Erase(iter);
661 // queue the notification on finished or looped (to update loop count)
662 if ( mImpl->animationFinishedDuringUpdate || animationLooped )
664 // The application should be notified by NotificationManager, in another thread
665 mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationPlaylist );
669 void UpdateManager::ConstrainCustomObjects( BufferIndex bufferIndex )
671 //Constrain custom objects (in construction order)
672 for ( auto&& object : mImpl->customObjects )
674 ConstrainPropertyOwner( *object, bufferIndex );
678 void UpdateManager::ConstrainRenderTasks( BufferIndex bufferIndex )
680 // Constrain system-level render-tasks
681 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
682 for ( auto&& task : systemLevelTasks )
684 ConstrainPropertyOwner( *task, bufferIndex );
687 // Constrain render-tasks
688 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
689 for ( auto&& task : tasks )
691 ConstrainPropertyOwner( *task, bufferIndex );
695 void UpdateManager::ConstrainShaders( BufferIndex bufferIndex )
697 // constrain shaders... (in construction order)
698 for ( auto&& shader : mImpl->shaders )
700 ConstrainPropertyOwner( *shader, bufferIndex );
704 void UpdateManager::ProcessPropertyNotifications( BufferIndex bufferIndex )
706 for( auto&& notification : mImpl->propertyNotifications )
708 bool valid = notification->Check( bufferIndex );
711 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
716 void UpdateManager::UpdateRenderers( BufferIndex bufferIndex )
718 const unsigned int rendererCount = mImpl->renderers.Count();
719 for( unsigned int i = 0; i < rendererCount; ++i )
722 ConstrainPropertyOwner( *mImpl->renderers[i], bufferIndex );
724 mImpl->renderers[i]->PrepareRender( bufferIndex );
728 void UpdateManager::UpdateNodes( BufferIndex bufferIndex )
730 mImpl->nodeDirtyFlags = NothingFlag;
737 // Prepare resources, update shaders, for each node
738 // And add the renderers to the sorted layers. Start from root, which is also a layer
739 mImpl->nodeDirtyFlags = UpdateNodeTree( *( mImpl->root ), bufferIndex );
741 if ( mImpl->systemLevelRoot )
743 mImpl->nodeDirtyFlags |= UpdateNodeTree( *( mImpl->systemLevelRoot ), bufferIndex );
747 unsigned int UpdateManager::Update( float elapsedSeconds,
748 unsigned int lastVSyncTimeMilliseconds,
749 unsigned int nextVSyncTimeMilliseconds,
750 bool renderToFboEnabled,
751 bool isRenderingToFbo )
753 const BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
755 //Clear nodes/resources which were previously discarded
756 mImpl->discardQueue.Clear( bufferIndex );
758 //Process Touches & Gestures
759 const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
761 bool updateScene = // The scene-graph requires an update if..
762 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
763 IsAnimationRunning() || // ..at least one animation is running OR
764 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
765 gestureUpdated; // ..a gesture property was updated
768 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
769 // values if the scene was updated in the previous frame.
770 if( updateScene || mImpl->previousUpdateScene )
772 //Reset properties from the previous update
773 ResetProperties( bufferIndex );
774 mImpl->transformManager.ResetToBaseValue();
777 // Process the queued scene messages. Note, MessageQueue::FlushQueue may be called
778 // between calling IsSceneUpdateRequired() above and here, so updateScene should
780 updateScene |= mImpl->messageQueue.ProcessMessages( bufferIndex );
782 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
783 // renderer lists if the scene was updated in the previous frame.
784 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
785 if( updateScene || mImpl->previousUpdateScene )
788 Animate( bufferIndex, elapsedSeconds );
790 //Constraint custom objects
791 ConstrainCustomObjects( bufferIndex );
793 //Clear the lists of renderers from the previous update
794 for( size_t i(0); i<mImpl->sortedLayers.size(); ++i )
796 mImpl->sortedLayers[i]->ClearRenderables();
799 for( size_t i(0); i<mImpl->systemLevelSortedLayers.size(); ++i )
801 mImpl->systemLevelSortedLayers[i]->ClearRenderables();
804 //Update node hierarchy, apply constraints and perform sorting / culling.
805 //This will populate each Layer with a list of renderers which are ready.
806 UpdateNodes( bufferIndex );
808 //Apply constraints to RenderTasks, shaders
809 ConstrainRenderTasks( bufferIndex );
810 ConstrainShaders( bufferIndex );
812 //Update renderers and apply constraints
813 UpdateRenderers( bufferIndex );
815 //Update the trnasformations of all the nodes
816 mImpl->transformManager.Update();
818 //Process Property Notifications
819 ProcessPropertyNotifications( bufferIndex );
822 for( auto&& cameraIterator : mImpl->cameras )
824 cameraIterator->Update( bufferIndex );
827 //Process the RenderTasks if renderers exist. This creates the instructions for rendering the next frame.
828 //reset the update buffer index and make sure there is enough room in the instruction container
829 if( mImpl->renderersAdded )
831 mImpl->renderInstructions.ResetAndReserve(bufferIndex,
832 mImpl->taskList.GetTasks().Count() +
833 mImpl->systemLevelTaskList.GetTasks().Count());
835 if ( NULL != mImpl->root )
837 mImpl->renderTaskProcessor.Process( bufferIndex,
841 mImpl->renderInstructions,
845 // Process the system-level RenderTasks last
846 if ( NULL != mImpl->systemLevelRoot )
848 mImpl->renderTaskProcessor.Process( bufferIndex,
849 mImpl->systemLevelTaskList,
850 *mImpl->systemLevelRoot,
851 mImpl->systemLevelSortedLayers,
852 mImpl->renderInstructions,
857 // generate graphics objects
859 SubmitRenderInstructions( mImpl->graphics.GetController(), mImpl->renderInstructions, bufferIndex );
863 // check the countdown and notify (note, at the moment this is only done for normal tasks, not for systemlevel tasks)
864 bool doRenderOnceNotify = false;
865 mImpl->renderTaskWaiting = false;
866 for ( auto&& renderTask : mImpl->taskList.GetTasks() )
868 renderTask->UpdateState();
870 if( renderTask->IsWaitingToRender() &&
871 renderTask->ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
873 mImpl->renderTaskWaiting = true; // keep update/render threads alive
876 if( renderTask->HasRendered() )
878 doRenderOnceNotify = true;
882 if( doRenderOnceNotify )
884 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
885 mImpl->notificationManager.QueueCompleteNotification( mImpl->taskList.GetCompleteNotificationInterface() );
888 // Macro is undefined in release build.
889 SNAPSHOT_NODE_LOGGING;
891 // A ResetProperties() may be required in the next frame
892 mImpl->previousUpdateScene = updateScene;
894 // Check whether further updates are required
895 unsigned int keepUpdating = KeepUpdatingCheck( elapsedSeconds );
897 // tell the update manager that we're done so the queue can be given to event thread
898 mImpl->notificationManager.UpdateCompleted();
900 // The update has finished; swap the double-buffering indices
901 mSceneGraphBuffers.Swap();
906 unsigned int UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
908 // Update the duration set via Stage::KeepRendering()
909 if ( mImpl->keepRenderingSeconds > 0.0f )
911 mImpl->keepRenderingSeconds -= elapsedSeconds;
914 unsigned int keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
916 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
917 // Keep updating until no messages are received and no animations are running.
918 // If an animation has just finished, update at least once more for Discard end-actions.
919 // No need to check for renderQueue as there is always a render after update and if that
920 // render needs another update it will tell the adaptor to call update again
922 if ( mImpl->keepRenderingSeconds > 0.0f )
924 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
927 if ( IsAnimationRunning() ||
928 mImpl->animationFinishedDuringUpdate )
930 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
933 if ( mImpl->renderTaskWaiting )
935 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
938 return keepUpdatingRequest;
941 void UpdateManager::SetBackgroundColor( const Vector4& color )
943 DALI_ASSERT_ALWAYS( true && "GRAPHICS: FIXME" );
946 void UpdateManager::SetDefaultSurfaceRect( const Rect<int>& rect )
948 DALI_ASSERT_ALWAYS( true && "GRAPHICS: FIXME" );
951 void UpdateManager::KeepRendering( float durationSeconds )
953 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
956 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, bool systemLevel )
960 // just copy the vector of pointers
961 mImpl->sortedLayers = layers;
965 mImpl->systemLevelSortedLayers = layers;
969 void UpdateManager::SetDepthIndices( OwnerPointer< NodeDepths >& nodeDepths )
971 // note,this vector is already in depth order. It could be used as-is to
972 // remove sorting in update algorithm. However, it lacks layer boundary markers.
973 for( auto&& iter : nodeDepths->nodeDepths )
975 iter.node->SetDepthIndex( iter.sortedDepth );
978 // Go through node hierarchy and rearrange siblings according to depth-index
979 SortSiblingNodesRecursively( *( mImpl->root ) );
982 void UpdateManager::AddSampler( OwnerPointer< SceneGraph::Sampler >& sampler )
984 mImpl->samplerContainer.PushBack( sampler.Release() );
987 void UpdateManager::RemoveSampler( SceneGraph::Sampler* sampler )
989 mImpl->samplerContainer.EraseObject( sampler );
992 void UpdateManager::AddPropertyBuffer( OwnerPointer< SceneGraph::PropertyBuffer >& propertyBuffer )
994 propertyBuffer->Initialize( mImpl->graphics );
995 mImpl->propertyBufferContainer.PushBack( propertyBuffer.Release() );
998 void UpdateManager::RemovePropertyBuffer( SceneGraph::PropertyBuffer* propertyBuffer )
1000 mImpl->propertyBufferContainer.EraseObject( propertyBuffer );
1003 void UpdateManager::AddGeometry( OwnerPointer< SceneGraph::Geometry >& geometry )
1005 geometry->Initialize( mImpl->graphics );
1006 mImpl->geometryContainer.PushBack( geometry.Release() );
1009 void UpdateManager::RemoveGeometry( SceneGraph::Geometry* geometry )
1011 mImpl->geometryContainer.EraseObject( geometry );
1014 void UpdateManager::AddTexture( OwnerPointer< SceneGraph::Texture >& texture )
1016 texture->Initialize( mImpl->graphics );
1017 mImpl->textureContainer.PushBack( texture.Release() );
1020 void UpdateManager::RemoveTexture( SceneGraph::Texture* texture)
1022 DALI_ASSERT_DEBUG( NULL != texture );
1024 // Find the texture, use reference to pointer so we can do the erase safely
1025 for ( auto&& iter : mImpl->textureContainer )
1027 if ( iter == texture )
1029 mImpl->textureContainer.Erase( &iter ); // Texture found; now destroy it
1035 void UpdateManager::AddFrameBuffer( OwnerPointer< SceneGraph::FrameBuffer>& frameBuffer )
1037 frameBuffer->Initialize( mImpl->graphics );
1038 mImpl->frameBufferContainer.PushBack( frameBuffer.Release() );
1041 void UpdateManager::RemoveFrameBuffer( SceneGraph::FrameBuffer* frameBuffer)
1043 DALI_ASSERT_DEBUG( NULL != frameBuffer );
1045 // Find the sampler, use reference so we can safely do the erase
1046 for ( auto&& iter : mImpl->frameBufferContainer )
1048 if ( iter == frameBuffer )
1050 mImpl->frameBufferContainer.Erase( &iter ); // frameBuffer found; now destroy it
1057 } // namespace SceneGraph
1059 } // namespace Internal