2 * Copyright (c) 2017 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>
39 #include <dali/internal/update/animation/scene-graph-animator.h>
40 #include <dali/internal/update/animation/scene-graph-animation.h>
41 #include <dali/internal/update/common/discard-queue.h>
42 #include <dali/internal/update/common/scene-graph-buffers.h>
43 #include <dali/internal/update/controllers/render-message-dispatcher.h>
44 #include <dali/internal/update/controllers/scene-controller-impl.h>
45 #include <dali/internal/update/gestures/scene-graph-pan-gesture.h>
46 #include <dali/internal/update/manager/render-task-processor.h>
47 #include <dali/internal/update/manager/sorted-layers.h>
48 #include <dali/internal/update/manager/update-algorithms.h>
49 #include <dali/internal/update/manager/update-manager-debug.h>
50 #include <dali/internal/update/manager/transform-manager.h>
51 #include <dali/internal/update/nodes/node.h>
52 #include <dali/internal/update/nodes/scene-graph-layer.h>
53 #include <dali/internal/update/queue/update-message-queue.h>
54 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
55 #include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
56 #include <dali/internal/update/render-tasks/scene-graph-camera.h>
58 #include <dali/internal/render/common/render-instruction-container.h>
59 #include <dali/internal/render/common/render-manager.h>
60 #include <dali/internal/render/queue/render-queue.h>
61 #include <dali/internal/render/shaders/scene-graph-shader.h>
63 // Un-comment to enable node tree debug logging
64 //#define NODE_TREE_LOGGING 1
66 #if ( defined( DEBUG_ENABLED ) && defined( NODE_TREE_LOGGING ) )
67 #define SNAPSHOT_NODE_LOGGING \
68 const int FRAME_COUNT_TRIGGER = 16;\
69 if( mImpl->frameCounter >= FRAME_COUNT_TRIGGER )\
71 if ( NULL != mImpl->root )\
73 mImpl->frameCounter = 0;\
74 PrintNodeTree( *mImpl->root, mSceneGraphBuffers.GetUpdateBufferIndex(), "" );\
77 mImpl->frameCounter++;
79 #define SNAPSHOT_NODE_LOGGING
82 #if defined(DEBUG_ENABLED)
83 extern Debug::Filter* gRenderTaskLogFilter;
87 using namespace Dali::Integration;
88 using Dali::Internal::Update::MessageQueue;
102 * Helper to reset animate-able objects to base values
103 * @param container to iterate over
104 * @param updateBufferIndex to use
107 inline void ResetToBaseValues( OwnerContainer<T*>& container, BufferIndex updateBufferIndex )
109 // Reset animatable properties to base values
110 typename OwnerContainer<T*>::Iterator iter = container.Begin();
111 const typename OwnerContainer<T*>::ConstIterator endIter = container.End();
112 for ( ; iter != endIter; ++iter )
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 typename OwnerContainer<T*>::Iterator iter = container.Begin();
131 const typename OwnerContainer<T*>::ConstIterator endIter = container.End();
132 for ( ; iter != endIter; ++iter )
134 if ( *iter == object )
136 // Transfer ownership to the discard queue, this keeps the object alive, until the render-thread has finished with it
137 discardQueue.Add( updateBufferIndex, container.Release( iter ) );
145 typedef OwnerContainer< Shader* > ShaderOwner;
146 typedef ShaderOwner::Iterator ShaderIter;
147 typedef std::vector<Internal::ShaderDataPtr> ShaderDataBinaryQueue;
149 typedef OwnerContainer< TextureSet* > TextureSetOwner;
150 typedef TextureSetOwner::Iterator TextureSetIter;
152 typedef OwnerContainer<Renderer*> RendererOwner;
153 typedef RendererOwner::Iterator RendererIter;
155 typedef OwnerContainer< Camera* > CameraOwner;
156 typedef OwnerContainer< PropertyOwner* > CustomObjectOwner;
159 * Structure to contain UpdateManager internal data
161 struct UpdateManager::Impl
163 Impl( NotificationManager& notificationManager,
164 CompleteNotificationInterface& animationFinishedNotifier,
165 PropertyNotifier& propertyNotifier,
166 DiscardQueue& discardQueue,
167 RenderController& renderController,
168 RenderManager& renderManager,
169 RenderQueue& renderQueue,
170 SceneGraphBuffers& sceneGraphBuffers,
171 RenderTaskProcessor& renderTaskProcessor )
172 : renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ),
173 notificationManager( notificationManager ),
175 animationFinishedNotifier( animationFinishedNotifier ),
176 propertyNotifier( propertyNotifier ),
178 discardQueue( discardQueue ),
179 renderController( renderController ),
180 sceneController( NULL ),
181 renderManager( renderManager ),
182 renderQueue( renderQueue ),
183 renderInstructions( renderManager.GetRenderInstructionContainer() ),
184 renderTaskProcessor( renderTaskProcessor ),
185 backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
186 taskList( renderMessageDispatcher ),
187 systemLevelTaskList( renderMessageDispatcher ),
189 systemLevelRoot( NULL ),
193 panGestureProcessor( NULL ),
194 messageQueue( renderController, sceneGraphBuffers ),
195 keepRenderingSeconds( 0.0f ),
196 nodeDirtyFlags( TransformFlag ), // set to TransformFlag to ensure full update the first time through Update()
198 animationFinishedDuringUpdate( false ),
199 previousUpdateScene( false ),
200 renderTaskWaiting( false )
202 sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue );
204 // create first 'dummy' node
210 // Disconnect render tasks from nodes, before destroying the nodes
211 RenderTaskList::RenderTaskContainer& tasks = taskList.GetTasks();
212 for (RenderTaskList::RenderTaskContainer::Iterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
214 (*iter)->SetSourceNode( NULL );
216 // ..repeat for system level RenderTasks
217 RenderTaskList::RenderTaskContainer& systemLevelTasks = systemLevelTaskList.GetTasks();
218 for (RenderTaskList::RenderTaskContainer::Iterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
220 (*iter)->SetSourceNode( NULL );
223 // UpdateManager owns the Nodes
224 Vector<Node*>::Iterator iter = nodes.Begin()+1;
225 Vector<Node*>::Iterator endIter = nodes.End();
226 for(;iter!=endIter;++iter)
228 (*iter)->OnDestroy();
232 // If there is root, reset it, otherwise do nothing as rendering was never started
237 Node::Delete( root );
241 if( systemLevelRoot )
243 systemLevelRoot->OnDestroy();
245 Node::Delete( systemLevelRoot );
246 systemLevelRoot = NULL;
249 delete sceneController;
252 SceneGraphBuffers sceneGraphBuffers; ///< Used to keep track of which buffers are being written or read
253 RenderMessageDispatcher renderMessageDispatcher; ///< Used for passing messages to the render-thread
254 NotificationManager& notificationManager; ///< Queues notification messages for the event-thread.
255 TransformManager transformManager; ///< Used to update the transformation matrices of the nodes
256 CompleteNotificationInterface& animationFinishedNotifier; ///< Provides notification to applications when animations are finished.
257 PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
258 ShaderSaver* shaderSaver; ///< Saves shader binaries.
259 DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
260 RenderController& renderController; ///< render controller
261 SceneControllerImpl* sceneController; ///< scene controller
262 RenderManager& renderManager; ///< This is responsible for rendering the results of each "update"
263 RenderQueue& renderQueue; ///< Used to queue messages for the next render
264 RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions
265 RenderTaskProcessor& renderTaskProcessor; ///< Handles RenderTasks and RenderInstrucitons
267 Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
269 RenderTaskList taskList; ///< The list of scene graph render-tasks
270 RenderTaskList systemLevelTaskList; ///< Separate render-tasks for system-level content
272 Layer* root; ///< The root node (root is a layer)
273 Layer* systemLevelRoot; ///< A separate root-node for system-level content
275 Vector<Node*> nodes; ///< A container of all instantiated nodes
277 SortedLayerPointers sortedLayers; ///< A container of Layer pointers sorted by depth
278 SortedLayerPointers systemLevelSortedLayers; ///< A separate container of system-level Layers
280 CameraOwner cameras; ///< A container of cameras
281 CustomObjectOwner customObjects; ///< A container of owned objects (with custom properties)
283 AnimationContainer animations; ///< A container of owned animations
284 PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
286 RendererOwner renderers; ///< A container of owned renderers
287 TextureSetOwner textureSets; ///< A container of owned texture sets
288 ShaderOwner shaders; ///< A container of owned shaders
289 OwnerPointer<PanGesture> panGestureProcessor; ///< Owned pan gesture processor; it lives for the lifecycle of UpdateManager
291 MessageQueue messageQueue; ///< The messages queued from the event-thread
292 ShaderDataBinaryQueue renderCompiledShaders; ///< Shaders compiled on Render thread are inserted here for update thread to pass on to event thread.
293 ShaderDataBinaryQueue updateCompiledShaders; ///< Shaders to be sent from Update to Event
294 Mutex compiledShaderMutex; ///< lock to ensure no corruption on the renderCompiledShaders
296 float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
297 int nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
298 int frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
300 bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
301 bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
302 bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
306 Impl( const Impl& ); ///< Undefined
307 Impl& operator=( const Impl& ); ///< Undefined
310 UpdateManager::UpdateManager( NotificationManager& notificationManager,
311 CompleteNotificationInterface& animationFinishedNotifier,
312 PropertyNotifier& propertyNotifier,
313 DiscardQueue& discardQueue,
314 RenderController& controller,
315 RenderManager& renderManager,
316 RenderQueue& renderQueue,
317 RenderTaskProcessor& renderTaskProcessor )
320 mImpl = new Impl( notificationManager,
321 animationFinishedNotifier,
328 renderTaskProcessor );
332 UpdateManager::~UpdateManager()
337 void UpdateManager::InstallRoot( SceneGraph::Layer* layer, bool systemLevel )
339 DALI_ASSERT_DEBUG( layer->IsLayer() );
340 DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
344 DALI_ASSERT_DEBUG( mImpl->root == NULL && "Root Node already installed" );
346 mImpl->root->CreateTransform( &mImpl->transformManager );
350 DALI_ASSERT_DEBUG( mImpl->systemLevelRoot == NULL && "System-level Root Node already installed" );
351 mImpl->systemLevelRoot = layer;
352 mImpl->systemLevelRoot->CreateTransform( &mImpl->transformManager );
355 layer->SetRoot(true);
358 void UpdateManager::AddNode( Node* node )
360 DALI_ASSERT_ALWAYS( NULL != node );
361 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
363 // Nodes must be sorted by pointer
364 Vector<Node*>::Iterator begin = mImpl->nodes.Begin();
365 for(Vector<Node*>::Iterator iter = mImpl->nodes.End()-1; iter >= begin; --iter)
369 mImpl->nodes.Insert((iter+1), node);
370 node->CreateTransform( &mImpl->transformManager );
376 void UpdateManager::ConnectNode( Node* parent, Node* node )
378 DALI_ASSERT_ALWAYS( NULL != parent );
379 DALI_ASSERT_ALWAYS( NULL != node );
380 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
382 parent->ConnectChild( node );
385 void UpdateManager::DisconnectNode( Node* node )
387 Node* parent = node->GetParent();
388 DALI_ASSERT_ALWAYS( NULL != parent );
389 parent->SetDirtyFlag( ChildDeletedFlag ); // make parent dirty so that render items dont get reused
391 parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node );
394 void UpdateManager::DestroyNode( Node* node )
396 DALI_ASSERT_ALWAYS( NULL != node );
397 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
399 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
400 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
401 for(;iter!=endIter;++iter)
405 mImpl->nodes.Erase(iter);
410 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
412 // Notify the Node about impending destruction
416 void UpdateManager::AddCamera( Camera* camera )
418 DALI_ASSERT_DEBUG( camera != NULL );
420 mImpl->cameras.PushBack( camera ); // takes ownership
423 void UpdateManager::RemoveCamera( const Camera* camera )
425 // Find the camera and destroy it
426 EraseUsingDiscardQueue( mImpl->cameras, const_cast<Camera*>( camera ), mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
429 void UpdateManager::AddObject( PropertyOwner* object )
431 DALI_ASSERT_DEBUG( NULL != object );
433 mImpl->customObjects.PushBack( object );
436 void UpdateManager::RemoveObject( PropertyOwner* object )
438 mImpl->customObjects.EraseObject( object );
441 void UpdateManager::AddAnimation( Animation* animation )
443 mImpl->animations.PushBack( animation );
446 void UpdateManager::StopAnimation( Animation* animation )
448 DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
450 bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
452 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
455 void UpdateManager::RemoveAnimation( Animation* animation )
457 DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
459 animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
461 DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
464 bool UpdateManager::IsAnimationRunning() const
466 bool isRunning(false);
467 AnimationContainer& animations = mImpl->animations;
469 // Find any animation that isn't stopped or paused
471 const AnimationIter endIter = animations.End();
472 for ( AnimationIter iter = animations.Begin(); !isRunning && iter != endIter; ++iter )
474 const Animation::State state = (*iter)->GetState();
476 if (state != Animation::Stopped &&
477 state != Animation::Paused)
486 void UpdateManager::AddPropertyNotification( PropertyNotification* propertyNotification )
488 mImpl->propertyNotifications.PushBack( propertyNotification );
491 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
493 mImpl->propertyNotifications.EraseObject( propertyNotification );
496 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
498 DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
499 propertyNotification->SetNotifyMode( notifyMode );
502 void UpdateManager::AddShader( Shader* shader )
504 DALI_ASSERT_DEBUG( NULL != shader );
506 mImpl->shaders.PushBack( shader );
509 void UpdateManager::RemoveShader( Shader* shader )
511 // Find the shader and destroy it
512 EraseUsingDiscardQueue( mImpl->shaders, shader, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
515 void UpdateManager::SetShaderProgram( Shader* shader,
516 Internal::ShaderDataPtr shaderData, bool modifiesGeometry )
521 typedef MessageValue3< Shader, Internal::ShaderDataPtr, ProgramCache*, bool> DerivedType;
523 // Reserve some memory inside the render queue
524 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
526 // Construct message in the render queue memory; note that delete should not be called on the return value
527 new (slot) DerivedType( shader, &Shader::SetProgram, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
531 void UpdateManager::SaveBinary( Internal::ShaderDataPtr shaderData )
533 DALI_ASSERT_DEBUG( shaderData && "No NULL shader data pointers please." );
534 DALI_ASSERT_DEBUG( shaderData->GetBufferSize() > 0 && "Shader binary empty so nothing to save." );
536 // lock as update might be sending previously compiled shaders to event thread
537 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
538 mImpl->renderCompiledShaders.push_back( shaderData );
542 void UpdateManager::SetShaderSaver( ShaderSaver& upstream )
544 mImpl->shaderSaver = &upstream;
547 void UpdateManager::AddRenderer( Renderer* renderer )
549 DALI_ASSERT_DEBUG( renderer != NULL );
551 mImpl->renderers.PushBack( renderer );
553 renderer->ConnectToSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
556 void UpdateManager::RemoveRenderer( Renderer* renderer )
558 // Find the renderer and destroy it
559 EraseUsingDiscardQueue( mImpl->renderers, renderer, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
560 // Need to remove the render object as well
561 renderer->DisconnectFromSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
564 void UpdateManager::SetPanGestureProcessor( PanGesture* panGestureProcessor )
566 DALI_ASSERT_DEBUG( NULL != panGestureProcessor );
568 mImpl->panGestureProcessor = panGestureProcessor;
571 void UpdateManager::AddTextureSet( TextureSet* textureSet )
573 DALI_ASSERT_DEBUG( NULL != textureSet );
575 mImpl->textureSets.PushBack( textureSet );
578 void UpdateManager::RemoveTextureSet( TextureSet* textureSet )
580 mImpl->textureSets.EraseObject( textureSet );
583 RenderTaskList* UpdateManager::GetRenderTaskList( bool systemLevel )
587 // copy the list, this is only likely to happen once in application life cycle
588 return &(mImpl->taskList);
592 // copy the list, this is only likely to happen once in application life cycle
593 return &(mImpl->systemLevelTaskList);
597 unsigned int* UpdateManager::ReserveMessageSlot( std::size_t size, bool updateScene )
599 return mImpl->messageQueue.ReserveMessageSlot( size, updateScene );
602 void UpdateManager::EventProcessingStarted()
604 mImpl->messageQueue.EventProcessingStarted();
607 bool UpdateManager::FlushQueue()
609 return mImpl->messageQueue.FlushQueue();
612 void UpdateManager::ResetProperties( BufferIndex bufferIndex )
614 // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
615 mImpl->animationFinishedDuringUpdate = false;
617 // Animated properties have to be reset to their original value each frame
619 // Reset root properties
622 mImpl->root->ResetToBaseValues( bufferIndex );
624 if ( mImpl->systemLevelRoot )
626 mImpl->systemLevelRoot->ResetToBaseValues( bufferIndex );
629 // Reset all the nodes
630 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
631 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
632 for( ;iter != endIter; ++iter )
634 (*iter)->ResetToBaseValues( bufferIndex );
637 // Reset system-level render-task list properties to base values
638 ResetToBaseValues( mImpl->systemLevelTaskList.GetTasks(), bufferIndex );
640 // Reset render-task list properties to base values.
641 ResetToBaseValues( mImpl->taskList.GetTasks(), bufferIndex );
643 // Reset custom object properties to base values
644 ResetToBaseValues( mImpl->customObjects, bufferIndex );
646 // Reset animatable renderer properties to base values
647 ResetToBaseValues( mImpl->renderers, bufferIndex );
649 // Reset animatable shader properties to base values
650 ResetToBaseValues( mImpl->shaders, bufferIndex );
653 bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds )
655 bool gestureUpdated( false );
657 if( mImpl->panGestureProcessor )
659 // gesture processor only supports default properties
660 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
661 gestureUpdated |= mImpl->panGestureProcessor->UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
664 return gestureUpdated;
667 void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
669 AnimationContainer &animations = mImpl->animations;
670 AnimationIter iter = animations.Begin();
671 bool animationLooped = false;
672 while ( iter != animations.End() )
674 Animation* animation = *iter;
675 bool finished = false;
677 animation->Update( bufferIndex, elapsedSeconds, looped, finished );
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->animationFinishedNotifier );
701 void UpdateManager::ConstrainCustomObjects( BufferIndex bufferIndex )
703 //Constrain custom objects (in construction order)
704 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
705 const OwnerContainer< PropertyOwner* >::Iterator endIter = customObjects.End();
706 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); endIter != iter; ++iter )
708 PropertyOwner& object = **iter;
709 ConstrainPropertyOwner( object, bufferIndex );
713 void UpdateManager::ConstrainRenderTasks( BufferIndex bufferIndex )
715 // Constrain system-level render-tasks
716 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
717 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter )
719 RenderTask& task = **iter;
720 ConstrainPropertyOwner( task, bufferIndex );
723 // Constrain render-tasks
724 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
725 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter )
727 RenderTask& task = **iter;
728 ConstrainPropertyOwner( task, bufferIndex );
732 void UpdateManager::ConstrainShaders( BufferIndex bufferIndex )
734 // constrain shaders... (in construction order)
735 ShaderOwner& shaders = mImpl->shaders;
736 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
738 Shader& shader = **iter;
739 ConstrainPropertyOwner( shader, bufferIndex );
743 void UpdateManager::ProcessPropertyNotifications( BufferIndex bufferIndex )
745 PropertyNotificationContainer ¬ifications = mImpl->propertyNotifications;
746 PropertyNotificationIter iter = notifications.Begin();
748 while ( iter != notifications.End() )
750 PropertyNotification* notification = *iter;
751 bool valid = notification->Check( bufferIndex );
754 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
760 void UpdateManager::ForwardCompiledShadersToEventThread()
762 DALI_ASSERT_DEBUG( (mImpl->shaderSaver != 0) && "shaderSaver should be wired-up during startup." );
763 if( mImpl->shaderSaver )
765 // lock and swap the queues
767 // render might be attempting to send us more binaries at the same time
768 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
769 mImpl->renderCompiledShaders.swap( mImpl->updateCompiledShaders );
772 if( mImpl->updateCompiledShaders.size() > 0 )
774 ShaderSaver& factory = *mImpl->shaderSaver;
775 ShaderDataBinaryQueue::iterator i = mImpl->updateCompiledShaders.begin();
776 ShaderDataBinaryQueue::iterator end = mImpl->updateCompiledShaders.end();
777 for( ; i != end; ++i )
779 mImpl->notificationManager.QueueMessage( ShaderCompiledMessage( factory, *i ) );
781 // we don't need them in update anymore
782 mImpl->updateCompiledShaders.clear();
787 void UpdateManager::UpdateRenderers( BufferIndex bufferIndex )
789 const unsigned int rendererCount = mImpl->renderers.Count();
790 for( unsigned int i = 0; i < rendererCount; ++i )
793 ConstrainPropertyOwner( *mImpl->renderers[i], bufferIndex );
795 mImpl->renderers[i]->PrepareRender( bufferIndex );
799 void UpdateManager::UpdateNodes( BufferIndex bufferIndex )
801 mImpl->nodeDirtyFlags = NothingFlag;
808 // Prepare resources, update shaders, for each node
809 // And add the renderers to the sorted layers. Start from root, which is also a layer
810 mImpl->nodeDirtyFlags = UpdateNodeTree( *( mImpl->root ),
812 mImpl->renderQueue );
814 if ( mImpl->systemLevelRoot )
816 mImpl->nodeDirtyFlags |= UpdateNodeTree( *( mImpl->systemLevelRoot ),
818 mImpl->renderQueue );
822 unsigned int UpdateManager::Update( float elapsedSeconds,
823 unsigned int lastVSyncTimeMilliseconds,
824 unsigned int nextVSyncTimeMilliseconds )
826 const BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
828 //Clear nodes/resources which were previously discarded
829 mImpl->discardQueue.Clear( bufferIndex );
831 //Process Touches & Gestures
832 const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
834 bool updateScene = // The scene-graph requires an update if..
835 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
836 IsAnimationRunning() || // ..at least one animation is running OR
837 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
838 gestureUpdated; // ..a gesture property was updated
841 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
842 // values if the scene was updated in the previous frame.
843 if( updateScene || mImpl->previousUpdateScene )
845 //Reset properties from the previous update
846 ResetProperties( bufferIndex );
847 mImpl->transformManager.ResetToBaseValue();
850 // Process the queued scene messages. Note, MessageQueue::FlushQueue may be called
851 // between calling IsSceneUpdateRequired() above and here, so updateScene should
853 updateScene |= mImpl->messageQueue.ProcessMessages( bufferIndex );
855 //Forward compiled shader programs to event thread for saving
856 ForwardCompiledShadersToEventThread();
858 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
859 // renderer lists if the scene was updated in the previous frame.
860 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
861 if( updateScene || mImpl->previousUpdateScene )
864 Animate( bufferIndex, elapsedSeconds );
866 //Constraint custom objects
867 ConstrainCustomObjects( bufferIndex );
869 //Clear the lists of renderers from the previous update
870 for( size_t i(0); i<mImpl->sortedLayers.size(); ++i )
872 mImpl->sortedLayers[i]->ClearRenderables();
875 for( size_t i(0); i<mImpl->systemLevelSortedLayers.size(); ++i )
877 mImpl->systemLevelSortedLayers[i]->ClearRenderables();
880 //Update node hierarchy, apply constraints and perform sorting / culling.
881 //This will populate each Layer with a list of renderers which are ready.
882 UpdateNodes( bufferIndex );
884 //Apply constraints to RenderTasks, shaders
885 ConstrainRenderTasks( bufferIndex );
886 ConstrainShaders( bufferIndex );
888 //Update renderers and apply constraints
889 UpdateRenderers( bufferIndex );
891 //Update the trnasformations of all the nodes
892 mImpl->transformManager.Update();
894 //Process Property Notifications
895 ProcessPropertyNotifications( bufferIndex );
897 //Process the RenderTasks; this creates the instructions for rendering the next frame.
898 //reset the update buffer index and make sure there is enough room in the instruction container
899 mImpl->renderInstructions.ResetAndReserve( bufferIndex,
900 mImpl->taskList.GetTasks().Count() + mImpl->systemLevelTaskList.GetTasks().Count() );
902 if ( NULL != mImpl->root )
904 mImpl->renderTaskProcessor.Process( bufferIndex,
908 mImpl->renderInstructions );
910 // Process the system-level RenderTasks last
911 if ( NULL != mImpl->systemLevelRoot )
913 mImpl->renderTaskProcessor.Process( bufferIndex,
914 mImpl->systemLevelTaskList,
915 *mImpl->systemLevelRoot,
916 mImpl->systemLevelSortedLayers,
917 mImpl->renderInstructions );
922 // check the countdown and notify (note, at the moment this is only done for normal tasks, not for systemlevel tasks)
923 bool doRenderOnceNotify = false;
924 mImpl->renderTaskWaiting = false;
925 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
926 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(), endIter = tasks.End();
927 endIter != iter; ++iter )
929 RenderTask& renderTask(*(*iter));
931 renderTask.UpdateState();
933 if( renderTask.IsWaitingToRender() &&
934 renderTask.ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
936 mImpl->renderTaskWaiting = true; // keep update/render threads alive
939 if( renderTask.HasRendered() )
941 doRenderOnceNotify = true;
945 if( doRenderOnceNotify )
947 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
948 mImpl->notificationManager.QueueCompleteNotification( mImpl->taskList.GetCompleteNotificationInterface() );
951 // Macro is undefined in release build.
952 SNAPSHOT_NODE_LOGGING;
954 // A ResetProperties() may be required in the next frame
955 mImpl->previousUpdateScene = updateScene;
957 // Check whether further updates are required
958 unsigned int keepUpdating = KeepUpdatingCheck( elapsedSeconds );
960 // tell the update manager that we're done so the queue can be given to event thread
961 mImpl->notificationManager.UpdateCompleted();
963 // The update has finished; swap the double-buffering indices
964 mSceneGraphBuffers.Swap();
969 unsigned int UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
971 // Update the duration set via Stage::KeepRendering()
972 if ( mImpl->keepRenderingSeconds > 0.0f )
974 mImpl->keepRenderingSeconds -= elapsedSeconds;
977 unsigned int keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
979 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
980 // Keep updating until no messages are received and no animations are running.
981 // If an animation has just finished, update at least once more for Discard end-actions.
982 // No need to check for renderQueue as there is always a render after update and if that
983 // render needs another update it will tell the adaptor to call update again
985 if ( mImpl->keepRenderingSeconds > 0.0f )
987 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
990 if ( IsAnimationRunning() ||
991 mImpl->animationFinishedDuringUpdate )
993 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
996 if ( mImpl->renderTaskWaiting )
998 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
1001 return keepUpdatingRequest;
1004 void UpdateManager::SetBackgroundColor( const Vector4& color )
1006 typedef MessageValue1< RenderManager, Vector4 > DerivedType;
1008 // Reserve some memory inside the render queue
1009 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1011 // Construct message in the render queue memory; note that delete should not be called on the return value
1012 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
1015 void UpdateManager::SetDefaultSurfaceRect( const Rect<int>& rect )
1017 typedef MessageValue1< RenderManager, Rect<int> > DerivedType;
1019 // Reserve some memory inside the render queue
1020 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1022 // Construct message in the render queue memory; note that delete should not be called on the return value
1023 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1026 void UpdateManager::KeepRendering( float durationSeconds )
1028 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1031 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, bool systemLevel )
1035 // just copy the vector of pointers
1036 mImpl->sortedLayers = layers;
1040 mImpl->systemLevelSortedLayers = layers;
1044 void UpdateManager::SetDepthIndices( NodeDepths* nodeDepths )
1048 // note,this vector is already in depth order. It could be used as-is to
1049 // remove sorting in update algorithm. However, it lacks layer boundary markers.
1050 for( std::vector<NodeDepthPair>::iterator iter = nodeDepths->nodeDepths.begin(),
1051 end = nodeDepths->nodeDepths.end() ;
1052 iter != end ; ++iter )
1054 iter->node->SetDepthIndex( iter->sortedDepth );
1060 void UpdateManager::AddSampler( Render::Sampler* sampler )
1062 // Message has ownership of Sampler while in transit from update to render
1063 typedef MessageValue1< RenderManager, OwnerPointer< Render::Sampler > > DerivedType;
1065 // Reserve some memory inside the render queue
1066 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1068 // Construct message in the render queue memory; note that delete should not be called on the return value
1069 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddSampler, sampler );
1072 void UpdateManager::RemoveSampler( Render::Sampler* sampler )
1074 typedef MessageValue1< RenderManager, Render::Sampler* > DerivedType;
1076 // Reserve some memory inside the render queue
1077 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1079 // Construct message in the render queue memory; note that delete should not be called on the return value
1080 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveSampler, sampler );
1083 void UpdateManager::SetFilterMode( Render::Sampler* sampler, unsigned int minFilterMode, unsigned int magFilterMode )
1085 typedef MessageValue3< RenderManager, Render::Sampler*, unsigned int, unsigned int > DerivedType;
1087 // Reserve some memory inside the render queue
1088 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1090 // Construct message in the render queue memory; note that delete should not be called on the return value
1091 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetFilterMode, sampler, minFilterMode, magFilterMode );
1094 void UpdateManager::SetWrapMode( Render::Sampler* sampler, unsigned int rWrapMode, unsigned int sWrapMode, unsigned int tWrapMode )
1096 typedef MessageValue4< RenderManager, Render::Sampler*, unsigned int, unsigned int, unsigned int > DerivedType;
1098 // Reserve some memory inside the render queue
1099 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1101 // Construct message in the render queue memory; note that delete should not be called on the return value
1102 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetWrapMode, sampler, rWrapMode, sWrapMode, tWrapMode );
1105 void UpdateManager::AddPropertyBuffer( Render::PropertyBuffer* propertyBuffer )
1107 // Message has ownership of format while in transit from update -> render
1108 typedef MessageValue1< RenderManager, OwnerPointer< Render::PropertyBuffer > > DerivedType;
1110 // Reserve some memory inside the render queue
1111 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1113 // Construct message in the render queue memory; note that delete should not be called on the return value
1114 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddPropertyBuffer, propertyBuffer );
1117 void UpdateManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer )
1119 typedef MessageValue1< RenderManager, Render::PropertyBuffer* > DerivedType;
1121 // Reserve some memory inside the render queue
1122 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1124 // Construct message in the render queue memory; note that delete should not be called on the return value
1125 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemovePropertyBuffer, propertyBuffer );
1128 void UpdateManager::SetPropertyBufferFormat(Render::PropertyBuffer* propertyBuffer, Render::PropertyBuffer::Format* format )
1130 // Message has ownership of format while in transit from update -> render
1131 typedef MessageValue2< RenderManager, Render::PropertyBuffer*, OwnerPointer< Render::PropertyBuffer::Format > > DerivedType;
1133 // Reserve some memory inside the render queue
1134 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1136 // Construct message in the render queue memory; note that delete should not be called on the return value
1137 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferFormat, propertyBuffer, format );
1140 void UpdateManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffer, Dali::Vector<char>* data, size_t size )
1142 // Message has ownership of format while in transit from update -> render
1143 typedef MessageValue3< RenderManager, Render::PropertyBuffer*, OwnerPointer< Dali::Vector<char> >, size_t > 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::SetPropertyBufferData, propertyBuffer, data, size );
1152 void UpdateManager::AddGeometry( Render::Geometry* geometry )
1154 // Message has ownership of format while in transit from update -> render
1155 typedef MessageValue1< RenderManager, OwnerPointer< Render::Geometry > > DerivedType;
1157 // Reserve some memory inside the render queue
1158 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1160 // Construct message in the render queue memory; note that delete should not be called on the return value
1161 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddGeometry, geometry );
1164 void UpdateManager::RemoveGeometry( Render::Geometry* geometry )
1166 typedef MessageValue1< RenderManager, Render::Geometry* > DerivedType;
1168 // Reserve some memory inside the render queue
1169 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1171 // Construct message in the render queue memory; note that delete should not be called on the return value
1172 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveGeometry, geometry );
1175 void UpdateManager::SetGeometryType( Render::Geometry* geometry, unsigned int geometryType )
1177 typedef MessageValue2< RenderManager, Render::Geometry*, unsigned int > DerivedType;
1179 // Reserve some memory inside the render queue
1180 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1182 // Construct message in the render queue memory; note that delete should not be called on the return value
1183 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetGeometryType, geometry, geometryType );
1186 void UpdateManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector<unsigned short>& indices )
1188 typedef IndexBufferMessage< RenderManager > DerivedType;
1190 // Reserve some memory inside the render queue
1191 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1193 // Construct message in the render queue memory; note that delete should not be called on the return value
1194 new (slot) DerivedType( &mImpl->renderManager, geometry, indices );
1197 void UpdateManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1199 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1201 // Reserve some memory inside the render queue
1202 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1204 // Construct message in the render queue memory; note that delete should not be called on the return value
1205 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveVertexBuffer, geometry, propertyBuffer );
1208 void UpdateManager::AddVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1210 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1212 // Reserve some memory inside the render queue
1213 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1215 // Construct message in the render queue memory; note that delete should not be called on the return value
1216 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddVertexBuffer, geometry, propertyBuffer );
1219 void UpdateManager::AddTexture( Render::Texture* texture )
1221 // Message has ownership of Texture while in transit from update -> render
1222 typedef MessageValue1< RenderManager, OwnerPointer< Render::Texture > > DerivedType;
1224 // Reserve some memory inside the render queue
1225 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1227 // Construct message in the render queue memory; note that delete should not be called on the return value
1228 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddTexture, texture );
1231 void UpdateManager::RemoveTexture( Render::Texture* texture)
1233 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1235 // Reserve some memory inside the render queue
1236 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1238 // Construct message in the render queue memory; note that delete should not be called on the return value
1239 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveTexture, texture );
1242 void UpdateManager::UploadTexture( Render::Texture* texture, PixelDataPtr pixelData, const Texture::UploadParams& params )
1244 typedef MessageValue3< RenderManager, Render::Texture*, PixelDataPtr, Texture::UploadParams > DerivedType;
1246 // Reserve some memory inside the message queue
1247 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1249 // Construct message in the message queue memory; note that delete should not be called on the return value
1250 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::UploadTexture, texture, pixelData, params );
1253 void UpdateManager::GenerateMipmaps( Render::Texture* texture )
1255 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1257 // Reserve some memory inside the render queue
1258 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1260 // Construct message in the render queue memory; note that delete should not be called on the return value
1261 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::GenerateMipmaps, texture );
1264 void UpdateManager::AddFrameBuffer( Render::FrameBuffer* frameBuffer )
1266 typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType;
1268 // Reserve some memory inside the render queue
1269 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1271 // Construct message in the render queue memory; note that delete should not be called on the return value
1272 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddFrameBuffer, frameBuffer );
1275 void UpdateManager::RemoveFrameBuffer( Render::FrameBuffer* frameBuffer)
1277 typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType;
1279 // Reserve some memory inside the render queue
1280 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1282 // Construct message in the render queue memory; note that delete should not be called on the return value
1283 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveFrameBuffer, frameBuffer );
1286 void UpdateManager::AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, unsigned int mipmapLevel, unsigned int layer )
1288 typedef MessageValue4< RenderManager, Render::FrameBuffer*, Render::Texture*, unsigned int, unsigned int > DerivedType;
1290 // Reserve some memory inside the render queue
1291 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1293 // Construct message in the render queue memory; note that delete should not be called on the return value
1294 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AttachColorTextureToFrameBuffer, frameBuffer, texture, mipmapLevel, layer );
1297 } // namespace SceneGraph
1299 } // namespace Internal