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. Although Nodes are pool allocated they contain heap allocated parts
224 // like custom properties, which get released here
225 Vector<Node*>::Iterator iter = nodes.Begin()+1;
226 Vector<Node*>::Iterator endIter = nodes.End();
227 for(;iter!=endIter;++iter)
229 (*iter)->OnDestroy();
233 // If there is root, reset it, otherwise do nothing as rendering was never started
238 Node::Delete( root );
242 if( systemLevelRoot )
244 systemLevelRoot->OnDestroy();
246 Node::Delete( systemLevelRoot );
247 systemLevelRoot = NULL;
250 delete sceneController;
253 SceneGraphBuffers sceneGraphBuffers; ///< Used to keep track of which buffers are being written or read
254 RenderMessageDispatcher renderMessageDispatcher; ///< Used for passing messages to the render-thread
255 NotificationManager& notificationManager; ///< Queues notification messages for the event-thread.
256 TransformManager transformManager; ///< Used to update the transformation matrices of the nodes
257 CompleteNotificationInterface& animationFinishedNotifier; ///< Provides notification to applications when animations are finished.
258 PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
259 ShaderSaver* shaderSaver; ///< Saves shader binaries.
260 DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
261 RenderController& renderController; ///< render controller
262 SceneControllerImpl* sceneController; ///< scene controller
263 RenderManager& renderManager; ///< This is responsible for rendering the results of each "update"
264 RenderQueue& renderQueue; ///< Used to queue messages for the next render
265 RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions
266 RenderTaskProcessor& renderTaskProcessor; ///< Handles RenderTasks and RenderInstrucitons
268 Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
270 RenderTaskList taskList; ///< The list of scene graph render-tasks
271 RenderTaskList systemLevelTaskList; ///< Separate render-tasks for system-level content
273 Layer* root; ///< The root node (root is a layer)
274 Layer* systemLevelRoot; ///< A separate root-node for system-level content
276 Vector<Node*> nodes; ///< A container of all instantiated nodes
278 SortedLayerPointers sortedLayers; ///< A container of Layer pointers sorted by depth
279 SortedLayerPointers systemLevelSortedLayers; ///< A separate container of system-level Layers
281 CameraOwner cameras; ///< A container of cameras
282 CustomObjectOwner customObjects; ///< A container of owned objects (with custom properties)
284 AnimationContainer animations; ///< A container of owned animations
285 PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
287 RendererOwner renderers; ///< A container of owned renderers
288 TextureSetOwner textureSets; ///< A container of owned texture sets
289 ShaderOwner shaders; ///< A container of owned shaders
290 OwnerPointer<PanGesture> panGestureProcessor; ///< Owned pan gesture processor; it lives for the lifecycle of UpdateManager
292 MessageQueue messageQueue; ///< The messages queued from the event-thread
293 ShaderDataBinaryQueue renderCompiledShaders; ///< Shaders compiled on Render thread are inserted here for update thread to pass on to event thread.
294 ShaderDataBinaryQueue updateCompiledShaders; ///< Shaders to be sent from Update to Event
295 Mutex compiledShaderMutex; ///< lock to ensure no corruption on the renderCompiledShaders
297 float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
298 int nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
299 int frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
301 bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
302 bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
303 bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
307 Impl( const Impl& ); ///< Undefined
308 Impl& operator=( const Impl& ); ///< Undefined
311 UpdateManager::UpdateManager( NotificationManager& notificationManager,
312 CompleteNotificationInterface& animationFinishedNotifier,
313 PropertyNotifier& propertyNotifier,
314 DiscardQueue& discardQueue,
315 RenderController& controller,
316 RenderManager& renderManager,
317 RenderQueue& renderQueue,
318 RenderTaskProcessor& renderTaskProcessor )
321 mImpl = new Impl( notificationManager,
322 animationFinishedNotifier,
329 renderTaskProcessor );
333 UpdateManager::~UpdateManager()
338 void UpdateManager::InstallRoot( OwnerPointer<Layer>& layer, bool systemLevel )
340 DALI_ASSERT_DEBUG( layer->IsLayer() );
341 DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
345 DALI_ASSERT_DEBUG( mImpl->root == NULL && "Root Node already installed" );
346 mImpl->root = layer.Release();
347 mImpl->root->CreateTransform( &mImpl->transformManager );
348 mImpl->root->SetRoot(true);
352 DALI_ASSERT_DEBUG( mImpl->systemLevelRoot == NULL && "System-level Root Node already installed" );
353 mImpl->systemLevelRoot = layer.Release();
354 mImpl->systemLevelRoot->CreateTransform( &mImpl->transformManager );
355 mImpl->systemLevelRoot->SetRoot(true);
360 void UpdateManager::AddNode( OwnerPointer<Node>& node )
362 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
364 // Nodes must be sorted by pointer
365 Node* rawNode = node.Release();
366 Vector<Node*>::Iterator begin = mImpl->nodes.Begin();
367 for( Vector<Node*>::Iterator iter = mImpl->nodes.End()-1; iter >= begin; --iter )
369 if( rawNode > (*iter) )
371 mImpl->nodes.Insert((iter+1), rawNode );
372 rawNode->CreateTransform( &mImpl->transformManager );
378 void UpdateManager::ConnectNode( Node* parent, Node* node )
380 DALI_ASSERT_ALWAYS( NULL != parent );
381 DALI_ASSERT_ALWAYS( NULL != node );
382 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
384 parent->ConnectChild( node );
387 void UpdateManager::DisconnectNode( Node* node )
389 Node* parent = node->GetParent();
390 DALI_ASSERT_ALWAYS( NULL != parent );
391 parent->SetDirtyFlag( ChildDeletedFlag ); // make parent dirty so that render items dont get reused
393 parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node );
396 void UpdateManager::DestroyNode( Node* node )
398 DALI_ASSERT_ALWAYS( NULL != node );
399 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
401 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
402 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
403 for(;iter!=endIter;++iter)
407 mImpl->nodes.Erase(iter);
412 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
414 // Notify the Node about impending destruction
418 void UpdateManager::AddCamera( OwnerPointer< Camera >& camera )
420 mImpl->cameras.PushBack( camera.Release() ); // 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( OwnerPointer<PropertyOwner>& object )
431 mImpl->customObjects.PushBack( object.Release() );
434 void UpdateManager::RemoveObject( PropertyOwner* object )
436 mImpl->customObjects.EraseObject( object );
439 void UpdateManager::AddAnimation( OwnerPointer< SceneGraph::Animation >& animation )
441 mImpl->animations.PushBack( animation.Release() );
444 void UpdateManager::StopAnimation( Animation* animation )
446 DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
448 bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
450 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
453 void UpdateManager::RemoveAnimation( Animation* animation )
455 DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
457 animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
459 DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
462 bool UpdateManager::IsAnimationRunning() const
464 bool isRunning(false);
465 AnimationContainer& animations = mImpl->animations;
467 // Find any animation that isn't stopped or paused
469 const AnimationIter endIter = animations.End();
470 for ( AnimationIter iter = animations.Begin(); !isRunning && iter != endIter; ++iter )
472 const Animation::State state = (*iter)->GetState();
474 if (state != Animation::Stopped &&
475 state != Animation::Paused)
484 void UpdateManager::AddPropertyNotification( OwnerPointer< PropertyNotification >& propertyNotification )
486 mImpl->propertyNotifications.PushBack( propertyNotification.Release() );
489 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
491 mImpl->propertyNotifications.EraseObject( propertyNotification );
494 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
496 DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
497 propertyNotification->SetNotifyMode( notifyMode );
500 void UpdateManager::AddShader( OwnerPointer< Shader >& shader )
502 mImpl->shaders.PushBack( shader.Release() );
505 void UpdateManager::RemoveShader( Shader* shader )
507 // Find the shader and destroy it
508 EraseUsingDiscardQueue( mImpl->shaders, shader, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
511 void UpdateManager::SetShaderProgram( Shader* shader,
512 Internal::ShaderDataPtr shaderData, bool modifiesGeometry )
517 typedef MessageValue3< Shader, Internal::ShaderDataPtr, ProgramCache*, bool> DerivedType;
519 // Reserve some memory inside the render queue
520 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
522 // Construct message in the render queue memory; note that delete should not be called on the return value
523 new (slot) DerivedType( shader, &Shader::SetProgram, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
527 void UpdateManager::SaveBinary( Internal::ShaderDataPtr shaderData )
529 DALI_ASSERT_DEBUG( shaderData && "No NULL shader data pointers please." );
530 DALI_ASSERT_DEBUG( shaderData->GetBufferSize() > 0 && "Shader binary empty so nothing to save." );
532 // lock as update might be sending previously compiled shaders to event thread
533 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
534 mImpl->renderCompiledShaders.push_back( shaderData );
538 void UpdateManager::SetShaderSaver( ShaderSaver& upstream )
540 mImpl->shaderSaver = &upstream;
543 void UpdateManager::AddRenderer( OwnerPointer< Renderer >& renderer )
545 renderer->ConnectToSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
546 mImpl->renderers.PushBack( renderer.Release() );
549 void UpdateManager::RemoveRenderer( Renderer* renderer )
551 // Find the renderer and destroy it
552 EraseUsingDiscardQueue( mImpl->renderers, renderer, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
553 // Need to remove the render object as well
554 renderer->DisconnectFromSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
557 void UpdateManager::SetPanGestureProcessor( PanGesture* panGestureProcessor )
559 DALI_ASSERT_DEBUG( NULL != panGestureProcessor );
561 mImpl->panGestureProcessor = panGestureProcessor;
564 void UpdateManager::AddTextureSet( OwnerPointer< TextureSet >& textureSet )
566 mImpl->textureSets.PushBack( textureSet.Release() );
569 void UpdateManager::RemoveTextureSet( TextureSet* textureSet )
571 mImpl->textureSets.EraseObject( textureSet );
574 RenderTaskList* UpdateManager::GetRenderTaskList( bool systemLevel )
578 // copy the list, this is only likely to happen once in application life cycle
579 return &(mImpl->taskList);
583 // copy the list, this is only likely to happen once in application life cycle
584 return &(mImpl->systemLevelTaskList);
588 unsigned int* UpdateManager::ReserveMessageSlot( std::size_t size, bool updateScene )
590 return mImpl->messageQueue.ReserveMessageSlot( size, updateScene );
593 void UpdateManager::EventProcessingStarted()
595 mImpl->messageQueue.EventProcessingStarted();
598 bool UpdateManager::FlushQueue()
600 return mImpl->messageQueue.FlushQueue();
603 void UpdateManager::ResetProperties( BufferIndex bufferIndex )
605 // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
606 mImpl->animationFinishedDuringUpdate = false;
608 // Animated properties have to be reset to their original value each frame
610 // Reset root properties
613 mImpl->root->ResetToBaseValues( bufferIndex );
615 if ( mImpl->systemLevelRoot )
617 mImpl->systemLevelRoot->ResetToBaseValues( bufferIndex );
620 // Reset all the nodes
621 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
622 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
623 for( ;iter != endIter; ++iter )
625 (*iter)->ResetToBaseValues( bufferIndex );
628 // Reset system-level render-task list properties to base values
629 ResetToBaseValues( mImpl->systemLevelTaskList.GetTasks(), bufferIndex );
631 // Reset render-task list properties to base values.
632 ResetToBaseValues( mImpl->taskList.GetTasks(), bufferIndex );
634 // Reset custom object properties to base values
635 ResetToBaseValues( mImpl->customObjects, bufferIndex );
637 // Reset animatable renderer properties to base values
638 ResetToBaseValues( mImpl->renderers, bufferIndex );
640 // Reset animatable shader properties to base values
641 ResetToBaseValues( mImpl->shaders, bufferIndex );
644 bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds )
646 bool gestureUpdated( false );
648 if( mImpl->panGestureProcessor )
650 // gesture processor only supports default properties
651 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
652 gestureUpdated |= mImpl->panGestureProcessor->UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
655 return gestureUpdated;
658 void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
660 AnimationContainer &animations = mImpl->animations;
661 AnimationIter iter = animations.Begin();
662 bool animationLooped = false;
663 while ( iter != animations.End() )
665 Animation* animation = *iter;
666 bool finished = false;
668 animation->Update( bufferIndex, elapsedSeconds, looped, finished );
670 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
671 animationLooped = animationLooped || looped;
673 // Remove animations that had been destroyed but were still waiting for an update
674 if (animation->GetState() == Animation::Destroyed)
676 iter = animations.Erase(iter);
684 // queue the notification on finished or looped (to update loop count)
685 if ( mImpl->animationFinishedDuringUpdate || animationLooped )
687 // The application should be notified by NotificationManager, in another thread
688 mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationFinishedNotifier );
692 void UpdateManager::ConstrainCustomObjects( BufferIndex bufferIndex )
694 //Constrain custom objects (in construction order)
695 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
696 const OwnerContainer< PropertyOwner* >::Iterator endIter = customObjects.End();
697 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); endIter != iter; ++iter )
699 PropertyOwner& object = **iter;
700 ConstrainPropertyOwner( object, bufferIndex );
704 void UpdateManager::ConstrainRenderTasks( BufferIndex bufferIndex )
706 // Constrain system-level render-tasks
707 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
708 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter )
710 RenderTask& task = **iter;
711 ConstrainPropertyOwner( task, bufferIndex );
714 // Constrain render-tasks
715 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
716 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter )
718 RenderTask& task = **iter;
719 ConstrainPropertyOwner( task, bufferIndex );
723 void UpdateManager::ConstrainShaders( BufferIndex bufferIndex )
725 // constrain shaders... (in construction order)
726 ShaderOwner& shaders = mImpl->shaders;
727 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
729 Shader& shader = **iter;
730 ConstrainPropertyOwner( shader, bufferIndex );
734 void UpdateManager::ProcessPropertyNotifications( BufferIndex bufferIndex )
736 PropertyNotificationContainer ¬ifications = mImpl->propertyNotifications;
737 PropertyNotificationIter iter = notifications.Begin();
739 while ( iter != notifications.End() )
741 PropertyNotification* notification = *iter;
742 bool valid = notification->Check( bufferIndex );
745 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
751 void UpdateManager::ForwardCompiledShadersToEventThread()
753 DALI_ASSERT_DEBUG( (mImpl->shaderSaver != 0) && "shaderSaver should be wired-up during startup." );
754 if( mImpl->shaderSaver )
756 // lock and swap the queues
758 // render might be attempting to send us more binaries at the same time
759 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
760 mImpl->renderCompiledShaders.swap( mImpl->updateCompiledShaders );
763 if( mImpl->updateCompiledShaders.size() > 0 )
765 ShaderSaver& factory = *mImpl->shaderSaver;
766 ShaderDataBinaryQueue::iterator i = mImpl->updateCompiledShaders.begin();
767 ShaderDataBinaryQueue::iterator end = mImpl->updateCompiledShaders.end();
768 for( ; i != end; ++i )
770 mImpl->notificationManager.QueueMessage( ShaderCompiledMessage( factory, *i ) );
772 // we don't need them in update anymore
773 mImpl->updateCompiledShaders.clear();
778 void UpdateManager::UpdateRenderers( BufferIndex bufferIndex )
780 const unsigned int rendererCount = mImpl->renderers.Count();
781 for( unsigned int i = 0; i < rendererCount; ++i )
784 ConstrainPropertyOwner( *mImpl->renderers[i], bufferIndex );
786 mImpl->renderers[i]->PrepareRender( bufferIndex );
790 void UpdateManager::UpdateNodes( BufferIndex bufferIndex )
792 mImpl->nodeDirtyFlags = NothingFlag;
799 // Prepare resources, update shaders, for each node
800 // And add the renderers to the sorted layers. Start from root, which is also a layer
801 mImpl->nodeDirtyFlags = UpdateNodeTree( *( mImpl->root ),
803 mImpl->renderQueue );
805 if ( mImpl->systemLevelRoot )
807 mImpl->nodeDirtyFlags |= UpdateNodeTree( *( mImpl->systemLevelRoot ),
809 mImpl->renderQueue );
813 unsigned int UpdateManager::Update( float elapsedSeconds,
814 unsigned int lastVSyncTimeMilliseconds,
815 unsigned int nextVSyncTimeMilliseconds )
817 const BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
819 //Clear nodes/resources which were previously discarded
820 mImpl->discardQueue.Clear( bufferIndex );
822 //Process Touches & Gestures
823 const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
825 bool updateScene = // The scene-graph requires an update if..
826 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
827 IsAnimationRunning() || // ..at least one animation is running OR
828 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
829 gestureUpdated; // ..a gesture property was updated
832 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
833 // values if the scene was updated in the previous frame.
834 if( updateScene || mImpl->previousUpdateScene )
836 //Reset properties from the previous update
837 ResetProperties( bufferIndex );
838 mImpl->transformManager.ResetToBaseValue();
841 // Process the queued scene messages. Note, MessageQueue::FlushQueue may be called
842 // between calling IsSceneUpdateRequired() above and here, so updateScene should
844 updateScene |= mImpl->messageQueue.ProcessMessages( bufferIndex );
846 //Forward compiled shader programs to event thread for saving
847 ForwardCompiledShadersToEventThread();
849 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
850 // renderer lists if the scene was updated in the previous frame.
851 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
852 if( updateScene || mImpl->previousUpdateScene )
855 Animate( bufferIndex, elapsedSeconds );
857 //Constraint custom objects
858 ConstrainCustomObjects( bufferIndex );
860 //Clear the lists of renderers from the previous update
861 for( size_t i(0); i<mImpl->sortedLayers.size(); ++i )
863 mImpl->sortedLayers[i]->ClearRenderables();
866 for( size_t i(0); i<mImpl->systemLevelSortedLayers.size(); ++i )
868 mImpl->systemLevelSortedLayers[i]->ClearRenderables();
871 //Update node hierarchy, apply constraints and perform sorting / culling.
872 //This will populate each Layer with a list of renderers which are ready.
873 UpdateNodes( bufferIndex );
875 //Apply constraints to RenderTasks, shaders
876 ConstrainRenderTasks( bufferIndex );
877 ConstrainShaders( bufferIndex );
879 //Update renderers and apply constraints
880 UpdateRenderers( bufferIndex );
882 //Update the trnasformations of all the nodes
883 mImpl->transformManager.Update();
885 //Process Property Notifications
886 ProcessPropertyNotifications( bufferIndex );
888 //Process the RenderTasks; this creates the instructions for rendering the next frame.
889 //reset the update buffer index and make sure there is enough room in the instruction container
890 mImpl->renderInstructions.ResetAndReserve( bufferIndex,
891 mImpl->taskList.GetTasks().Count() + mImpl->systemLevelTaskList.GetTasks().Count() );
893 if ( NULL != mImpl->root )
895 mImpl->renderTaskProcessor.Process( bufferIndex,
899 mImpl->renderInstructions );
901 // Process the system-level RenderTasks last
902 if ( NULL != mImpl->systemLevelRoot )
904 mImpl->renderTaskProcessor.Process( bufferIndex,
905 mImpl->systemLevelTaskList,
906 *mImpl->systemLevelRoot,
907 mImpl->systemLevelSortedLayers,
908 mImpl->renderInstructions );
913 // check the countdown and notify (note, at the moment this is only done for normal tasks, not for systemlevel tasks)
914 bool doRenderOnceNotify = false;
915 mImpl->renderTaskWaiting = false;
916 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
917 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(), endIter = tasks.End();
918 endIter != iter; ++iter )
920 RenderTask& renderTask(*(*iter));
922 renderTask.UpdateState();
924 if( renderTask.IsWaitingToRender() &&
925 renderTask.ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
927 mImpl->renderTaskWaiting = true; // keep update/render threads alive
930 if( renderTask.HasRendered() )
932 doRenderOnceNotify = true;
936 if( doRenderOnceNotify )
938 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
939 mImpl->notificationManager.QueueCompleteNotification( mImpl->taskList.GetCompleteNotificationInterface() );
942 // Macro is undefined in release build.
943 SNAPSHOT_NODE_LOGGING;
945 // A ResetProperties() may be required in the next frame
946 mImpl->previousUpdateScene = updateScene;
948 // Check whether further updates are required
949 unsigned int keepUpdating = KeepUpdatingCheck( elapsedSeconds );
951 // tell the update manager that we're done so the queue can be given to event thread
952 mImpl->notificationManager.UpdateCompleted();
954 // The update has finished; swap the double-buffering indices
955 mSceneGraphBuffers.Swap();
960 unsigned int UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
962 // Update the duration set via Stage::KeepRendering()
963 if ( mImpl->keepRenderingSeconds > 0.0f )
965 mImpl->keepRenderingSeconds -= elapsedSeconds;
968 unsigned int keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
970 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
971 // Keep updating until no messages are received and no animations are running.
972 // If an animation has just finished, update at least once more for Discard end-actions.
973 // No need to check for renderQueue as there is always a render after update and if that
974 // render needs another update it will tell the adaptor to call update again
976 if ( mImpl->keepRenderingSeconds > 0.0f )
978 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
981 if ( IsAnimationRunning() ||
982 mImpl->animationFinishedDuringUpdate )
984 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
987 if ( mImpl->renderTaskWaiting )
989 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
992 return keepUpdatingRequest;
995 void UpdateManager::SetBackgroundColor( const Vector4& color )
997 typedef MessageValue1< RenderManager, Vector4 > DerivedType;
999 // Reserve some memory inside the render queue
1000 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1002 // Construct message in the render queue memory; note that delete should not be called on the return value
1003 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
1006 void UpdateManager::SetDefaultSurfaceRect( const Rect<int>& rect )
1008 typedef MessageValue1< RenderManager, Rect<int> > DerivedType;
1010 // Reserve some memory inside the render queue
1011 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1013 // Construct message in the render queue memory; note that delete should not be called on the return value
1014 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1017 void UpdateManager::KeepRendering( float durationSeconds )
1019 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1022 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, bool systemLevel )
1026 // just copy the vector of pointers
1027 mImpl->sortedLayers = layers;
1031 mImpl->systemLevelSortedLayers = layers;
1035 void UpdateManager::SetDepthIndices( OwnerPointer< NodeDepths >& nodeDepths )
1037 // note,this vector is already in depth order. It could be used as-is to
1038 // remove sorting in update algorithm. However, it lacks layer boundary markers.
1039 for( std::vector<NodeDepthPair>::iterator iter = nodeDepths->nodeDepths.begin(),
1040 end = nodeDepths->nodeDepths.end() ;
1041 iter != end ; ++iter )
1043 iter->node->SetDepthIndex( iter->sortedDepth );
1047 void UpdateManager::AddSampler( OwnerPointer< Render::Sampler >& sampler )
1049 // Message has ownership of Sampler while in transit from update to render
1050 typedef MessageValue1< RenderManager, OwnerPointer< Render::Sampler > > DerivedType;
1052 // Reserve some memory inside the render queue
1053 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1055 // Construct message in the render queue memory; note that delete should not be called on the return value
1056 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddSampler, sampler );
1059 void UpdateManager::RemoveSampler( Render::Sampler* sampler )
1061 typedef MessageValue1< RenderManager, Render::Sampler* > DerivedType;
1063 // Reserve some memory inside the render queue
1064 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1066 // Construct message in the render queue memory; note that delete should not be called on the return value
1067 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveSampler, sampler );
1070 void UpdateManager::SetFilterMode( Render::Sampler* sampler, unsigned int minFilterMode, unsigned int magFilterMode )
1072 typedef MessageValue3< RenderManager, Render::Sampler*, unsigned int, unsigned int > DerivedType;
1074 // Reserve some memory inside the render queue
1075 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1077 // Construct message in the render queue memory; note that delete should not be called on the return value
1078 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetFilterMode, sampler, minFilterMode, magFilterMode );
1081 void UpdateManager::SetWrapMode( Render::Sampler* sampler, unsigned int rWrapMode, unsigned int sWrapMode, unsigned int tWrapMode )
1083 typedef MessageValue4< RenderManager, Render::Sampler*, unsigned int, unsigned int, unsigned int > DerivedType;
1085 // Reserve some memory inside the render queue
1086 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1088 // Construct message in the render queue memory; note that delete should not be called on the return value
1089 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetWrapMode, sampler, rWrapMode, sWrapMode, tWrapMode );
1092 void UpdateManager::AddPropertyBuffer( OwnerPointer< Render::PropertyBuffer >& propertyBuffer )
1094 // Message has ownership of format while in transit from update -> render
1095 typedef MessageValue1< RenderManager, OwnerPointer< Render::PropertyBuffer > > DerivedType;
1097 // Reserve some memory inside the render queue
1098 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1100 // Construct message in the render queue memory; note that delete should not be called on the return value
1101 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddPropertyBuffer, propertyBuffer );
1104 void UpdateManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer )
1106 typedef MessageValue1< RenderManager, Render::PropertyBuffer* > DerivedType;
1108 // Reserve some memory inside the render queue
1109 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1111 // Construct message in the render queue memory; note that delete should not be called on the return value
1112 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemovePropertyBuffer, propertyBuffer );
1115 void UpdateManager::SetPropertyBufferFormat( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Render::PropertyBuffer::Format>& format )
1117 // Message has ownership of format while in transit from update -> render
1118 typedef MessageValue2< RenderManager, Render::PropertyBuffer*, OwnerPointer< Render::PropertyBuffer::Format > > DerivedType;
1120 // Reserve some memory inside the render queue
1121 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1123 // Construct message in the render queue memory; note that delete should not be called on the return value
1124 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferFormat, propertyBuffer, format );
1127 void UpdateManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Vector<char> >& data, size_t size )
1129 // Message has ownership of format while in transit from update -> render
1130 typedef MessageValue3< RenderManager, Render::PropertyBuffer*, OwnerPointer< Dali::Vector<char> >, size_t > DerivedType;
1132 // Reserve some memory inside the render queue
1133 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1135 // Construct message in the render queue memory; note that delete should not be called on the return value
1136 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferData, propertyBuffer, data, size );
1139 void UpdateManager::AddGeometry( OwnerPointer< Render::Geometry >& geometry )
1141 // Message has ownership of format while in transit from update -> render
1142 typedef MessageValue1< RenderManager, OwnerPointer< Render::Geometry > > DerivedType;
1144 // Reserve some memory inside the render queue
1145 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1147 // Construct message in the render queue memory; note that delete should not be called on the return value
1148 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddGeometry, geometry );
1151 void UpdateManager::RemoveGeometry( Render::Geometry* geometry )
1153 typedef MessageValue1< RenderManager, Render::Geometry* > DerivedType;
1155 // Reserve some memory inside the render queue
1156 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1158 // Construct message in the render queue memory; note that delete should not be called on the return value
1159 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveGeometry, geometry );
1162 void UpdateManager::SetGeometryType( Render::Geometry* geometry, unsigned int geometryType )
1164 typedef MessageValue2< RenderManager, Render::Geometry*, unsigned int > DerivedType;
1166 // Reserve some memory inside the render queue
1167 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1169 // Construct message in the render queue memory; note that delete should not be called on the return value
1170 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetGeometryType, geometry, geometryType );
1173 void UpdateManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector<unsigned short>& indices )
1175 typedef IndexBufferMessage< RenderManager > DerivedType;
1177 // Reserve some memory inside the render queue
1178 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1180 // Construct message in the render queue memory; note that delete should not be called on the return value
1181 new (slot) DerivedType( &mImpl->renderManager, geometry, indices );
1184 void UpdateManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1186 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1188 // Reserve some memory inside the render queue
1189 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1191 // Construct message in the render queue memory; note that delete should not be called on the return value
1192 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveVertexBuffer, geometry, propertyBuffer );
1195 void UpdateManager::AttachVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1197 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1199 // Reserve some memory inside the render queue
1200 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1202 // Construct message in the render queue memory; note that delete should not be called on the return value
1203 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AttachVertexBuffer, geometry, propertyBuffer );
1206 void UpdateManager::AddTexture( OwnerPointer< Render::Texture >& texture )
1208 // Message has ownership of Texture while in transit from update -> render
1209 typedef MessageValue1< RenderManager, OwnerPointer< Render::Texture > > DerivedType;
1211 // Reserve some memory inside the render queue
1212 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1214 // Construct message in the render queue memory; note that delete should not be called on the return value
1215 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddTexture, texture );
1218 void UpdateManager::RemoveTexture( Render::Texture* texture)
1220 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1222 // Reserve some memory inside the render queue
1223 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1225 // Construct message in the render queue memory; note that delete should not be called on the return value
1226 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveTexture, texture );
1229 void UpdateManager::UploadTexture( Render::Texture* texture, PixelDataPtr pixelData, const Texture::UploadParams& params )
1231 typedef MessageValue3< RenderManager, Render::Texture*, PixelDataPtr, Texture::UploadParams > DerivedType;
1233 // Reserve some memory inside the message queue
1234 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1236 // Construct message in the message queue memory; note that delete should not be called on the return value
1237 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::UploadTexture, texture, pixelData, params );
1240 void UpdateManager::GenerateMipmaps( Render::Texture* texture )
1242 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1244 // Reserve some memory inside the render queue
1245 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1247 // Construct message in the render queue memory; note that delete should not be called on the return value
1248 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::GenerateMipmaps, texture );
1251 void UpdateManager::AddFrameBuffer( Render::FrameBuffer* frameBuffer )
1253 typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType;
1255 // Reserve some memory inside the render queue
1256 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1258 // Construct message in the render queue memory; note that delete should not be called on the return value
1259 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddFrameBuffer, frameBuffer );
1262 void UpdateManager::RemoveFrameBuffer( Render::FrameBuffer* frameBuffer)
1264 typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType;
1266 // Reserve some memory inside the render queue
1267 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1269 // Construct message in the render queue memory; note that delete should not be called on the return value
1270 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveFrameBuffer, frameBuffer );
1273 void UpdateManager::AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, unsigned int mipmapLevel, unsigned int layer )
1275 typedef MessageValue4< RenderManager, Render::FrameBuffer*, Render::Texture*, unsigned int, unsigned int > 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::AttachColorTextureToFrameBuffer, frameBuffer, texture, mipmapLevel, layer );
1284 } // namespace SceneGraph
1286 } // namespace Internal