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/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/render-task-processor.h>
48 #include <dali/internal/update/manager/sorted-layers.h>
49 #include <dali/internal/update/manager/update-algorithms.h>
50 #include <dali/internal/update/manager/update-manager-debug.h>
51 #include <dali/internal/update/manager/transform-manager.h>
52 #include <dali/internal/update/nodes/node.h>
53 #include <dali/internal/update/nodes/scene-graph-layer.h>
54 #include <dali/internal/update/queue/update-message-queue.h>
55 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
56 #include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
57 #include <dali/internal/update/render-tasks/scene-graph-camera.h>
59 #include <dali/internal/render/common/render-instruction-container.h>
60 #include <dali/internal/render/common/render-manager.h>
61 #include <dali/internal/render/queue/render-queue.h>
62 #include <dali/internal/render/shaders/scene-graph-shader.h>
64 // Un-comment to enable node tree debug logging
65 //#define NODE_TREE_LOGGING 1
67 #if ( defined( DEBUG_ENABLED ) && defined( NODE_TREE_LOGGING ) )
68 #define SNAPSHOT_NODE_LOGGING \
69 const int FRAME_COUNT_TRIGGER = 16;\
70 if( mImpl->frameCounter >= FRAME_COUNT_TRIGGER )\
72 if ( NULL != mImpl->root )\
74 mImpl->frameCounter = 0;\
75 PrintNodeTree( *mImpl->root, mSceneGraphBuffers.GetUpdateBufferIndex(), "" );\
78 mImpl->frameCounter++;
80 #define SNAPSHOT_NODE_LOGGING
83 #if defined(DEBUG_ENABLED)
84 extern Debug::Filter* gRenderTaskLogFilter;
88 using namespace Dali::Integration;
89 using Dali::Internal::Update::MessageQueue;
103 * Helper to reset animate-able objects to base values
104 * @param container to iterate over
105 * @param updateBufferIndex to use
108 inline void ResetToBaseValues( OwnerContainer<T*>& container, BufferIndex updateBufferIndex )
110 // Reset animatable properties to base values
111 typename OwnerContainer<T*>::Iterator iter = container.Begin();
112 const typename OwnerContainer<T*>::ConstIterator endIter = container.End();
113 for ( ; iter != endIter; ++iter )
115 (*iter)->ResetToBaseValues( updateBufferIndex );
120 * Helper to Erase an object from OwnerContainer using discard queue
121 * @param container to remove from
122 * @param object to remove
123 * @param discardQueue to put the object to
124 * @param updateBufferIndex to use
127 inline void EraseUsingDiscardQueue( OwnerContainer<T*>& container, T* object, DiscardQueue& discardQueue, BufferIndex updateBufferIndex )
129 DALI_ASSERT_DEBUG( object && "NULL object not allowed" );
131 typename OwnerContainer<T*>::Iterator iter = container.Begin();
132 const typename OwnerContainer<T*>::ConstIterator endIter = container.End();
133 for ( ; iter != endIter; ++iter )
135 if ( *iter == object )
137 // Transfer ownership to the discard queue, this keeps the object alive, until the render-thread has finished with it
138 discardQueue.Add( updateBufferIndex, container.Release( iter ) );
146 typedef OwnerContainer< Shader* > ShaderOwner;
147 typedef ShaderOwner::Iterator ShaderIter;
148 typedef std::vector<Internal::ShaderDataPtr> ShaderDataBinaryQueue;
150 typedef OwnerContainer< TextureSet* > TextureSetOwner;
151 typedef TextureSetOwner::Iterator TextureSetIter;
153 typedef OwnerContainer<Renderer*> RendererOwner;
154 typedef RendererOwner::Iterator RendererIter;
156 typedef OwnerContainer< Camera* > CameraOwner;
157 typedef OwnerContainer< PropertyOwner* > CustomObjectOwner;
160 * Structure to contain UpdateManager internal data
162 struct UpdateManager::Impl
164 Impl( NotificationManager& notificationManager,
165 CompleteNotificationInterface& animationFinishedNotifier,
166 PropertyNotifier& propertyNotifier,
167 DiscardQueue& discardQueue,
168 RenderController& renderController,
169 RenderManager& renderManager,
170 RenderQueue& renderQueue,
171 SceneGraphBuffers& sceneGraphBuffers,
172 RenderTaskProcessor& renderTaskProcessor )
173 : renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ),
174 notificationManager( notificationManager ),
176 animationFinishedNotifier( animationFinishedNotifier ),
177 propertyNotifier( propertyNotifier ),
179 discardQueue( discardQueue ),
180 renderController( renderController ),
181 sceneController( NULL ),
182 renderManager( renderManager ),
183 renderQueue( renderQueue ),
184 renderInstructions( renderManager.GetRenderInstructionContainer() ),
185 renderTaskProcessor( renderTaskProcessor ),
186 backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
187 taskList( renderMessageDispatcher ),
188 systemLevelTaskList( renderMessageDispatcher ),
190 systemLevelRoot( NULL ),
194 panGestureProcessor( NULL ),
195 messageQueue( renderController, sceneGraphBuffers ),
196 keepRenderingSeconds( 0.0f ),
197 nodeDirtyFlags( TransformFlag ), // set to TransformFlag to ensure full update the first time through Update()
199 animationFinishedDuringUpdate( false ),
200 previousUpdateScene( false ),
201 renderTaskWaiting( false )
203 sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue );
205 // create first 'dummy' node
211 // Disconnect render tasks from nodes, before destroying the nodes
212 RenderTaskList::RenderTaskContainer& tasks = taskList.GetTasks();
213 for (RenderTaskList::RenderTaskContainer::Iterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
215 (*iter)->SetSourceNode( NULL );
217 // ..repeat for system level RenderTasks
218 RenderTaskList::RenderTaskContainer& systemLevelTasks = systemLevelTaskList.GetTasks();
219 for (RenderTaskList::RenderTaskContainer::Iterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
221 (*iter)->SetSourceNode( NULL );
224 // UpdateManager owns the Nodes
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( SceneGraph::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" );
347 mImpl->root->CreateTransform( &mImpl->transformManager );
351 DALI_ASSERT_DEBUG( mImpl->systemLevelRoot == NULL && "System-level Root Node already installed" );
352 mImpl->systemLevelRoot = layer;
353 mImpl->systemLevelRoot->CreateTransform( &mImpl->transformManager );
356 layer->SetRoot(true);
359 void UpdateManager::AddNode( Node* node )
361 DALI_ASSERT_ALWAYS( NULL != node );
362 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
364 // Nodes must be sorted by pointer
365 Vector<Node*>::Iterator begin = mImpl->nodes.Begin();
366 for(Vector<Node*>::Iterator iter = mImpl->nodes.End()-1; iter >= begin; --iter)
370 mImpl->nodes.Insert((iter+1), node);
371 node->CreateTransform( &mImpl->transformManager );
377 void UpdateManager::ConnectNode( Node* parent, Node* node )
379 DALI_ASSERT_ALWAYS( NULL != parent );
380 DALI_ASSERT_ALWAYS( NULL != node );
381 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
383 parent->ConnectChild( node );
386 void UpdateManager::DisconnectNode( Node* node )
388 Node* parent = node->GetParent();
389 DALI_ASSERT_ALWAYS( NULL != parent );
390 parent->SetDirtyFlag( ChildDeletedFlag ); // make parent dirty so that render items dont get reused
392 parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node );
395 void UpdateManager::DestroyNode( Node* node )
397 DALI_ASSERT_ALWAYS( NULL != node );
398 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
400 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
401 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
402 for(;iter!=endIter;++iter)
406 mImpl->nodes.Erase(iter);
411 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
413 // Notify the Node about impending destruction
417 void UpdateManager::AddCamera( Camera* camera )
419 DALI_ASSERT_DEBUG( camera != NULL );
421 mImpl->cameras.PushBack( camera ); // takes ownership
424 void UpdateManager::RemoveCamera( const Camera* camera )
426 // Find the camera and destroy it
427 EraseUsingDiscardQueue( mImpl->cameras, const_cast<Camera*>( camera ), mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
430 void UpdateManager::AddObject( PropertyOwner* object )
432 DALI_ASSERT_DEBUG( NULL != object );
434 mImpl->customObjects.PushBack( object );
437 void UpdateManager::RemoveObject( PropertyOwner* object )
439 mImpl->customObjects.EraseObject( object );
442 void UpdateManager::AddAnimation( Animation* animation )
444 mImpl->animations.PushBack( animation );
447 void UpdateManager::StopAnimation( Animation* animation )
449 DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
451 bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
453 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
456 void UpdateManager::RemoveAnimation( Animation* animation )
458 DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
460 animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
462 DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
465 bool UpdateManager::IsAnimationRunning() const
467 bool isRunning(false);
468 AnimationContainer& animations = mImpl->animations;
470 // Find any animation that isn't stopped or paused
472 const AnimationIter endIter = animations.End();
473 for ( AnimationIter iter = animations.Begin(); !isRunning && iter != endIter; ++iter )
475 const Animation::State state = (*iter)->GetState();
477 if (state != Animation::Stopped &&
478 state != Animation::Paused)
487 void UpdateManager::AddPropertyNotification( PropertyNotification* propertyNotification )
489 mImpl->propertyNotifications.PushBack( propertyNotification );
492 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
494 mImpl->propertyNotifications.EraseObject( propertyNotification );
497 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
499 DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
500 propertyNotification->SetNotifyMode( notifyMode );
503 void UpdateManager::AddShader( Shader* shader )
505 DALI_ASSERT_DEBUG( NULL != shader );
507 mImpl->shaders.PushBack( shader );
510 void UpdateManager::RemoveShader( Shader* shader )
512 // Find the shader and destroy it
513 EraseUsingDiscardQueue( mImpl->shaders, shader, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
516 void UpdateManager::SetShaderProgram( Shader* shader,
517 Internal::ShaderDataPtr shaderData, bool modifiesGeometry )
522 typedef MessageValue3< Shader, Internal::ShaderDataPtr, ProgramCache*, bool> DerivedType;
524 // Reserve some memory inside the render queue
525 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
527 // Construct message in the render queue memory; note that delete should not be called on the return value
528 new (slot) DerivedType( shader, &Shader::SetProgram, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
532 void UpdateManager::SaveBinary( Internal::ShaderDataPtr shaderData )
534 DALI_ASSERT_DEBUG( shaderData && "No NULL shader data pointers please." );
535 DALI_ASSERT_DEBUG( shaderData->GetBufferSize() > 0 && "Shader binary empty so nothing to save." );
537 // lock as update might be sending previously compiled shaders to event thread
538 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
539 mImpl->renderCompiledShaders.push_back( shaderData );
543 void UpdateManager::SetShaderSaver( ShaderSaver& upstream )
545 mImpl->shaderSaver = &upstream;
548 void UpdateManager::AddRenderer( Renderer* renderer )
550 DALI_ASSERT_DEBUG( renderer != NULL );
552 mImpl->renderers.PushBack( renderer );
554 renderer->ConnectToSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
557 void UpdateManager::RemoveRenderer( Renderer* renderer )
559 // Find the renderer and destroy it
560 EraseUsingDiscardQueue( mImpl->renderers, renderer, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
561 // Need to remove the render object as well
562 renderer->DisconnectFromSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
565 void UpdateManager::SetPanGestureProcessor( PanGesture* panGestureProcessor )
567 DALI_ASSERT_DEBUG( NULL != panGestureProcessor );
569 mImpl->panGestureProcessor = panGestureProcessor;
572 void UpdateManager::AddTextureSet( TextureSet* textureSet )
574 DALI_ASSERT_DEBUG( NULL != textureSet );
576 mImpl->textureSets.PushBack( textureSet );
579 void UpdateManager::RemoveTextureSet( TextureSet* textureSet )
581 mImpl->textureSets.EraseObject( textureSet );
584 RenderTaskList* UpdateManager::GetRenderTaskList( bool systemLevel )
588 // copy the list, this is only likely to happen once in application life cycle
589 return &(mImpl->taskList);
593 // copy the list, this is only likely to happen once in application life cycle
594 return &(mImpl->systemLevelTaskList);
598 unsigned int* UpdateManager::ReserveMessageSlot( std::size_t size, bool updateScene )
600 return mImpl->messageQueue.ReserveMessageSlot( size, updateScene );
603 void UpdateManager::EventProcessingStarted()
605 mImpl->messageQueue.EventProcessingStarted();
608 bool UpdateManager::FlushQueue()
610 return mImpl->messageQueue.FlushQueue();
613 void UpdateManager::ResetProperties( BufferIndex bufferIndex )
615 // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
616 mImpl->animationFinishedDuringUpdate = false;
618 // Animated properties have to be reset to their original value each frame
620 // Reset root properties
623 mImpl->root->ResetToBaseValues( bufferIndex );
625 if ( mImpl->systemLevelRoot )
627 mImpl->systemLevelRoot->ResetToBaseValues( bufferIndex );
630 // Reset all the nodes
631 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
632 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
633 for( ;iter != endIter; ++iter )
635 (*iter)->ResetToBaseValues( bufferIndex );
638 // Reset system-level render-task list properties to base values
639 ResetToBaseValues( mImpl->systemLevelTaskList.GetTasks(), bufferIndex );
641 // Reset render-task list properties to base values.
642 ResetToBaseValues( mImpl->taskList.GetTasks(), bufferIndex );
644 // Reset custom object properties to base values
645 ResetToBaseValues( mImpl->customObjects, bufferIndex );
647 // Reset animatable renderer properties to base values
648 ResetToBaseValues( mImpl->renderers, bufferIndex );
650 // Reset animatable shader properties to base values
651 ResetToBaseValues( mImpl->shaders, bufferIndex );
654 bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds )
656 bool gestureUpdated( false );
658 if( mImpl->panGestureProcessor )
660 // gesture processor only supports default properties
661 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
662 gestureUpdated |= mImpl->panGestureProcessor->UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
665 return gestureUpdated;
668 void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
670 AnimationContainer &animations = mImpl->animations;
671 AnimationIter iter = animations.Begin();
672 bool animationLooped = false;
673 while ( iter != animations.End() )
675 Animation* animation = *iter;
676 bool finished = false;
678 animation->Update( bufferIndex, elapsedSeconds, looped, finished );
680 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
681 animationLooped = animationLooped || looped;
683 // Remove animations that had been destroyed but were still waiting for an update
684 if (animation->GetState() == Animation::Destroyed)
686 iter = animations.Erase(iter);
694 // queue the notification on finished or looped (to update loop count)
695 if ( mImpl->animationFinishedDuringUpdate || animationLooped )
697 // The application should be notified by NotificationManager, in another thread
698 mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationFinishedNotifier );
702 void UpdateManager::ConstrainCustomObjects( BufferIndex bufferIndex )
704 //Constrain custom objects (in construction order)
705 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
706 const OwnerContainer< PropertyOwner* >::Iterator endIter = customObjects.End();
707 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); endIter != iter; ++iter )
709 PropertyOwner& object = **iter;
710 ConstrainPropertyOwner( object, bufferIndex );
714 void UpdateManager::ConstrainRenderTasks( BufferIndex bufferIndex )
716 // Constrain system-level render-tasks
717 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
718 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter )
720 RenderTask& task = **iter;
721 ConstrainPropertyOwner( task, bufferIndex );
724 // Constrain render-tasks
725 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
726 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter )
728 RenderTask& task = **iter;
729 ConstrainPropertyOwner( task, bufferIndex );
733 void UpdateManager::ConstrainShaders( BufferIndex bufferIndex )
735 // constrain shaders... (in construction order)
736 ShaderOwner& shaders = mImpl->shaders;
737 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
739 Shader& shader = **iter;
740 ConstrainPropertyOwner( shader, bufferIndex );
744 void UpdateManager::ProcessPropertyNotifications( BufferIndex bufferIndex )
746 PropertyNotificationContainer ¬ifications = mImpl->propertyNotifications;
747 PropertyNotificationIter iter = notifications.Begin();
749 while ( iter != notifications.End() )
751 PropertyNotification* notification = *iter;
752 bool valid = notification->Check( bufferIndex );
755 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
761 void UpdateManager::ForwardCompiledShadersToEventThread()
763 DALI_ASSERT_DEBUG( (mImpl->shaderSaver != 0) && "shaderSaver should be wired-up during startup." );
764 if( mImpl->shaderSaver )
766 // lock and swap the queues
768 // render might be attempting to send us more binaries at the same time
769 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
770 mImpl->renderCompiledShaders.swap( mImpl->updateCompiledShaders );
773 if( mImpl->updateCompiledShaders.size() > 0 )
775 ShaderSaver& factory = *mImpl->shaderSaver;
776 ShaderDataBinaryQueue::iterator i = mImpl->updateCompiledShaders.begin();
777 ShaderDataBinaryQueue::iterator end = mImpl->updateCompiledShaders.end();
778 for( ; i != end; ++i )
780 mImpl->notificationManager.QueueMessage( ShaderCompiledMessage( factory, *i ) );
782 // we don't need them in update anymore
783 mImpl->updateCompiledShaders.clear();
788 void UpdateManager::UpdateRenderers( BufferIndex bufferIndex )
790 const unsigned int rendererCount = mImpl->renderers.Count();
791 for( unsigned int i = 0; i < rendererCount; ++i )
794 ConstrainPropertyOwner( *mImpl->renderers[i], bufferIndex );
796 mImpl->renderers[i]->PrepareRender( bufferIndex );
800 void UpdateManager::UpdateNodes( BufferIndex bufferIndex )
802 mImpl->nodeDirtyFlags = NothingFlag;
809 // Prepare resources, update shaders, for each node
810 // And add the renderers to the sorted layers. Start from root, which is also a layer
811 mImpl->nodeDirtyFlags = UpdateNodeTree( *( mImpl->root ),
813 mImpl->renderQueue );
815 if ( mImpl->systemLevelRoot )
817 mImpl->nodeDirtyFlags |= UpdateNodeTree( *( mImpl->systemLevelRoot ),
819 mImpl->renderQueue );
823 unsigned int UpdateManager::Update( float elapsedSeconds,
824 unsigned int lastVSyncTimeMilliseconds,
825 unsigned int nextVSyncTimeMilliseconds )
827 const BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
829 //Clear nodes/resources which were previously discarded
830 mImpl->discardQueue.Clear( bufferIndex );
832 //Process Touches & Gestures
833 const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
835 bool updateScene = // The scene-graph requires an update if..
836 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
837 IsAnimationRunning() || // ..at least one animation is running OR
838 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
839 gestureUpdated; // ..a gesture property was updated
842 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
843 // values if the scene was updated in the previous frame.
844 if( updateScene || mImpl->previousUpdateScene )
846 //Reset properties from the previous update
847 ResetProperties( bufferIndex );
848 mImpl->transformManager.ResetToBaseValue();
851 // Process the queued scene messages. Note, MessageQueue::FlushQueue may be called
852 // between calling IsSceneUpdateRequired() above and here, so updateScene should
854 updateScene |= mImpl->messageQueue.ProcessMessages( bufferIndex );
856 //Forward compiled shader programs to event thread for saving
857 ForwardCompiledShadersToEventThread();
859 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
860 // renderer lists if the scene was updated in the previous frame.
861 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
862 if( updateScene || mImpl->previousUpdateScene )
865 Animate( bufferIndex, elapsedSeconds );
867 //Constraint custom objects
868 ConstrainCustomObjects( bufferIndex );
870 //Clear the lists of renderers from the previous update
871 for( size_t i(0); i<mImpl->sortedLayers.size(); ++i )
873 mImpl->sortedLayers[i]->ClearRenderables();
876 for( size_t i(0); i<mImpl->systemLevelSortedLayers.size(); ++i )
878 mImpl->systemLevelSortedLayers[i]->ClearRenderables();
881 //Update node hierarchy, apply constraints and perform sorting / culling.
882 //This will populate each Layer with a list of renderers which are ready.
883 UpdateNodes( bufferIndex );
885 //Apply constraints to RenderTasks, shaders
886 ConstrainRenderTasks( bufferIndex );
887 ConstrainShaders( bufferIndex );
889 //Update renderers and apply constraints
890 UpdateRenderers( bufferIndex );
892 //Update the trnasformations of all the nodes
893 mImpl->transformManager.Update();
895 //Process Property Notifications
896 ProcessPropertyNotifications( bufferIndex );
898 //Process the RenderTasks; this creates the instructions for rendering the next frame.
899 //reset the update buffer index and make sure there is enough room in the instruction container
900 mImpl->renderInstructions.ResetAndReserve( bufferIndex,
901 mImpl->taskList.GetTasks().Count() + mImpl->systemLevelTaskList.GetTasks().Count() );
903 if ( NULL != mImpl->root )
905 mImpl->renderTaskProcessor.Process( bufferIndex,
909 mImpl->renderInstructions );
911 // Process the system-level RenderTasks last
912 if ( NULL != mImpl->systemLevelRoot )
914 mImpl->renderTaskProcessor.Process( bufferIndex,
915 mImpl->systemLevelTaskList,
916 *mImpl->systemLevelRoot,
917 mImpl->systemLevelSortedLayers,
918 mImpl->renderInstructions );
923 // check the countdown and notify (note, at the moment this is only done for normal tasks, not for systemlevel tasks)
924 bool doRenderOnceNotify = false;
925 mImpl->renderTaskWaiting = false;
926 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
927 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(), endIter = tasks.End();
928 endIter != iter; ++iter )
930 RenderTask& renderTask(*(*iter));
932 renderTask.UpdateState();
934 if( renderTask.IsWaitingToRender() &&
935 renderTask.ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
937 mImpl->renderTaskWaiting = true; // keep update/render threads alive
940 if( renderTask.HasRendered() )
942 doRenderOnceNotify = true;
946 if( doRenderOnceNotify )
948 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
949 mImpl->notificationManager.QueueCompleteNotification( mImpl->taskList.GetCompleteNotificationInterface() );
952 // Macro is undefined in release build.
953 SNAPSHOT_NODE_LOGGING;
955 // A ResetProperties() may be required in the next frame
956 mImpl->previousUpdateScene = updateScene;
958 // Check whether further updates are required
959 unsigned int keepUpdating = KeepUpdatingCheck( elapsedSeconds );
961 // tell the update manager that we're done so the queue can be given to event thread
962 mImpl->notificationManager.UpdateCompleted();
964 // The update has finished; swap the double-buffering indices
965 mSceneGraphBuffers.Swap();
970 unsigned int UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
972 // Update the duration set via Stage::KeepRendering()
973 if ( mImpl->keepRenderingSeconds > 0.0f )
975 mImpl->keepRenderingSeconds -= elapsedSeconds;
978 unsigned int keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
980 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
981 // Keep updating until no messages are received and no animations are running.
982 // If an animation has just finished, update at least once more for Discard end-actions.
983 // No need to check for renderQueue as there is always a render after update and if that
984 // render needs another update it will tell the adaptor to call update again
986 if ( mImpl->keepRenderingSeconds > 0.0f )
988 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
991 if ( IsAnimationRunning() ||
992 mImpl->animationFinishedDuringUpdate )
994 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
997 if ( mImpl->renderTaskWaiting )
999 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
1002 return keepUpdatingRequest;
1005 void UpdateManager::SetBackgroundColor( const Vector4& color )
1007 typedef MessageValue1< RenderManager, Vector4 > DerivedType;
1009 // Reserve some memory inside the render queue
1010 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1012 // Construct message in the render queue memory; note that delete should not be called on the return value
1013 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
1016 void UpdateManager::SetDefaultSurfaceRect( const Rect<int>& rect )
1018 typedef MessageValue1< RenderManager, Rect<int> > DerivedType;
1020 // Reserve some memory inside the render queue
1021 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1023 // Construct message in the render queue memory; note that delete should not be called on the return value
1024 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1027 void UpdateManager::KeepRendering( float durationSeconds )
1029 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1032 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, bool systemLevel )
1036 // just copy the vector of pointers
1037 mImpl->sortedLayers = layers;
1041 mImpl->systemLevelSortedLayers = layers;
1045 void UpdateManager::SetDepthIndices( NodeDepths* nodeDepths )
1049 // note,this vector is already in depth order. It could be used as-is to
1050 // remove sorting in update algorithm. However, it lacks layer boundary markers.
1051 for( std::vector<NodeDepthPair>::iterator iter = nodeDepths->nodeDepths.begin(),
1052 end = nodeDepths->nodeDepths.end() ;
1053 iter != end ; ++iter )
1055 iter->node->SetDepthIndex( iter->sortedDepth );
1060 void UpdateManager::AddSampler( Render::Sampler* sampler )
1062 // Message has ownership of Sampler while in transit from update to render
1063 typedef MessageValue1< RenderManager, OwnerPointer< Render::Sampler > > DerivedType;
1065 // Reserve some memory inside the render queue
1066 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1068 // Construct message in the render queue memory; note that delete should not be called on the return value
1069 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddSampler, sampler );
1072 void UpdateManager::RemoveSampler( Render::Sampler* sampler )
1074 typedef MessageValue1< RenderManager, Render::Sampler* > DerivedType;
1076 // Reserve some memory inside the render queue
1077 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1079 // Construct message in the render queue memory; note that delete should not be called on the return value
1080 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveSampler, sampler );
1083 void UpdateManager::SetFilterMode( Render::Sampler* sampler, unsigned int minFilterMode, unsigned int magFilterMode )
1085 typedef MessageValue3< RenderManager, Render::Sampler*, unsigned int, unsigned int > DerivedType;
1087 // Reserve some memory inside the render queue
1088 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1090 // Construct message in the render queue memory; note that delete should not be called on the return value
1091 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetFilterMode, sampler, minFilterMode, magFilterMode );
1094 void UpdateManager::SetWrapMode( Render::Sampler* sampler, unsigned int rWrapMode, unsigned int sWrapMode, unsigned int tWrapMode )
1096 typedef MessageValue4< RenderManager, Render::Sampler*, unsigned int, unsigned int, unsigned int > DerivedType;
1098 // Reserve some memory inside the render queue
1099 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1101 // Construct message in the render queue memory; note that delete should not be called on the return value
1102 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetWrapMode, sampler, rWrapMode, sWrapMode, tWrapMode );
1105 void UpdateManager::AddPropertyBuffer( Render::PropertyBuffer* propertyBuffer )
1107 // Message has ownership of format while in transit from update -> render
1108 typedef MessageValue1< RenderManager, OwnerPointer< Render::PropertyBuffer > > DerivedType;
1110 // Reserve some memory inside the render queue
1111 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1113 // Construct message in the render queue memory; note that delete should not be called on the return value
1114 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddPropertyBuffer, propertyBuffer );
1117 void UpdateManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer )
1119 typedef MessageValue1< RenderManager, Render::PropertyBuffer* > DerivedType;
1121 // Reserve some memory inside the render queue
1122 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1124 // Construct message in the render queue memory; note that delete should not be called on the return value
1125 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemovePropertyBuffer, propertyBuffer );
1128 void UpdateManager::SetPropertyBufferFormat(Render::PropertyBuffer* propertyBuffer, Render::PropertyBuffer::Format* format )
1130 // Message has ownership of format while in transit from update -> render
1131 typedef MessageValue2< RenderManager, Render::PropertyBuffer*, OwnerPointer< Render::PropertyBuffer::Format > > DerivedType;
1133 // Reserve some memory inside the render queue
1134 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1136 // Construct message in the render queue memory; note that delete should not be called on the return value
1137 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferFormat, propertyBuffer, format );
1140 void UpdateManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffer, Dali::Vector<char>* data, size_t size )
1142 // Message has ownership of format while in transit from update -> render
1143 typedef MessageValue3< RenderManager, Render::PropertyBuffer*, OwnerPointer< Dali::Vector<char> >, size_t > DerivedType;
1145 // Reserve some memory inside the render queue
1146 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1148 // Construct message in the render queue memory; note that delete should not be called on the return value
1149 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferData, propertyBuffer, data, size );
1152 void UpdateManager::AddGeometry( Render::Geometry* geometry )
1154 // Message has ownership of format while in transit from update -> render
1155 typedef MessageValue1< RenderManager, OwnerPointer< Render::Geometry > > DerivedType;
1157 // Reserve some memory inside the render queue
1158 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1160 // Construct message in the render queue memory; note that delete should not be called on the return value
1161 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddGeometry, geometry );
1164 void UpdateManager::RemoveGeometry( Render::Geometry* geometry )
1166 typedef MessageValue1< RenderManager, Render::Geometry* > DerivedType;
1168 // Reserve some memory inside the render queue
1169 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1171 // Construct message in the render queue memory; note that delete should not be called on the return value
1172 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveGeometry, geometry );
1175 void UpdateManager::SetGeometryType( Render::Geometry* geometry, unsigned int geometryType )
1177 typedef MessageValue2< RenderManager, Render::Geometry*, unsigned int > DerivedType;
1179 // Reserve some memory inside the render queue
1180 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1182 // Construct message in the render queue memory; note that delete should not be called on the return value
1183 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetGeometryType, geometry, geometryType );
1186 void UpdateManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector<unsigned short>& indices )
1188 typedef IndexBufferMessage< RenderManager > DerivedType;
1190 // Reserve some memory inside the render queue
1191 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1193 // Construct message in the render queue memory; note that delete should not be called on the return value
1194 new (slot) DerivedType( &mImpl->renderManager, geometry, indices );
1197 void UpdateManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1199 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1201 // Reserve some memory inside the render queue
1202 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1204 // Construct message in the render queue memory; note that delete should not be called on the return value
1205 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveVertexBuffer, geometry, propertyBuffer );
1208 void UpdateManager::AddVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1210 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1212 // Reserve some memory inside the render queue
1213 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1215 // Construct message in the render queue memory; note that delete should not be called on the return value
1216 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddVertexBuffer, geometry, propertyBuffer );
1219 void UpdateManager::AddTexture( Render::Texture* texture )
1221 // Message has ownership of Texture while in transit from update -> render
1222 typedef MessageValue1< RenderManager, OwnerPointer< Render::Texture > > DerivedType;
1224 // Reserve some memory inside the render queue
1225 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1227 // Construct message in the render queue memory; note that delete should not be called on the return value
1228 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddTexture, texture );
1231 void UpdateManager::RemoveTexture( Render::Texture* texture)
1233 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1235 // Reserve some memory inside the render queue
1236 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1238 // Construct message in the render queue memory; note that delete should not be called on the return value
1239 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveTexture, texture );
1242 void UpdateManager::UploadTexture( Render::Texture* texture, PixelDataPtr pixelData, const Texture::UploadParams& params )
1244 typedef MessageValue3< RenderManager, Render::Texture*, PixelDataPtr, Texture::UploadParams > DerivedType;
1246 // Reserve some memory inside the message queue
1247 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1249 // Construct message in the message queue memory; note that delete should not be called on the return value
1250 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::UploadTexture, texture, pixelData, params );
1253 void UpdateManager::GenerateMipmaps( Render::Texture* texture )
1255 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1257 // Reserve some memory inside the render queue
1258 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1260 // Construct message in the render queue memory; note that delete should not be called on the return value
1261 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::GenerateMipmaps, texture );
1264 void UpdateManager::AddFrameBuffer( Render::FrameBuffer* frameBuffer )
1266 typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType;
1268 // Reserve some memory inside the render queue
1269 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1271 // Construct message in the render queue memory; note that delete should not be called on the return value
1272 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddFrameBuffer, frameBuffer );
1275 void UpdateManager::RemoveFrameBuffer( Render::FrameBuffer* frameBuffer)
1277 typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType;
1279 // Reserve some memory inside the render queue
1280 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1282 // Construct message in the render queue memory; note that delete should not be called on the return value
1283 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveFrameBuffer, frameBuffer );
1286 void UpdateManager::AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, unsigned int mipmapLevel, unsigned int layer )
1288 typedef MessageValue4< RenderManager, Render::FrameBuffer*, Render::Texture*, unsigned int, unsigned int > DerivedType;
1290 // Reserve some memory inside the render queue
1291 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1293 // Construct message in the render queue memory; note that delete should not be called on the return value
1294 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AttachColorTextureToFrameBuffer, frameBuffer, texture, mipmapLevel, layer );
1297 } // namespace SceneGraph
1299 } // namespace Internal