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.
19 #include <dali/internal/update/manager/update-manager.h>
22 #include <dali/public-api/common/stage.h>
23 #include <dali/devel-api/common/owner-container.h>
24 #include <dali/devel-api/threading/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/message.h>
34 #include <dali/internal/event/common/notification-manager.h>
35 #include <dali/internal/event/common/property-notification-impl.h>
36 #include <dali/internal/event/common/property-notifier.h>
37 #include <dali/internal/event/effects/shader-factory.h>
38 #include <dali/internal/event/animation/animation-playlist.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/render-task-processor.h>
48 #include <dali/internal/update/manager/sorted-layers.h>
49 #include <dali/internal/update/manager/update-algorithms.h>
50 #include <dali/internal/update/manager/update-manager-debug.h>
51 #include <dali/internal/update/manager/transform-manager.h>
52 #include <dali/internal/update/nodes/node.h>
53 #include <dali/internal/update/nodes/scene-graph-layer.h>
54 #include <dali/internal/update/queue/update-message-queue.h>
55 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
56 #include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
57 #include <dali/internal/update/render-tasks/scene-graph-camera.h>
59 #include <dali/internal/render/common/render-instruction-container.h>
60 #include <dali/internal/render/common/render-manager.h>
61 #include <dali/internal/render/queue/render-queue.h>
62 #include <dali/internal/render/shaders/scene-graph-shader.h>
64 // Un-comment to enable node tree debug logging
65 //#define NODE_TREE_LOGGING 1
67 #if ( defined( DEBUG_ENABLED ) && defined( NODE_TREE_LOGGING ) )
68 #define SNAPSHOT_NODE_LOGGING \
69 const int FRAME_COUNT_TRIGGER = 16;\
70 if( mImpl->frameCounter >= FRAME_COUNT_TRIGGER )\
72 if ( NULL != mImpl->root )\
74 mImpl->frameCounter = 0;\
75 PrintNodeTree( *mImpl->root, mSceneGraphBuffers.GetUpdateBufferIndex(), "" );\
78 mImpl->frameCounter++;
80 #define SNAPSHOT_NODE_LOGGING
83 #if defined(DEBUG_ENABLED)
84 extern Debug::Filter* gRenderTaskLogFilter;
88 using namespace Dali::Integration;
89 using Dali::Internal::Update::MessageQueue;
103 * Helper to reset animate-able objects to base values
104 * @param container to iterate over
105 * @param updateBufferIndex to use
108 inline void ResetToBaseValues( OwnerContainer<T*>& container, BufferIndex updateBufferIndex )
110 // Reset animatable properties to base values
111 // use reference to avoid extra copies of the iterator
112 for( auto&& iter : container )
114 iter->ResetToBaseValues( updateBufferIndex );
119 * Helper to Erase an object from OwnerContainer using discard queue
120 * @param container to remove from
121 * @param object to remove
122 * @param discardQueue to put the object to
123 * @param updateBufferIndex to use
126 inline void EraseUsingDiscardQueue( OwnerContainer<T*>& container, T* object, DiscardQueue& discardQueue, BufferIndex updateBufferIndex )
128 DALI_ASSERT_DEBUG( object && "NULL object not allowed" );
130 // need to use the reference version of auto as we need the pointer to the pointer for the Release call below
131 for( auto&& iter : container )
133 if ( iter == object )
135 // Transfer ownership to the discard queue, this keeps the object alive, until the render-thread has finished with it
136 discardQueue.Add( updateBufferIndex, container.Release( &iter ) ); // take the address of the reference to a pointer (iter)
137 return; // return as we only ever remove one object. Iterators to container are now invalidated as well so cannot continue
143 * Descends into node's hierarchy and sorts the children of each child according to their depth-index.
144 * @param[in] node The node whose hierarchy to descend
146 void SortSiblingNodesRecursively( Node& node )
148 NodeContainer& container = node.GetChildren();
149 std::sort( container.Begin(), container.End(),
150 []( Node* a, Node* b ) { return a->GetDepthIndex() < b->GetDepthIndex(); } );
152 // Descend tree and sort as well
153 for( auto&& iter : container )
155 SortSiblingNodesRecursively( *iter );
159 } // unnamed namespace
162 * Structure to contain UpdateManager internal data
164 struct UpdateManager::Impl
166 Impl( NotificationManager& notificationManager,
167 CompleteNotificationInterface& animationPlaylist,
168 PropertyNotifier& propertyNotifier,
169 DiscardQueue& discardQueue,
170 RenderController& renderController,
171 RenderManager& renderManager,
172 RenderQueue& renderQueue,
173 SceneGraphBuffers& sceneGraphBuffers,
174 RenderTaskProcessor& renderTaskProcessor )
175 : renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ),
176 notificationManager( notificationManager ),
178 animationPlaylist( animationPlaylist ),
179 propertyNotifier( propertyNotifier ),
181 discardQueue( discardQueue ),
182 renderController( renderController ),
183 sceneController( NULL ),
184 renderManager( renderManager ),
185 renderQueue( renderQueue ),
186 renderInstructions( renderManager.GetRenderInstructionContainer() ),
187 renderTaskProcessor( renderTaskProcessor ),
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 renderingBehavior( DevelStage::Rendering::IF_REQUIRED ),
202 animationFinishedDuringUpdate( false ),
203 previousUpdateScene( false ),
204 renderTaskWaiting( false ),
205 renderersAdded( false ),
206 surfaceRectChanged( false )
208 sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue );
210 // create first 'dummy' node
216 // Disconnect render tasks from nodes, before destroying the nodes
217 RenderTaskList::RenderTaskContainer& tasks = taskList.GetTasks();
218 for ( auto&& iter : tasks )
220 iter->SetSourceNode( NULL );
222 // ..repeat for system level RenderTasks
223 RenderTaskList::RenderTaskContainer& systemLevelTasks = systemLevelTaskList.GetTasks();
224 for ( auto&& iter : systemLevelTasks )
226 iter->SetSourceNode( NULL );
229 // UpdateManager owns the Nodes. Although Nodes are pool allocated they contain heap allocated parts
230 // like custom properties, which get released here
231 Vector<Node*>::Iterator iter = nodes.Begin()+1;
232 Vector<Node*>::Iterator endIter = nodes.End();
233 for(;iter!=endIter;++iter)
235 (*iter)->OnDestroy();
239 // If there is root, reset it, otherwise do nothing as rendering was never started
244 Node::Delete( root );
248 if( systemLevelRoot )
250 systemLevelRoot->OnDestroy();
252 Node::Delete( systemLevelRoot );
253 systemLevelRoot = NULL;
256 delete sceneController;
259 SceneGraphBuffers sceneGraphBuffers; ///< Used to keep track of which buffers are being written or read
260 RenderMessageDispatcher renderMessageDispatcher; ///< Used for passing messages to the render-thread
261 NotificationManager& notificationManager; ///< Queues notification messages for the event-thread.
262 TransformManager transformManager; ///< Used to update the transformation matrices of the nodes
263 CompleteNotificationInterface& animationPlaylist; ///< Holds handles to all the animations
264 PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
265 ShaderSaver* shaderSaver; ///< Saves shader binaries.
266 DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
267 RenderController& renderController; ///< render controller
268 SceneControllerImpl* sceneController; ///< scene controller
269 RenderManager& renderManager; ///< This is responsible for rendering the results of each "update"
270 RenderQueue& renderQueue; ///< Used to queue messages for the next render
271 RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions
272 RenderTaskProcessor& renderTaskProcessor; ///< Handles RenderTasks and RenderInstrucitons
274 Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
276 RenderTaskList taskList; ///< The list of scene graph render-tasks
277 RenderTaskList systemLevelTaskList; ///< Separate render-tasks for system-level content
279 Layer* root; ///< The root node (root is a layer)
280 Layer* systemLevelRoot; ///< A separate root-node for system-level content
282 Vector<Node*> nodes; ///< A container of all instantiated nodes
284 SortedLayerPointers sortedLayers; ///< A container of Layer pointers sorted by depth
285 SortedLayerPointers systemLevelSortedLayers; ///< A separate container of system-level Layers
287 OwnerContainer< Camera* > cameras; ///< A container of cameras
288 OwnerContainer< PropertyOwner* > customObjects; ///< A container of owned objects (with custom properties)
290 OwnerContainer< PropertyResetterBase* > propertyResetters; ///< A container of property resetters
291 AnimationContainer animations; ///< A container of owned animations
292 PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
293 OwnerContainer< Renderer* > renderers; ///< A container of owned renderers
294 OwnerContainer< TextureSet* > textureSets; ///< A container of owned texture sets
295 OwnerContainer< Shader* > shaders; ///< A container of owned shaders
296 OwnerPointer< PanGesture > panGestureProcessor; ///< Owned pan gesture processor; it lives for the lifecycle of UpdateManager
298 MessageQueue messageQueue; ///< The messages queued from the event-thread
299 std::vector<Internal::ShaderDataPtr> renderCompiledShaders; ///< Shaders compiled on Render thread are inserted here for update thread to pass on to event thread.
300 std::vector<Internal::ShaderDataPtr> updateCompiledShaders; ///< Shaders to be sent from Update to Event
301 Mutex compiledShaderMutex; ///< lock to ensure no corruption on the renderCompiledShaders
303 float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
304 int nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
305 int frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
307 DevelStage::Rendering renderingBehavior; ///< Set via DevelStage::SetRenderingBehavior
309 bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
310 bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
311 bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
312 bool renderersAdded; ///< Flag to keep track when renderers have been added to avoid unnecessary processing
313 bool surfaceRectChanged; ///< True if the default surface rect is changed
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 RenderManager& renderManager,
327 RenderQueue& renderQueue,
328 RenderTaskProcessor& renderTaskProcessor )
331 mImpl = new Impl( notificationManager,
332 animationFinishedNotifier,
339 renderTaskProcessor );
343 UpdateManager::~UpdateManager()
348 void UpdateManager::InstallRoot( OwnerPointer<Layer>& layer, bool systemLevel )
350 DALI_ASSERT_DEBUG( layer->IsLayer() );
351 DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
355 DALI_ASSERT_DEBUG( mImpl->root == NULL && "Root Node already installed" );
356 mImpl->root = layer.Release();
357 mImpl->root->CreateTransform( &mImpl->transformManager );
358 mImpl->root->SetRoot(true);
362 DALI_ASSERT_DEBUG( mImpl->systemLevelRoot == NULL && "System-level Root Node already installed" );
363 mImpl->systemLevelRoot = layer.Release();
364 mImpl->systemLevelRoot->CreateTransform( &mImpl->transformManager );
365 mImpl->systemLevelRoot->SetRoot(true);
370 void UpdateManager::AddNode( OwnerPointer<Node>& node )
372 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
374 // Nodes must be sorted by pointer
375 Node* rawNode = node.Release();
376 Vector<Node*>::Iterator begin = mImpl->nodes.Begin();
377 for( Vector<Node*>::Iterator iter = mImpl->nodes.End()-1; iter >= begin; --iter )
379 if( rawNode > (*iter) )
381 mImpl->nodes.Insert((iter+1), rawNode );
382 rawNode->CreateTransform( &mImpl->transformManager );
388 void UpdateManager::ConnectNode( Node* parent, Node* node )
390 DALI_ASSERT_ALWAYS( NULL != parent );
391 DALI_ASSERT_ALWAYS( NULL != node );
392 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
394 parent->ConnectChild( node );
397 void UpdateManager::DisconnectNode( Node* node )
399 Node* parent = node->GetParent();
400 DALI_ASSERT_ALWAYS( NULL != parent );
401 parent->SetDirtyFlag( ChildDeletedFlag ); // make parent dirty so that render items dont get reused
403 parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node );
406 void UpdateManager::DestroyNode( Node* node )
408 DALI_ASSERT_ALWAYS( NULL != node );
409 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
411 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
412 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
413 for(;iter!=endIter;++iter)
417 mImpl->nodes.Erase(iter);
422 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
424 // Notify the Node about impending destruction
428 void UpdateManager::AddCamera( OwnerPointer< Camera >& camera )
430 mImpl->cameras.PushBack( camera.Release() ); // takes ownership
433 void UpdateManager::RemoveCamera( const Camera* camera )
435 // Find the camera and destroy it
436 EraseUsingDiscardQueue( mImpl->cameras, const_cast<Camera*>( camera ), mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
439 void UpdateManager::AddObject( OwnerPointer<PropertyOwner>& object )
441 mImpl->customObjects.PushBack( object.Release() );
444 void UpdateManager::RemoveObject( PropertyOwner* object )
446 mImpl->customObjects.EraseObject( object );
449 void UpdateManager::AddAnimation( OwnerPointer< SceneGraph::Animation >& animation )
451 mImpl->animations.PushBack( animation.Release() );
454 void UpdateManager::StopAnimation( Animation* animation )
456 DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
458 bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
460 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
463 void UpdateManager::RemoveAnimation( Animation* animation )
465 DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
467 animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
469 DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
472 bool UpdateManager::IsAnimationRunning() const
474 // Find any animation that isn't stopped or paused
475 for ( auto&& iter : mImpl->animations )
477 const Animation::State state = iter->GetState();
479 if (state != Animation::Stopped &&
480 state != Animation::Paused)
482 return true; // stop iteration as soon as first one is found
489 void UpdateManager::AddPropertyResetter( OwnerPointer<PropertyResetterBase>& propertyResetter )
491 propertyResetter->Initialize();
492 mImpl->propertyResetters.PushBack( propertyResetter.Release() );
495 void UpdateManager::AddPropertyNotification( OwnerPointer< PropertyNotification >& propertyNotification )
497 mImpl->propertyNotifications.PushBack( propertyNotification.Release() );
500 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
502 mImpl->propertyNotifications.EraseObject( propertyNotification );
505 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
507 DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
508 propertyNotification->SetNotifyMode( notifyMode );
511 void UpdateManager::AddShader( OwnerPointer< Shader >& shader )
513 mImpl->shaders.PushBack( shader.Release() );
516 void UpdateManager::RemoveShader( Shader* shader )
518 // Find the shader and destroy it
519 EraseUsingDiscardQueue( mImpl->shaders, shader, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
522 void UpdateManager::SetShaderProgram( Shader* shader,
523 Internal::ShaderDataPtr shaderData, bool modifiesGeometry )
528 typedef MessageValue3< Shader, Internal::ShaderDataPtr, ProgramCache*, bool> DerivedType;
530 // Reserve some memory inside the render queue
531 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
533 // Construct message in the render queue memory; note that delete should not be called on the return value
534 new (slot) DerivedType( shader, &Shader::SetProgram, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
538 void UpdateManager::SaveBinary( Internal::ShaderDataPtr shaderData )
540 DALI_ASSERT_DEBUG( shaderData && "No NULL shader data pointers please." );
541 DALI_ASSERT_DEBUG( shaderData->GetBufferSize() > 0 && "Shader binary empty so nothing to save." );
543 // lock as update might be sending previously compiled shaders to event thread
544 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
545 mImpl->renderCompiledShaders.push_back( shaderData );
549 void UpdateManager::SetShaderSaver( ShaderSaver& upstream )
551 mImpl->shaderSaver = &upstream;
554 void UpdateManager::AddRenderer( OwnerPointer< Renderer >& renderer )
556 renderer->ConnectToSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
557 mImpl->renderers.PushBack( renderer.Release() );
558 mImpl->renderersAdded = true;
561 void UpdateManager::RemoveRenderer( Renderer* renderer )
563 // Find the renderer and destroy it
564 EraseUsingDiscardQueue( mImpl->renderers, renderer, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
565 // Need to remove the render object as well
566 renderer->DisconnectFromSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
569 void UpdateManager::SetPanGestureProcessor( PanGesture* panGestureProcessor )
571 DALI_ASSERT_DEBUG( NULL != panGestureProcessor );
573 mImpl->panGestureProcessor = panGestureProcessor;
576 void UpdateManager::AddTextureSet( OwnerPointer< TextureSet >& textureSet )
578 mImpl->textureSets.PushBack( textureSet.Release() );
581 void UpdateManager::RemoveTextureSet( TextureSet* textureSet )
583 mImpl->textureSets.EraseObject( textureSet );
586 RenderTaskList* UpdateManager::GetRenderTaskList( bool systemLevel )
590 // copy the list, this is only likely to happen once in application life cycle
591 return &(mImpl->taskList);
595 // copy the list, this is only likely to happen once in application life cycle
596 return &(mImpl->systemLevelTaskList);
600 unsigned int* UpdateManager::ReserveMessageSlot( std::size_t size, bool updateScene )
602 return mImpl->messageQueue.ReserveMessageSlot( size, updateScene );
605 void UpdateManager::EventProcessingStarted()
607 mImpl->messageQueue.EventProcessingStarted();
610 bool UpdateManager::FlushQueue()
612 return mImpl->messageQueue.FlushQueue();
615 void UpdateManager::ResetProperties( BufferIndex bufferIndex )
617 // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
618 mImpl->animationFinishedDuringUpdate = false;
620 // Reset all animating / constrained properties
621 std::vector<PropertyResetterBase*>toDelete;
622 for( auto&& element : mImpl->propertyResetters )
624 element->ResetToBaseValue( bufferIndex );
625 if( element->IsFinished() )
627 toDelete.push_back( element );
631 // If a resetter is no longer required (the animator or constraint has been removed), delete it.
632 for( auto&& elementPtr : toDelete )
634 mImpl->propertyResetters.EraseObject( elementPtr );
637 // Clear node dirty flags
638 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
639 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
640 for( ;iter != endIter; ++iter )
642 (*iter)->ResetDirtyFlags( bufferIndex );
646 bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds )
648 bool gestureUpdated( false );
650 if( mImpl->panGestureProcessor )
652 // gesture processor only supports default properties
653 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
654 gestureUpdated |= mImpl->panGestureProcessor->UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
657 return gestureUpdated;
660 void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
662 AnimationContainer &animations = mImpl->animations;
663 AnimationIter iter = animations.Begin();
664 bool animationLooped = false;
666 while ( iter != animations.End() )
668 Animation* animation = *iter;
669 bool finished = false;
671 bool progressMarkerReached = false;
672 animation->Update( bufferIndex, elapsedSeconds, looped, finished, progressMarkerReached );
674 if ( progressMarkerReached )
676 mImpl->notificationManager.QueueMessage( Internal::NotifyProgressReachedMessage( mImpl->animationPlaylist, animation ) );
679 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
680 animationLooped = animationLooped || looped;
682 // Remove animations that had been destroyed but were still waiting for an update
683 if (animation->GetState() == Animation::Destroyed)
685 iter = animations.Erase(iter);
693 // queue the notification on finished or looped (to update loop count)
694 if ( mImpl->animationFinishedDuringUpdate || animationLooped )
696 // The application should be notified by NotificationManager, in another thread
697 mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationPlaylist );
701 void UpdateManager::ConstrainCustomObjects( BufferIndex bufferIndex )
703 //Constrain custom objects (in construction order)
704 for ( auto&& object : mImpl->customObjects )
706 ConstrainPropertyOwner( *object, bufferIndex );
710 void UpdateManager::ConstrainRenderTasks( BufferIndex bufferIndex )
712 // Constrain system-level render-tasks
713 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
714 for ( auto&& task : systemLevelTasks )
716 ConstrainPropertyOwner( *task, bufferIndex );
719 // Constrain render-tasks
720 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
721 for ( auto&& task : tasks )
723 ConstrainPropertyOwner( *task, bufferIndex );
727 void UpdateManager::ConstrainShaders( BufferIndex bufferIndex )
729 // constrain shaders... (in construction order)
730 for ( auto&& shader : mImpl->shaders )
732 ConstrainPropertyOwner( *shader, bufferIndex );
736 void UpdateManager::ProcessPropertyNotifications( BufferIndex bufferIndex )
738 for( auto&& notification : mImpl->propertyNotifications )
740 bool valid = notification->Check( bufferIndex );
743 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
748 void UpdateManager::ForwardCompiledShadersToEventThread()
750 DALI_ASSERT_DEBUG( (mImpl->shaderSaver != 0) && "shaderSaver should be wired-up during startup." );
751 if( mImpl->shaderSaver )
753 // lock and swap the queues
755 // render might be attempting to send us more binaries at the same time
756 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
757 mImpl->renderCompiledShaders.swap( mImpl->updateCompiledShaders );
760 if( mImpl->updateCompiledShaders.size() > 0 )
762 ShaderSaver& factory = *mImpl->shaderSaver;
763 for( auto&& shader : mImpl->updateCompiledShaders )
765 mImpl->notificationManager.QueueMessage( ShaderCompiledMessage( factory, shader ) );
767 // we don't need them in update anymore
768 mImpl->updateCompiledShaders.clear();
773 void UpdateManager::UpdateRenderers( BufferIndex bufferIndex )
775 const unsigned int rendererCount = mImpl->renderers.Count();
776 for( unsigned int i = 0; i < rendererCount; ++i )
779 ConstrainPropertyOwner( *mImpl->renderers[i], bufferIndex );
781 mImpl->renderers[i]->PrepareRender( bufferIndex );
785 void UpdateManager::UpdateNodes( BufferIndex bufferIndex )
787 mImpl->nodeDirtyFlags = NothingFlag;
794 // Prepare resources, update shaders, for each node
795 // And add the renderers to the sorted layers. Start from root, which is also a layer
796 mImpl->nodeDirtyFlags = UpdateNodeTree( *( mImpl->root ),
798 mImpl->renderQueue );
800 if ( mImpl->systemLevelRoot )
802 mImpl->nodeDirtyFlags |= UpdateNodeTree( *( mImpl->systemLevelRoot ),
804 mImpl->renderQueue );
808 unsigned int UpdateManager::Update( float elapsedSeconds,
809 unsigned int lastVSyncTimeMilliseconds,
810 unsigned int nextVSyncTimeMilliseconds,
811 bool renderToFboEnabled,
812 bool isRenderingToFbo )
814 const BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
816 //Clear nodes/resources which were previously discarded
817 mImpl->discardQueue.Clear( bufferIndex );
819 //Process Touches & Gestures
820 const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
822 bool updateScene = // The scene-graph requires an update if..
823 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
824 IsAnimationRunning() || // ..at least one animation is running OR
825 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
826 gestureUpdated; // ..a gesture property was updated
829 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
830 // values if the scene was updated in the previous frame.
831 if( updateScene || mImpl->previousUpdateScene )
833 //Reset properties from the previous update
834 ResetProperties( bufferIndex );
835 mImpl->transformManager.ResetToBaseValue();
838 // Process the queued scene messages. Note, MessageQueue::FlushQueue may be called
839 // between calling IsSceneUpdateRequired() above and here, so updateScene should
841 updateScene |= mImpl->messageQueue.ProcessMessages( bufferIndex );
843 //Forward compiled shader programs to event thread for saving
844 ForwardCompiledShadersToEventThread();
846 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
847 // renderer lists if the scene was updated in the previous frame.
848 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
849 if( updateScene || mImpl->previousUpdateScene )
852 Animate( bufferIndex, elapsedSeconds );
854 //Constraint custom objects
855 ConstrainCustomObjects( bufferIndex );
857 //Clear the lists of renderers from the previous update
858 for( size_t i(0); i<mImpl->sortedLayers.size(); ++i )
860 mImpl->sortedLayers[i]->ClearRenderables();
863 for( size_t i(0); i<mImpl->systemLevelSortedLayers.size(); ++i )
865 mImpl->systemLevelSortedLayers[i]->ClearRenderables();
868 //Update node hierarchy, apply constraints and perform sorting / culling.
869 //This will populate each Layer with a list of renderers which are ready.
870 UpdateNodes( bufferIndex );
872 //Apply constraints to RenderTasks, shaders
873 ConstrainRenderTasks( bufferIndex );
874 ConstrainShaders( bufferIndex );
876 //Update renderers and apply constraints
877 UpdateRenderers( bufferIndex );
879 //Update the transformations of all the nodes
880 mImpl->transformManager.Update();
882 //Process Property Notifications
883 ProcessPropertyNotifications( bufferIndex );
886 for( auto&& cameraIterator : mImpl->cameras )
888 cameraIterator->Update( bufferIndex );
891 //Process the RenderTasks if renderers exist. This creates the instructions for rendering the next frame.
892 //reset the update buffer index and make sure there is enough room in the instruction container
893 if( mImpl->renderersAdded )
895 mImpl->renderInstructions.ResetAndReserve( bufferIndex,
896 mImpl->taskList.GetTasks().Count() + mImpl->systemLevelTaskList.GetTasks().Count() );
898 if ( NULL != mImpl->root )
900 mImpl->renderTaskProcessor.Process( bufferIndex,
904 mImpl->renderInstructions,
908 // Process the system-level RenderTasks last
909 if ( NULL != mImpl->systemLevelRoot )
911 mImpl->renderTaskProcessor.Process( bufferIndex,
912 mImpl->systemLevelTaskList,
913 *mImpl->systemLevelRoot,
914 mImpl->systemLevelSortedLayers,
915 mImpl->renderInstructions,
923 // check the countdown and notify (note, at the moment this is only done for normal tasks, not for systemlevel tasks)
924 bool doRenderOnceNotify = false;
925 mImpl->renderTaskWaiting = false;
926 for ( auto&& renderTask : mImpl->taskList.GetTasks() )
928 renderTask->UpdateState();
930 if( renderTask->IsWaitingToRender() &&
931 renderTask->ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
933 mImpl->renderTaskWaiting = true; // keep update/render threads alive
936 if( renderTask->HasRendered() )
938 doRenderOnceNotify = true;
942 if( doRenderOnceNotify )
944 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
945 mImpl->notificationManager.QueueCompleteNotification( mImpl->taskList.GetCompleteNotificationInterface() );
948 // Macro is undefined in release build.
949 SNAPSHOT_NODE_LOGGING;
951 // A ResetProperties() may be required in the next frame
952 mImpl->previousUpdateScene = updateScene;
954 // Check whether further updates are required
955 unsigned int keepUpdating = KeepUpdatingCheck( elapsedSeconds );
957 // tell the update manager that we're done so the queue can be given to event thread
958 mImpl->notificationManager.UpdateCompleted();
960 // The update has finished; swap the double-buffering indices
961 mSceneGraphBuffers.Swap();
966 unsigned int UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
968 // Update the duration set via Stage::KeepRendering()
969 if ( mImpl->keepRenderingSeconds > 0.0f )
971 mImpl->keepRenderingSeconds -= elapsedSeconds;
974 unsigned int keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
976 // If the rendering behavior is set to continuously render, then continue to render.
977 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
978 // Keep updating until no messages are received and no animations are running.
979 // If an animation has just finished, update at least once more for Discard end-actions.
980 // No need to check for renderQueue as there is always a render after update and if that
981 // render needs another update it will tell the adaptor to call update again
983 if ( ( mImpl->renderingBehavior == DevelStage::Rendering::CONTINUOUSLY ) ||
984 ( mImpl->keepRenderingSeconds > 0.0f ) )
986 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
989 if ( IsAnimationRunning() ||
990 mImpl->animationFinishedDuringUpdate )
992 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
995 if ( mImpl->renderTaskWaiting )
997 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
1000 return keepUpdatingRequest;
1003 void UpdateManager::SetBackgroundColor( const Vector4& color )
1005 typedef MessageValue1< RenderManager, Vector4 > DerivedType;
1007 // Reserve some memory inside the render queue
1008 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1010 // Construct message in the render queue memory; note that delete should not be called on the return value
1011 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
1014 void UpdateManager::SetDefaultSurfaceRect( const Rect<int>& rect )
1016 mImpl->surfaceRectChanged = true;
1018 typedef MessageValue1< RenderManager, Rect<int> > DerivedType;
1020 // Reserve some memory inside the render queue
1021 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1023 // Construct message in the render queue memory; note that delete should not be called on the return value
1024 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1027 void UpdateManager::KeepRendering( float durationSeconds )
1029 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1032 void UpdateManager::SetRenderingBehavior( DevelStage::Rendering renderingBehavior )
1034 mImpl->renderingBehavior = renderingBehavior;
1037 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, bool systemLevel )
1041 // just copy the vector of pointers
1042 mImpl->sortedLayers = layers;
1046 mImpl->systemLevelSortedLayers = layers;
1050 void UpdateManager::SetDepthIndices( OwnerPointer< NodeDepths >& nodeDepths )
1052 // note,this vector is already in depth order. It could be used as-is to
1053 // remove sorting in update algorithm. However, it lacks layer boundary markers.
1054 for( auto&& iter : nodeDepths->nodeDepths )
1056 iter.node->SetDepthIndex( iter.sortedDepth );
1059 // Go through node hierarchy and rearrange siblings according to depth-index
1060 SortSiblingNodesRecursively( *( mImpl->root ) );
1063 bool UpdateManager::IsDefaultSurfaceRectChanged()
1065 bool surfaceRectChanged = mImpl->surfaceRectChanged;
1068 mImpl->surfaceRectChanged = false;
1070 return surfaceRectChanged;
1073 void UpdateManager::AddSampler( OwnerPointer< Render::Sampler >& sampler )
1075 // Message has ownership of Sampler while in transit from update to render
1076 typedef MessageValue1< RenderManager, OwnerPointer< Render::Sampler > > 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::AddSampler, sampler );
1085 void UpdateManager::RemoveSampler( Render::Sampler* sampler )
1087 typedef MessageValue1< RenderManager, Render::Sampler* > 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::RemoveSampler, sampler );
1096 void UpdateManager::SetFilterMode( Render::Sampler* sampler, unsigned int minFilterMode, unsigned int magFilterMode )
1098 typedef MessageValue3< RenderManager, Render::Sampler*, unsigned int, unsigned int > DerivedType;
1100 // Reserve some memory inside the render queue
1101 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1103 // Construct message in the render queue memory; note that delete should not be called on the return value
1104 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetFilterMode, sampler, minFilterMode, magFilterMode );
1107 void UpdateManager::SetWrapMode( Render::Sampler* sampler, unsigned int rWrapMode, unsigned int sWrapMode, unsigned int tWrapMode )
1109 typedef MessageValue4< RenderManager, Render::Sampler*, unsigned int, unsigned int, unsigned int > DerivedType;
1111 // Reserve some memory inside the render queue
1112 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1114 // Construct message in the render queue memory; note that delete should not be called on the return value
1115 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetWrapMode, sampler, rWrapMode, sWrapMode, tWrapMode );
1118 void UpdateManager::AddPropertyBuffer( OwnerPointer< Render::PropertyBuffer >& propertyBuffer )
1120 // Message has ownership of format while in transit from update -> render
1121 typedef MessageValue1< RenderManager, OwnerPointer< Render::PropertyBuffer > > 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::AddPropertyBuffer, propertyBuffer );
1130 void UpdateManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer )
1132 typedef MessageValue1< RenderManager, Render::PropertyBuffer* > 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::RemovePropertyBuffer, propertyBuffer );
1141 void UpdateManager::SetPropertyBufferFormat( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Render::PropertyBuffer::Format>& format )
1143 // Message has ownership of format while in transit from update -> render
1144 typedef MessageValue2< RenderManager, Render::PropertyBuffer*, OwnerPointer< Render::PropertyBuffer::Format > > DerivedType;
1146 // Reserve some memory inside the render queue
1147 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1149 // Construct message in the render queue memory; note that delete should not be called on the return value
1150 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferFormat, propertyBuffer, format );
1153 void UpdateManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Vector<char> >& data, size_t size )
1155 // Message has ownership of format while in transit from update -> render
1156 typedef MessageValue3< RenderManager, Render::PropertyBuffer*, OwnerPointer< Dali::Vector<char> >, size_t > DerivedType;
1158 // Reserve some memory inside the render queue
1159 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1161 // Construct message in the render queue memory; note that delete should not be called on the return value
1162 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferData, propertyBuffer, data, size );
1165 void UpdateManager::AddGeometry( OwnerPointer< Render::Geometry >& geometry )
1167 // Message has ownership of format while in transit from update -> render
1168 typedef MessageValue1< RenderManager, OwnerPointer< Render::Geometry > > 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::AddGeometry, geometry );
1177 void UpdateManager::RemoveGeometry( Render::Geometry* geometry )
1179 typedef MessageValue1< RenderManager, Render::Geometry* > 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::RemoveGeometry, geometry );
1188 void UpdateManager::SetGeometryType( Render::Geometry* geometry, unsigned int geometryType )
1190 typedef MessageValue2< RenderManager, Render::Geometry*, unsigned int > DerivedType;
1192 // Reserve some memory inside the render queue
1193 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1195 // Construct message in the render queue memory; note that delete should not be called on the return value
1196 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetGeometryType, geometry, geometryType );
1199 void UpdateManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector<unsigned short>& indices )
1201 typedef IndexBufferMessage< RenderManager > DerivedType;
1203 // Reserve some memory inside the render queue
1204 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1206 // Construct message in the render queue memory; note that delete should not be called on the return value
1207 new (slot) DerivedType( &mImpl->renderManager, geometry, indices );
1210 void UpdateManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1212 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1214 // Reserve some memory inside the render queue
1215 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1217 // Construct message in the render queue memory; note that delete should not be called on the return value
1218 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveVertexBuffer, geometry, propertyBuffer );
1221 void UpdateManager::AttachVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1223 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1225 // Reserve some memory inside the render queue
1226 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1228 // Construct message in the render queue memory; note that delete should not be called on the return value
1229 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AttachVertexBuffer, geometry, propertyBuffer );
1232 void UpdateManager::AddTexture( OwnerPointer< Render::Texture >& texture )
1234 // Message has ownership of Texture while in transit from update -> render
1235 typedef MessageValue1< RenderManager, OwnerPointer< Render::Texture > > DerivedType;
1237 // Reserve some memory inside the render queue
1238 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1240 // Construct message in the render queue memory; note that delete should not be called on the return value
1241 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddTexture, texture );
1244 void UpdateManager::RemoveTexture( Render::Texture* texture)
1246 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1248 // Reserve some memory inside the render queue
1249 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1251 // Construct message in the render queue memory; note that delete should not be called on the return value
1252 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveTexture, texture );
1255 void UpdateManager::UploadTexture( Render::Texture* texture, PixelDataPtr pixelData, const Texture::UploadParams& params )
1257 typedef MessageValue3< RenderManager, Render::Texture*, PixelDataPtr, Texture::UploadParams > DerivedType;
1259 // Reserve some memory inside the message queue
1260 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1262 // Construct message in the message queue memory; note that delete should not be called on the return value
1263 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::UploadTexture, texture, pixelData, params );
1266 void UpdateManager::GenerateMipmaps( Render::Texture* texture )
1268 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1270 // Reserve some memory inside the render queue
1271 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1273 // Construct message in the render queue memory; note that delete should not be called on the return value
1274 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::GenerateMipmaps, texture );
1277 void UpdateManager::AddFrameBuffer( Render::FrameBuffer* frameBuffer )
1279 typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType;
1281 // Reserve some memory inside the render queue
1282 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1284 // Construct message in the render queue memory; note that delete should not be called on the return value
1285 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddFrameBuffer, frameBuffer );
1288 void UpdateManager::RemoveFrameBuffer( Render::FrameBuffer* frameBuffer)
1290 typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType;
1292 // Reserve some memory inside the render queue
1293 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1295 // Construct message in the render queue memory; note that delete should not be called on the return value
1296 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveFrameBuffer, frameBuffer );
1299 void UpdateManager::AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, unsigned int mipmapLevel, unsigned int layer )
1301 typedef MessageValue4< RenderManager, Render::FrameBuffer*, Render::Texture*, unsigned int, unsigned int > DerivedType;
1303 // Reserve some memory inside the render queue
1304 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1306 // Construct message in the render queue memory; note that delete should not be called on the return value
1307 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AttachColorTextureToFrameBuffer, frameBuffer, texture, mipmapLevel, layer );
1310 } // namespace SceneGraph
1312 } // namespace Internal