2 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/update/manager/update-manager.h>
22 #include <dali/public-api/common/stage.h>
23 #include <dali/devel-api/common/set-wrapper.h>
24 #include <dali/devel-api/common/owner-container.h>
25 #include <dali/devel-api/threading/mutex.h>
27 #include <dali/integration-api/core.h>
28 #include <dali/integration-api/render-controller.h>
29 #include <dali/internal/common/shader-data.h>
30 #include <dali/integration-api/debug.h>
32 #include <dali/internal/common/core-impl.h>
33 #include <dali/internal/common/message.h>
35 #include <dali/internal/event/common/notification-manager.h>
36 #include <dali/internal/event/common/property-notification-impl.h>
37 #include <dali/internal/event/common/property-notifier.h>
38 #include <dali/internal/event/effects/shader-factory.h>
40 #include <dali/internal/update/animation/scene-graph-animator.h>
41 #include <dali/internal/update/animation/scene-graph-animation.h>
42 #include <dali/internal/update/common/discard-queue.h>
43 #include <dali/internal/update/common/scene-graph-buffers.h>
44 #include <dali/internal/update/controllers/render-message-dispatcher.h>
45 #include <dali/internal/update/controllers/scene-controller-impl.h>
46 #include <dali/internal/update/gestures/scene-graph-pan-gesture.h>
47 #include <dali/internal/update/manager/object-owner-container.h>
48 #include <dali/internal/update/manager/render-task-processor.h>
49 #include <dali/internal/update/manager/sorted-layers.h>
50 #include <dali/internal/update/manager/update-algorithms.h>
51 #include <dali/internal/update/manager/update-manager-debug.h>
52 #include <dali/internal/update/manager/transform-manager.h>
53 #include <dali/internal/update/nodes/node.h>
54 #include <dali/internal/update/nodes/scene-graph-layer.h>
55 #include <dali/internal/update/queue/update-message-queue.h>
56 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
57 #include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
58 #include <dali/internal/update/rendering/scene-graph-texture-set.h>
59 #include <dali/internal/update/render-tasks/scene-graph-camera.h>
61 #include <dali/internal/render/common/render-instruction-container.h>
62 #include <dali/internal/render/common/render-manager.h>
63 #include <dali/internal/render/queue/render-queue.h>
64 #include <dali/internal/render/shaders/scene-graph-shader.h>
66 // Un-comment to enable node tree debug logging
67 //#define NODE_TREE_LOGGING 1
69 #if ( defined( DEBUG_ENABLED ) && defined( NODE_TREE_LOGGING ) )
70 #define SNAPSHOT_NODE_LOGGING \
71 const int FRAME_COUNT_TRIGGER = 16;\
72 if( mImpl->frameCounter >= FRAME_COUNT_TRIGGER )\
74 if ( NULL != mImpl->root )\
76 mImpl->frameCounter = 0;\
77 PrintNodeTree( *mImpl->root, mSceneGraphBuffers.GetUpdateBufferIndex(), "" );\
80 mImpl->frameCounter++;
82 #define SNAPSHOT_NODE_LOGGING
85 #if defined(DEBUG_ENABLED)
86 extern Debug::Filter* gRenderTaskLogFilter;
90 using namespace Dali::Integration;
91 using Dali::Internal::Update::MessageQueue;
102 typedef OwnerContainer< Shader* > ShaderContainer;
103 typedef ShaderContainer::Iterator ShaderIter;
104 typedef ShaderContainer::ConstIterator ShaderConstIter;
106 typedef std::vector<Internal::ShaderDataPtr> ShaderDataBinaryQueue;
108 typedef OwnerContainer<PanGesture*> GestureContainer;
109 typedef GestureContainer::Iterator GestureIter;
110 typedef GestureContainer::ConstIterator GestureConstIter;
112 typedef OwnerContainer< TextureSet* > TextureSetContainer;
113 typedef TextureSetContainer::Iterator TextureSetIter;
114 typedef TextureSetContainer::ConstIterator TextureSetConstIter;
117 * Structure to contain UpdateManager internal data
119 struct UpdateManager::Impl
121 Impl( NotificationManager& notificationManager,
122 CompleteNotificationInterface& animationFinishedNotifier,
123 PropertyNotifier& propertyNotifier,
124 DiscardQueue& discardQueue,
125 RenderController& renderController,
126 RenderManager& renderManager,
127 RenderQueue& renderQueue,
128 SceneGraphBuffers& sceneGraphBuffers,
129 RenderTaskProcessor& renderTaskProcessor )
130 : renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ),
131 notificationManager( notificationManager ),
133 animationFinishedNotifier( animationFinishedNotifier ),
134 propertyNotifier( propertyNotifier ),
136 discardQueue( discardQueue ),
137 renderController( renderController ),
138 sceneController( NULL ),
139 renderManager( renderManager ),
140 renderQueue( renderQueue ),
141 renderInstructions( renderManager.GetRenderInstructionContainer() ),
142 renderTaskProcessor( renderTaskProcessor ),
143 backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
144 taskList( renderMessageDispatcher ),
145 systemLevelTaskList( renderMessageDispatcher ),
147 systemLevelRoot( NULL ),
148 renderers( sceneGraphBuffers, discardQueue ),
150 messageQueue( renderController, sceneGraphBuffers ),
151 keepRenderingSeconds( 0.0f ),
152 animationFinishedDuringUpdate( false ),
153 nodeDirtyFlags( TransformFlag ), // set to TransformFlag to ensure full update the first time through Update()
154 previousUpdateScene( false ),
156 renderTaskWaiting( false )
158 sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue );
160 renderers.SetSceneController( *sceneController );
162 // create first 'dummy' node
168 // Disconnect render tasks from nodes, before destroying the nodes
169 RenderTaskList::RenderTaskContainer& tasks = taskList.GetTasks();
170 for (RenderTaskList::RenderTaskContainer::Iterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
172 (*iter)->SetSourceNode( NULL );
174 // ..repeat for system level RenderTasks
175 RenderTaskList::RenderTaskContainer& systemLevelTasks = systemLevelTaskList.GetTasks();
176 for (RenderTaskList::RenderTaskContainer::Iterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
178 (*iter)->SetSourceNode( NULL );
181 // UpdateManager owns the Nodes
182 Vector<Node*>::Iterator iter = nodes.Begin()+1;
183 Vector<Node*>::Iterator endIter = nodes.End();
184 for(;iter!=endIter;++iter)
186 (*iter)->OnDestroy();
190 // If there is root, reset it, otherwise do nothing as rendering was never started
195 Node::Delete( root );
199 if( systemLevelRoot )
201 systemLevelRoot->OnDestroy();
203 Node::Delete( systemLevelRoot );
204 systemLevelRoot = NULL;
207 delete sceneController;
210 SceneGraphBuffers sceneGraphBuffers; ///< Used to keep track of which buffers are being written or read
211 RenderMessageDispatcher renderMessageDispatcher; ///< Used for passing messages to the render-thread
212 NotificationManager& notificationManager; ///< Queues notification messages for the event-thread.
213 TransformManager transformManager; ///< Used to update the transformation matrices of the nodes
214 CompleteNotificationInterface& animationFinishedNotifier; ///< Provides notification to applications when animations are finished.
215 PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
216 ShaderSaver* shaderSaver; ///< Saves shader binaries.
217 DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
218 RenderController& renderController; ///< render controller
219 SceneControllerImpl* sceneController; ///< scene controller
220 RenderManager& renderManager; ///< This is responsible for rendering the results of each "update"
221 RenderQueue& renderQueue; ///< Used to queue messages for the next render
222 RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions
223 RenderTaskProcessor& renderTaskProcessor; ///< Handles RenderTasks and RenderInstrucitons
225 Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
227 RenderTaskList taskList; ///< The list of scene graph render-tasks
228 RenderTaskList systemLevelTaskList; ///< Separate render-tasks for system-level content
230 Layer* root; ///< The root node (root is a layer)
231 Layer* systemLevelRoot; ///< A separate root-node for system-level content
233 Vector<Node*> nodes; ///< A container of all instantiated nodes
235 SortedLayerPointers sortedLayers; ///< A container of Layer pointers sorted by depth
236 SortedLayerPointers systemLevelSortedLayers; ///< A separate container of system-level Layers
238 OwnerContainer< Camera* > cameras; ///< A container of cameras
239 OwnerContainer< PropertyOwner* > customObjects; ///< A container of owned objects (with custom properties)
241 AnimationContainer animations; ///< A container of owned animations
242 PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
244 ObjectOwnerContainer<Renderer> renderers;
245 TextureSetContainer textureSets; ///< A container of texture sets
247 ShaderContainer shaders; ///< A container of owned shaders
249 MessageQueue messageQueue; ///< The messages queued from the event-thread
250 ShaderDataBinaryQueue renderCompiledShaders; ///< Shaders compiled on Render thread are inserted here for update thread to pass on to event thread.
251 ShaderDataBinaryQueue updateCompiledShaders; ///< Shaders to be sent from Update to Event
252 Mutex compiledShaderMutex; ///< lock to ensure no corruption on the renderCompiledShaders
254 float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
255 bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
257 int nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
258 bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
260 int frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
262 GestureContainer gestures; ///< A container of owned gesture detectors
263 bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
267 Impl( const Impl& ); ///< Undefined
268 Impl& operator=( const Impl& ); ///< Undefined
271 UpdateManager::UpdateManager( NotificationManager& notificationManager,
272 CompleteNotificationInterface& animationFinishedNotifier,
273 PropertyNotifier& propertyNotifier,
274 DiscardQueue& discardQueue,
275 RenderController& controller,
276 RenderManager& renderManager,
277 RenderQueue& renderQueue,
278 RenderTaskProcessor& renderTaskProcessor )
281 mImpl = new Impl( notificationManager,
282 animationFinishedNotifier,
289 renderTaskProcessor );
293 UpdateManager::~UpdateManager()
298 void UpdateManager::InstallRoot( SceneGraph::Layer* layer, bool systemLevel )
300 DALI_ASSERT_DEBUG( layer->IsLayer() );
301 DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
305 DALI_ASSERT_DEBUG( mImpl->root == NULL && "Root Node already installed" );
307 mImpl->root->CreateTransform( &mImpl->transformManager );
311 DALI_ASSERT_DEBUG( mImpl->systemLevelRoot == NULL && "System-level Root Node already installed" );
312 mImpl->systemLevelRoot = layer;
313 mImpl->systemLevelRoot->CreateTransform( &mImpl->transformManager );
316 layer->SetRoot(true);
319 void UpdateManager::AddNode( Node* node )
321 DALI_ASSERT_ALWAYS( NULL != node );
322 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
324 // Nodes must be sorted by pointer
325 Vector<Node*>::Iterator begin = mImpl->nodes.Begin();
326 for(Vector<Node*>::Iterator iter = mImpl->nodes.End()-1; iter >= begin; --iter)
330 mImpl->nodes.Insert((iter+1), node);
331 node->CreateTransform( &mImpl->transformManager );
337 void UpdateManager::ConnectNode( Node* parent, Node* node )
339 DALI_ASSERT_ALWAYS( NULL != parent );
340 DALI_ASSERT_ALWAYS( NULL != node );
341 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
343 parent->ConnectChild( node );
346 void UpdateManager::DisconnectNode( Node* node )
348 Node* parent = node->GetParent();
349 DALI_ASSERT_ALWAYS( NULL != parent );
350 parent->SetDirtyFlag( ChildDeletedFlag ); // make parent dirty so that render items dont get reused
352 parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node );
355 void UpdateManager::DestroyNode( Node* node )
357 DALI_ASSERT_ALWAYS( NULL != node );
358 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
360 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
361 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
362 for(;iter!=endIter;++iter)
366 mImpl->nodes.Erase(iter);
371 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
373 // Notify the Node about impending destruction
377 void UpdateManager::AddCamera( Camera* camera )
379 DALI_ASSERT_DEBUG( camera != NULL );
381 mImpl->cameras.PushBack( camera ); // takes ownership
384 void UpdateManager::RemoveCamera( const Camera* camera )
387 OwnerContainer<Camera*>::Iterator iter = mImpl->cameras.Begin();
388 OwnerContainer<Camera*>::ConstIterator end = mImpl->cameras.End();
389 for ( ; iter != end; ++iter )
391 Camera* value = *iter;
392 if ( camera == value )
394 // Transfer ownership to the discard queue
395 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->cameras.Release( iter ) );
403 void UpdateManager::AddObject( PropertyOwner* object )
405 DALI_ASSERT_DEBUG( NULL != object );
407 mImpl->customObjects.PushBack( object );
410 void UpdateManager::RemoveObject( PropertyOwner* object )
412 DALI_ASSERT_DEBUG( NULL != object );
414 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
416 // Find the object and destroy it
417 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); iter != customObjects.End(); ++iter )
419 PropertyOwner* current = *iter;
420 if ( current == object )
422 customObjects.Erase( iter );
427 // Should not reach here
428 DALI_ASSERT_DEBUG(false);
431 void UpdateManager::AddAnimation( Animation* animation )
433 mImpl->animations.PushBack( animation );
436 void UpdateManager::StopAnimation( Animation* animation )
438 DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
440 bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
442 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
445 void UpdateManager::RemoveAnimation( Animation* animation )
447 DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
449 animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
451 DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
454 bool UpdateManager::IsAnimationRunning() const
456 bool isRunning(false);
457 AnimationContainer& animations = mImpl->animations;
459 // Find any animation that isn't stopped or paused
461 const AnimationIter endIter = animations.End();
462 for ( AnimationIter iter = animations.Begin(); !isRunning && iter != endIter; ++iter )
464 const Animation::State state = (*iter)->GetState();
466 if (state != Animation::Stopped &&
467 state != Animation::Paused)
476 void UpdateManager::AddPropertyNotification( PropertyNotification* propertyNotification )
478 mImpl->propertyNotifications.PushBack( propertyNotification );
481 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
483 PropertyNotificationContainer &propertyNotifications = mImpl->propertyNotifications;
484 PropertyNotificationIter iter = propertyNotifications.Begin();
486 while ( iter != propertyNotifications.End() )
488 if( *iter == propertyNotification )
490 propertyNotifications.Erase(iter);
497 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
499 DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
500 propertyNotification->SetNotifyMode( notifyMode );
503 ObjectOwnerContainer<Renderer>& UpdateManager::GetRendererOwner()
505 return mImpl->renderers;
508 void UpdateManager::AddShader( Shader* shader )
510 DALI_ASSERT_DEBUG( NULL != shader );
512 if( mImpl->shaders.Count() == 0 )
514 // the first added shader becomes our default shader
515 // Construct message in the render queue memory; note that delete should not be called on the return value
516 typedef MessageValue1< RenderManager, Shader* > DerivedType;
518 // Reserve some memory inside the render queue
519 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
521 // Construct message in the render queue memory; note that delete should not be called on the return value
522 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultShader, shader );
525 mImpl->shaders.PushBack( shader );
528 void UpdateManager::RemoveShader( Shader* shader )
530 DALI_ASSERT_DEBUG(shader != NULL);
532 ShaderContainer& shaders = mImpl->shaders;
534 // Find the shader and destroy it
535 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
537 Shader& current = **iter;
538 if ( ¤t == shader )
540 // Transfer ownership to the discard queue
541 // This keeps the shader alive, until the render-thread has finished with it
542 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), shaders.Release( iter ) );
547 // Should not reach here
548 DALI_ASSERT_DEBUG(false);
551 void UpdateManager::SetShaderProgram( Shader* shader,
552 Internal::ShaderDataPtr shaderData, bool modifiesGeometry )
557 typedef MessageValue3< Shader, Internal::ShaderDataPtr, ProgramCache*, bool> DerivedType;
559 // Reserve some memory inside the render queue
560 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
562 // Construct message in the render queue memory; note that delete should not be called on the return value
563 new (slot) DerivedType( shader, &Shader::SetProgram, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
567 void UpdateManager::SaveBinary( Internal::ShaderDataPtr shaderData )
569 DALI_ASSERT_DEBUG( shaderData && "No NULL shader data pointers please." );
570 DALI_ASSERT_DEBUG( shaderData->GetBufferSize() > 0 && "Shader binary empty so nothing to save." );
572 // lock as update might be sending previously compiled shaders to event thread
573 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
574 mImpl->renderCompiledShaders.push_back( shaderData );
578 RenderTaskList* UpdateManager::GetRenderTaskList( bool systemLevel )
582 // copy the list, this is only likely to happen once in application life cycle
583 return &(mImpl->taskList);
587 // copy the list, this is only likely to happen once in application life cycle
588 return &(mImpl->systemLevelTaskList);
592 void UpdateManager::AddGesture( PanGesture* gesture )
594 DALI_ASSERT_DEBUG( NULL != gesture );
596 mImpl->gestures.PushBack( gesture );
599 void UpdateManager::RemoveGesture( PanGesture* gesture )
601 DALI_ASSERT_DEBUG( gesture != NULL );
603 GestureContainer& gestures = mImpl->gestures;
605 // Find the gesture and destroy it
606 for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
608 PanGesture& current = **iter;
609 if ( ¤t == gesture )
611 mImpl->gestures.Erase( iter );
615 // Should not reach here
616 DALI_ASSERT_DEBUG(false);
619 void UpdateManager::AddTextureSet( TextureSet* textureSet )
621 DALI_ASSERT_DEBUG( NULL != textureSet );
622 mImpl->textureSets.PushBack( textureSet );
625 void UpdateManager::RemoveTextureSet( TextureSet* textureSet )
627 DALI_ASSERT_DEBUG(textureSet != NULL);
628 size_t textureSetCount( mImpl->textureSets.Size() );
629 for( size_t i(0); i<textureSetCount; ++i )
631 if( textureSet == mImpl->textureSets[i] )
633 mImpl->textureSets.Remove( mImpl->textureSets.Begin() + i );
635 // Update manager has ownership of the TextureSet
642 unsigned int* UpdateManager::ReserveMessageSlot( std::size_t size, bool updateScene )
644 return mImpl->messageQueue.ReserveMessageSlot( size, updateScene );
647 void UpdateManager::EventProcessingStarted()
649 mImpl->messageQueue.EventProcessingStarted();
652 bool UpdateManager::FlushQueue()
654 return mImpl->messageQueue.FlushQueue();
657 void UpdateManager::ResetProperties( BufferIndex bufferIndex )
659 // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
660 mImpl->animationFinishedDuringUpdate = false;
662 // Animated properties have to be reset to their original value each frame
664 // Reset root properties
667 mImpl->root->ResetToBaseValues( bufferIndex );
669 if ( mImpl->systemLevelRoot )
671 mImpl->systemLevelRoot->ResetToBaseValues( bufferIndex );
674 // Reset all the nodes
675 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
676 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
677 for(;iter != endIter; ++iter)
679 (*iter)->ResetToBaseValues( bufferIndex );
682 // Reset system-level render-task list properties to base values
683 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
685 for (RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
687 (*iter)->ResetToBaseValues( bufferIndex );
690 // Reset render-task list properties to base values.
691 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
693 for (RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
695 (*iter)->ResetToBaseValues( bufferIndex );
698 // Reset custom object properties to base values
699 for (OwnerContainer<PropertyOwner*>::Iterator iter = mImpl->customObjects.Begin(); iter != mImpl->customObjects.End(); ++iter)
701 (*iter)->ResetToBaseValues( bufferIndex );
704 mImpl->renderers.ResetToBaseValues( bufferIndex );
706 // Reset animatable shader properties to base values
707 for (ShaderIter iter = mImpl->shaders.Begin(); iter != mImpl->shaders.End(); ++iter)
709 (*iter)->ResetToBaseValues( bufferIndex );
713 bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds )
715 bool gestureUpdated( false );
717 // constrain gestures... (in construction order)
718 GestureContainer& gestures = mImpl->gestures;
720 for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
722 PanGesture& gesture = **iter;
723 gesture.ResetToBaseValues( bufferIndex ); // Needs to be done every time as gesture data is written directly to an update-buffer rather than via a message
724 gestureUpdated |= gesture.UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
727 return gestureUpdated;
730 void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
732 AnimationContainer &animations = mImpl->animations;
733 AnimationIter iter = animations.Begin();
734 bool animationLooped = false;
735 while ( iter != animations.End() )
737 Animation* animation = *iter;
738 bool finished = false;
740 animation->Update( bufferIndex, elapsedSeconds, looped, finished );
742 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
743 animationLooped = animationLooped || looped;
745 // Remove animations that had been destroyed but were still waiting for an update
746 if (animation->GetState() == Animation::Destroyed)
748 iter = animations.Erase(iter);
756 // queue the notification on finished or looped (to update loop count)
757 if ( mImpl->animationFinishedDuringUpdate || animationLooped )
759 // The application should be notified by NotificationManager, in another thread
760 mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationFinishedNotifier );
764 void UpdateManager::ConstrainCustomObjects( BufferIndex bufferIndex )
766 //Constrain custom objects (in construction order)
767 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
768 const OwnerContainer< PropertyOwner* >::Iterator endIter = customObjects.End();
769 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); endIter != iter; ++iter )
771 PropertyOwner& object = **iter;
772 ConstrainPropertyOwner( object, bufferIndex );
776 void UpdateManager::ConstrainRenderTasks( BufferIndex bufferIndex )
778 // Constrain system-level render-tasks
779 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
780 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter )
782 RenderTask& task = **iter;
783 ConstrainPropertyOwner( task, bufferIndex );
786 // Constrain render-tasks
787 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
788 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter )
790 RenderTask& task = **iter;
791 ConstrainPropertyOwner( task, bufferIndex );
795 void UpdateManager::ConstrainShaders( BufferIndex bufferIndex )
797 // constrain shaders... (in construction order)
798 ShaderContainer& shaders = mImpl->shaders;
799 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
801 Shader& shader = **iter;
802 ConstrainPropertyOwner( shader, bufferIndex );
806 void UpdateManager::ProcessPropertyNotifications( BufferIndex bufferIndex )
808 PropertyNotificationContainer ¬ifications = mImpl->propertyNotifications;
809 PropertyNotificationIter iter = notifications.Begin();
811 while ( iter != notifications.End() )
813 PropertyNotification* notification = *iter;
814 bool valid = notification->Check( bufferIndex );
817 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
823 void UpdateManager::ForwardCompiledShadersToEventThread()
825 DALI_ASSERT_DEBUG( (mImpl->shaderSaver != 0) && "shaderSaver should be wired-up during startup." );
826 if( mImpl->shaderSaver )
828 // lock and swap the queues
830 // render might be attempting to send us more binaries at the same time
831 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
832 mImpl->renderCompiledShaders.swap( mImpl->updateCompiledShaders );
835 if( mImpl->updateCompiledShaders.size() > 0 )
837 ShaderSaver& factory = *mImpl->shaderSaver;
838 ShaderDataBinaryQueue::iterator i = mImpl->updateCompiledShaders.begin();
839 ShaderDataBinaryQueue::iterator end = mImpl->updateCompiledShaders.end();
840 for( ; i != end; ++i )
842 mImpl->notificationManager.QueueMessage( ShaderCompiledMessage( factory, *i ) );
844 // we don't need them in update anymore
845 mImpl->updateCompiledShaders.clear();
850 void UpdateManager::UpdateRenderers( BufferIndex bufferIndex )
852 const OwnerContainer<Renderer*>& rendererContainer( mImpl->renderers.GetObjectContainer() );
853 unsigned int rendererCount( rendererContainer.Size() );
854 for( unsigned int i(0); i<rendererCount; ++i )
857 ConstrainPropertyOwner( *rendererContainer[i], bufferIndex );
859 rendererContainer[i]->PrepareRender( bufferIndex );
863 void UpdateManager::UpdateNodes( BufferIndex bufferIndex )
865 mImpl->nodeDirtyFlags = NothingFlag;
872 // Prepare resources, update shaders, for each node
873 // And add the renderers to the sorted layers. Start from root, which is also a layer
874 mImpl->nodeDirtyFlags = UpdateNodeTree( *( mImpl->root ),
876 mImpl->renderQueue );
878 if ( mImpl->systemLevelRoot )
880 mImpl->nodeDirtyFlags |= UpdateNodeTree( *( mImpl->systemLevelRoot ),
882 mImpl->renderQueue );
886 unsigned int UpdateManager::Update( float elapsedSeconds,
887 unsigned int lastVSyncTimeMilliseconds,
888 unsigned int nextVSyncTimeMilliseconds )
890 const BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
892 //Clear nodes/resources which were previously discarded
893 mImpl->discardQueue.Clear( bufferIndex );
895 //Process Touches & Gestures
896 const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
898 bool updateScene = // The scene-graph requires an update if..
899 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
900 IsAnimationRunning() || // ..at least one animation is running OR
901 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
902 gestureUpdated; // ..a gesture property was updated
905 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
906 // values if the scene was updated in the previous frame.
907 if( updateScene || mImpl->previousUpdateScene )
909 //Reset properties from the previous update
910 ResetProperties( bufferIndex );
911 mImpl->transformManager.ResetToBaseValue();
914 // Process the queued scene messages. Note, MessageQueue::FlushQueue may be called
915 // between calling IsSceneUpdateRequired() above and here, so updateScene should
917 updateScene |= mImpl->messageQueue.ProcessMessages( bufferIndex );
919 //Forward compiled shader programs to event thread for saving
920 ForwardCompiledShadersToEventThread();
922 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
923 // renderer lists if the scene was updated in the previous frame.
924 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
925 if( updateScene || mImpl->previousUpdateScene )
928 Animate( bufferIndex, elapsedSeconds );
930 //Constraint custom objects
931 ConstrainCustomObjects( bufferIndex );
933 //Clear the lists of renderers from the previous update
934 for( size_t i(0); i<mImpl->sortedLayers.size(); ++i )
936 mImpl->sortedLayers[i]->ClearRenderables();
939 for( size_t i(0); i<mImpl->systemLevelSortedLayers.size(); ++i )
941 mImpl->systemLevelSortedLayers[i]->ClearRenderables();
944 //Update node hierarchy, apply constraints and perform sorting / culling.
945 //This will populate each Layer with a list of renderers which are ready.
946 UpdateNodes( bufferIndex );
948 //Apply constraints to RenderTasks, shaders
949 ConstrainRenderTasks( bufferIndex );
950 ConstrainShaders( bufferIndex );
952 //Update renderers and apply constraints
953 UpdateRenderers( bufferIndex );
955 //Update the trnasformations of all the nodes
956 mImpl->transformManager.Update();
958 //Process Property Notifications
959 ProcessPropertyNotifications( bufferIndex );
961 //Process the RenderTasks; this creates the instructions for rendering the next frame.
962 //reset the update buffer index and make sure there is enough room in the instruction container
963 mImpl->renderInstructions.ResetAndReserve( bufferIndex,
964 mImpl->taskList.GetTasks().Count() + mImpl->systemLevelTaskList.GetTasks().Count() );
966 if ( NULL != mImpl->root )
968 mImpl->renderTaskProcessor.Process( bufferIndex,
972 mImpl->renderInstructions );
974 // Process the system-level RenderTasks last
975 if ( NULL != mImpl->systemLevelRoot )
977 mImpl->renderTaskProcessor.Process( bufferIndex,
978 mImpl->systemLevelTaskList,
979 *mImpl->systemLevelRoot,
980 mImpl->systemLevelSortedLayers,
981 mImpl->renderInstructions );
986 // check the countdown and notify (note, at the moment this is only done for normal tasks, not for systemlevel tasks)
987 bool doRenderOnceNotify = false;
988 mImpl->renderTaskWaiting = false;
989 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
990 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(), endIter = tasks.End();
991 endIter != iter; ++iter )
993 RenderTask& renderTask(*(*iter));
995 renderTask.UpdateState();
997 if( renderTask.IsWaitingToRender() &&
998 renderTask.ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
1000 mImpl->renderTaskWaiting = true; // keep update/render threads alive
1003 if( renderTask.HasRendered() )
1005 doRenderOnceNotify = true;
1009 if( doRenderOnceNotify )
1011 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
1012 mImpl->notificationManager.QueueCompleteNotification( mImpl->taskList.GetCompleteNotificationInterface() );
1015 // Macro is undefined in release build.
1016 SNAPSHOT_NODE_LOGGING;
1018 // A ResetProperties() may be required in the next frame
1019 mImpl->previousUpdateScene = updateScene;
1021 // Check whether further updates are required
1022 unsigned int keepUpdating = KeepUpdatingCheck( elapsedSeconds );
1024 // tell the update manager that we're done so the queue can be given to event thread
1025 mImpl->notificationManager.UpdateCompleted();
1027 // The update has finished; swap the double-buffering indices
1028 mSceneGraphBuffers.Swap();
1030 return keepUpdating;
1033 unsigned int UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
1035 // Update the duration set via Stage::KeepRendering()
1036 if ( mImpl->keepRenderingSeconds > 0.0f )
1038 mImpl->keepRenderingSeconds -= elapsedSeconds;
1041 unsigned int keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
1043 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
1044 // Keep updating until no messages are received and no animations are running.
1045 // If an animation has just finished, update at least once more for Discard end-actions.
1046 // No need to check for renderQueue as there is always a render after update and if that
1047 // render needs another update it will tell the adaptor to call update again
1049 if ( mImpl->keepRenderingSeconds > 0.0f )
1051 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
1054 if ( IsAnimationRunning() ||
1055 mImpl->animationFinishedDuringUpdate )
1057 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
1060 if ( mImpl->renderTaskWaiting )
1062 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
1065 return keepUpdatingRequest;
1068 void UpdateManager::SetBackgroundColor( const Vector4& color )
1070 typedef MessageValue1< RenderManager, Vector4 > DerivedType;
1072 // Reserve some memory inside the render queue
1073 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1075 // Construct message in the render queue memory; note that delete should not be called on the return value
1076 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
1079 void UpdateManager::SetDefaultSurfaceRect( const Rect<int>& rect )
1081 typedef MessageValue1< RenderManager, Rect<int> > DerivedType;
1083 // Reserve some memory inside the render queue
1084 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1086 // Construct message in the render queue memory; note that delete should not be called on the return value
1087 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1090 void UpdateManager::KeepRendering( float durationSeconds )
1092 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1095 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, bool systemLevel )
1099 // just copy the vector of pointers
1100 mImpl->sortedLayers = layers;
1104 mImpl->systemLevelSortedLayers = layers;
1108 void UpdateManager::SetShaderSaver( ShaderSaver& upstream )
1110 mImpl->shaderSaver = &upstream;
1113 void UpdateManager::AddSampler( Render::Sampler* sampler )
1115 // Message has ownership of Sampler while in transit from update to render
1116 typedef MessageValue1< RenderManager, OwnerPointer< Render::Sampler > > DerivedType;
1118 // Reserve some memory inside the render queue
1119 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1121 // Construct message in the render queue memory; note that delete should not be called on the return value
1122 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddSampler, sampler );
1125 void UpdateManager::RemoveSampler( Render::Sampler* sampler )
1127 typedef MessageValue1< RenderManager, Render::Sampler* > DerivedType;
1129 // Reserve some memory inside the render queue
1130 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1132 // Construct message in the render queue memory; note that delete should not be called on the return value
1133 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveSampler, sampler );
1136 void UpdateManager::SetFilterMode( Render::Sampler* sampler, unsigned int minFilterMode, unsigned int magFilterMode )
1138 typedef MessageValue3< RenderManager, Render::Sampler*, unsigned int, unsigned int > DerivedType;
1140 // Reserve some memory inside the render queue
1141 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1143 // Construct message in the render queue memory; note that delete should not be called on the return value
1144 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetFilterMode, sampler, minFilterMode, magFilterMode );
1147 void UpdateManager::SetWrapMode( Render::Sampler* sampler, unsigned int rWrapMode, unsigned int sWrapMode, unsigned int tWrapMode )
1149 typedef MessageValue4< RenderManager, Render::Sampler*, unsigned int, unsigned int, unsigned int > DerivedType;
1151 // Reserve some memory inside the render queue
1152 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1154 // Construct message in the render queue memory; note that delete should not be called on the return value
1155 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetWrapMode, sampler, rWrapMode, sWrapMode, tWrapMode );
1158 void UpdateManager::AddPropertyBuffer( Render::PropertyBuffer* propertyBuffer )
1160 // Message has ownership of format while in transit from update -> render
1161 typedef MessageValue1< RenderManager, OwnerPointer< Render::PropertyBuffer > > DerivedType;
1163 // Reserve some memory inside the render queue
1164 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1166 // Construct message in the render queue memory; note that delete should not be called on the return value
1167 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddPropertyBuffer, propertyBuffer );
1170 void UpdateManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer )
1172 typedef MessageValue1< RenderManager, Render::PropertyBuffer* > DerivedType;
1174 // Reserve some memory inside the render queue
1175 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1177 // Construct message in the render queue memory; note that delete should not be called on the return value
1178 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemovePropertyBuffer, propertyBuffer );
1181 void UpdateManager::SetPropertyBufferFormat(Render::PropertyBuffer* propertyBuffer, Render::PropertyBuffer::Format* format )
1183 // Message has ownership of format while in transit from update -> render
1184 typedef MessageValue2< RenderManager, Render::PropertyBuffer*, OwnerPointer< Render::PropertyBuffer::Format > > DerivedType;
1186 // Reserve some memory inside the render queue
1187 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1189 // Construct message in the render queue memory; note that delete should not be called on the return value
1190 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferFormat, propertyBuffer, format );
1193 void UpdateManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffer, Dali::Vector<char>* data, size_t size )
1195 // Message has ownership of format while in transit from update -> render
1196 typedef MessageValue3< RenderManager, Render::PropertyBuffer*, OwnerPointer< Dali::Vector<char> >, size_t > DerivedType;
1198 // Reserve some memory inside the render queue
1199 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1201 // Construct message in the render queue memory; note that delete should not be called on the return value
1202 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferData, propertyBuffer, data, size );
1205 void UpdateManager::AddGeometry( Render::Geometry* geometry )
1207 // Message has ownership of format while in transit from update -> render
1208 typedef MessageValue1< RenderManager, OwnerPointer< Render::Geometry > > DerivedType;
1210 // Reserve some memory inside the render queue
1211 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1213 // Construct message in the render queue memory; note that delete should not be called on the return value
1214 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddGeometry, geometry );
1217 void UpdateManager::RemoveGeometry( Render::Geometry* geometry )
1219 typedef MessageValue1< RenderManager, Render::Geometry* > DerivedType;
1221 // Reserve some memory inside the render queue
1222 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1224 // Construct message in the render queue memory; note that delete should not be called on the return value
1225 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveGeometry, geometry );
1228 void UpdateManager::SetGeometryType( Render::Geometry* geometry, unsigned int geometryType )
1230 typedef MessageValue2< RenderManager, Render::Geometry*, unsigned int > DerivedType;
1232 // Reserve some memory inside the render queue
1233 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1235 // Construct message in the render queue memory; note that delete should not be called on the return value
1236 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetGeometryType, geometry, geometryType );
1239 void UpdateManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector<unsigned short>& indices )
1241 typedef IndexBufferMessage< RenderManager > DerivedType;
1243 // Reserve some memory inside the render queue
1244 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1246 // Construct message in the render queue memory; note that delete should not be called on the return value
1247 new (slot) DerivedType( &mImpl->renderManager, geometry, indices );
1250 void UpdateManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1252 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1254 // Reserve some memory inside the render queue
1255 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1257 // Construct message in the render queue memory; note that delete should not be called on the return value
1258 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveVertexBuffer, geometry, propertyBuffer );
1261 void UpdateManager::AddVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1263 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1265 // Reserve some memory inside the render queue
1266 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1268 // Construct message in the render queue memory; note that delete should not be called on the return value
1269 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddVertexBuffer, geometry, propertyBuffer );
1272 void UpdateManager::AddTexture( Render::Texture* texture )
1274 // Message has ownership of Texture while in transit from update -> render
1275 typedef MessageValue1< RenderManager, OwnerPointer< Render::Texture > > DerivedType;
1277 // Reserve some memory inside the render queue
1278 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1280 // Construct message in the render queue memory; note that delete should not be called on the return value
1281 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddTexture, texture );
1284 void UpdateManager::RemoveTexture( Render::Texture* texture)
1286 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1288 // Reserve some memory inside the render queue
1289 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1291 // Construct message in the render queue memory; note that delete should not be called on the return value
1292 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveTexture, texture );
1295 void UpdateManager::UploadTexture( Render::Texture* texture, PixelDataPtr pixelData, const Texture::UploadParams& params )
1297 typedef MessageValue3< RenderManager, Render::Texture*, PixelDataPtr, Texture::UploadParams > DerivedType;
1299 // Reserve some memory inside the message queue
1300 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1302 // Construct message in the message queue memory; note that delete should not be called on the return value
1303 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::UploadTexture, texture, pixelData, params );
1306 void UpdateManager::GenerateMipmaps( Render::Texture* texture )
1308 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1310 // Reserve some memory inside the render queue
1311 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1313 // Construct message in the render queue memory; note that delete should not be called on the return value
1314 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::GenerateMipmaps, texture );
1317 void UpdateManager::AddFrameBuffer( Render::FrameBuffer* frameBuffer )
1319 typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType;
1321 // Reserve some memory inside the render queue
1322 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1324 // Construct message in the render queue memory; note that delete should not be called on the return value
1325 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddFrameBuffer, frameBuffer );
1328 void UpdateManager::RemoveFrameBuffer( Render::FrameBuffer* frameBuffer)
1330 typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType;
1332 // Reserve some memory inside the render queue
1333 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1335 // Construct message in the render queue memory; note that delete should not be called on the return value
1336 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveFrameBuffer, frameBuffer );
1339 void UpdateManager::AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, unsigned int mipmapLevel, unsigned int layer )
1341 typedef MessageValue4< RenderManager, Render::FrameBuffer*, Render::Texture*, unsigned int, unsigned int > DerivedType;
1343 // Reserve some memory inside the render queue
1344 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1346 // Construct message in the render queue memory; note that delete should not be called on the return value
1347 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AttachColorTextureToFrameBuffer, frameBuffer, texture, mipmapLevel, layer );
1350 } // namespace SceneGraph
1352 } // namespace Internal