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>
38 #include <dali/internal/event/animation/animation-playlist.h>
40 #include <dali/internal/update/animation/scene-graph-animator.h>
41 #include <dali/internal/update/animation/scene-graph-animation.h>
42 #include <dali/internal/update/common/discard-queue.h>
43 #include <dali/internal/update/common/scene-graph-buffers.h>
44 #include <dali/internal/update/controllers/render-message-dispatcher.h>
45 #include <dali/internal/update/controllers/scene-controller-impl.h>
46 #include <dali/internal/update/gestures/scene-graph-pan-gesture.h>
47 #include <dali/internal/update/manager/render-task-processor.h>
48 #include <dali/internal/update/manager/sorted-layers.h>
49 #include <dali/internal/update/manager/update-algorithms.h>
50 #include <dali/internal/update/manager/update-manager-debug.h>
51 #include <dali/internal/update/manager/transform-manager.h>
52 #include <dali/internal/update/nodes/node.h>
53 #include <dali/internal/update/nodes/scene-graph-layer.h>
54 #include <dali/internal/update/queue/update-message-queue.h>
55 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
56 #include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
57 #include <dali/internal/update/render-tasks/scene-graph-camera.h>
59 #include <dali/internal/render/common/render-instruction-container.h>
60 #include <dali/internal/render/common/render-manager.h>
61 #include <dali/internal/render/queue/render-queue.h>
62 #include <dali/internal/render/shaders/scene-graph-shader.h>
64 // Un-comment to enable node tree debug logging
65 //#define NODE_TREE_LOGGING 1
67 #if ( defined( DEBUG_ENABLED ) && defined( NODE_TREE_LOGGING ) )
68 #define SNAPSHOT_NODE_LOGGING \
69 const int FRAME_COUNT_TRIGGER = 16;\
70 if( mImpl->frameCounter >= FRAME_COUNT_TRIGGER )\
72 if ( NULL != mImpl->root )\
74 mImpl->frameCounter = 0;\
75 PrintNodeTree( *mImpl->root, mSceneGraphBuffers.GetUpdateBufferIndex(), "" );\
78 mImpl->frameCounter++;
80 #define SNAPSHOT_NODE_LOGGING
83 #if defined(DEBUG_ENABLED)
84 extern Debug::Filter* gRenderTaskLogFilter;
88 using namespace Dali::Integration;
89 using Dali::Internal::Update::MessageQueue;
103 * Helper to reset animate-able objects to base values
104 * @param container to iterate over
105 * @param updateBufferIndex to use
108 inline void ResetToBaseValues( OwnerContainer<T*>& container, BufferIndex updateBufferIndex )
110 // Reset animatable properties to base values
111 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& animationPlaylist,
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 animationPlaylist( animationPlaylist ),
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. Although Nodes are pool allocated they contain heap allocated parts
225 // like custom properties, which get released here
226 Vector<Node*>::Iterator iter = nodes.Begin()+1;
227 Vector<Node*>::Iterator endIter = nodes.End();
228 for(;iter!=endIter;++iter)
230 (*iter)->OnDestroy();
234 // If there is root, reset it, otherwise do nothing as rendering was never started
239 Node::Delete( root );
243 if( systemLevelRoot )
245 systemLevelRoot->OnDestroy();
247 Node::Delete( systemLevelRoot );
248 systemLevelRoot = NULL;
251 delete sceneController;
254 SceneGraphBuffers sceneGraphBuffers; ///< Used to keep track of which buffers are being written or read
255 RenderMessageDispatcher renderMessageDispatcher; ///< Used for passing messages to the render-thread
256 NotificationManager& notificationManager; ///< Queues notification messages for the event-thread.
257 TransformManager transformManager; ///< Used to update the transformation matrices of the nodes
258 CompleteNotificationInterface& animationPlaylist; ///< Holds handles to all the animations
259 PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
260 ShaderSaver* shaderSaver; ///< Saves shader binaries.
261 DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
262 RenderController& renderController; ///< render controller
263 SceneControllerImpl* sceneController; ///< scene controller
264 RenderManager& renderManager; ///< This is responsible for rendering the results of each "update"
265 RenderQueue& renderQueue; ///< Used to queue messages for the next render
266 RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions
267 RenderTaskProcessor& renderTaskProcessor; ///< Handles RenderTasks and RenderInstrucitons
269 Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
271 RenderTaskList taskList; ///< The list of scene graph render-tasks
272 RenderTaskList systemLevelTaskList; ///< Separate render-tasks for system-level content
274 Layer* root; ///< The root node (root is a layer)
275 Layer* systemLevelRoot; ///< A separate root-node for system-level content
277 Vector<Node*> nodes; ///< A container of all instantiated nodes
279 SortedLayerPointers sortedLayers; ///< A container of Layer pointers sorted by depth
280 SortedLayerPointers systemLevelSortedLayers; ///< A separate container of system-level Layers
282 CameraOwner cameras; ///< A container of cameras
283 CustomObjectOwner customObjects; ///< A container of owned objects (with custom properties)
285 AnimationContainer animations; ///< A container of owned animations
286 PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
288 RendererOwner renderers; ///< A container of owned renderers
289 TextureSetOwner textureSets; ///< A container of owned texture sets
290 ShaderOwner shaders; ///< A container of owned shaders
291 OwnerPointer<PanGesture> panGestureProcessor; ///< Owned pan gesture processor; it lives for the lifecycle of UpdateManager
293 MessageQueue messageQueue; ///< The messages queued from the event-thread
294 ShaderDataBinaryQueue renderCompiledShaders; ///< Shaders compiled on Render thread are inserted here for update thread to pass on to event thread.
295 ShaderDataBinaryQueue updateCompiledShaders; ///< Shaders to be sent from Update to Event
296 Mutex compiledShaderMutex; ///< lock to ensure no corruption on the renderCompiledShaders
298 float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
299 int nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
300 int frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
302 bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
303 bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
304 bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
308 Impl( const Impl& ); ///< Undefined
309 Impl& operator=( const Impl& ); ///< Undefined
312 UpdateManager::UpdateManager( NotificationManager& notificationManager,
313 CompleteNotificationInterface& animationFinishedNotifier,
314 PropertyNotifier& propertyNotifier,
315 DiscardQueue& discardQueue,
316 RenderController& controller,
317 RenderManager& renderManager,
318 RenderQueue& renderQueue,
319 RenderTaskProcessor& renderTaskProcessor )
322 mImpl = new Impl( notificationManager,
323 animationFinishedNotifier,
330 renderTaskProcessor );
334 UpdateManager::~UpdateManager()
339 void UpdateManager::InstallRoot( OwnerPointer<Layer>& layer, bool systemLevel )
341 DALI_ASSERT_DEBUG( layer->IsLayer() );
342 DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
346 DALI_ASSERT_DEBUG( mImpl->root == NULL && "Root Node already installed" );
347 mImpl->root = layer.Release();
348 mImpl->root->CreateTransform( &mImpl->transformManager );
349 mImpl->root->SetRoot(true);
353 DALI_ASSERT_DEBUG( mImpl->systemLevelRoot == NULL && "System-level Root Node already installed" );
354 mImpl->systemLevelRoot = layer.Release();
355 mImpl->systemLevelRoot->CreateTransform( &mImpl->transformManager );
356 mImpl->systemLevelRoot->SetRoot(true);
361 void UpdateManager::AddNode( OwnerPointer<Node>& node )
363 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
365 // Nodes must be sorted by pointer
366 Node* rawNode = node.Release();
367 Vector<Node*>::Iterator begin = mImpl->nodes.Begin();
368 for( Vector<Node*>::Iterator iter = mImpl->nodes.End()-1; iter >= begin; --iter )
370 if( rawNode > (*iter) )
372 mImpl->nodes.Insert((iter+1), rawNode );
373 rawNode->CreateTransform( &mImpl->transformManager );
379 void UpdateManager::ConnectNode( Node* parent, Node* node )
381 DALI_ASSERT_ALWAYS( NULL != parent );
382 DALI_ASSERT_ALWAYS( NULL != node );
383 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
385 parent->ConnectChild( node );
388 void UpdateManager::DisconnectNode( Node* node )
390 Node* parent = node->GetParent();
391 DALI_ASSERT_ALWAYS( NULL != parent );
392 parent->SetDirtyFlag( ChildDeletedFlag ); // make parent dirty so that render items dont get reused
394 parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node );
397 void UpdateManager::DestroyNode( Node* node )
399 DALI_ASSERT_ALWAYS( NULL != node );
400 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
402 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
403 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
404 for(;iter!=endIter;++iter)
408 mImpl->nodes.Erase(iter);
413 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
415 // Notify the Node about impending destruction
419 void UpdateManager::AddCamera( OwnerPointer< Camera >& camera )
421 mImpl->cameras.PushBack( camera.Release() ); // 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( OwnerPointer<PropertyOwner>& object )
432 mImpl->customObjects.PushBack( object.Release() );
435 void UpdateManager::RemoveObject( PropertyOwner* object )
437 mImpl->customObjects.EraseObject( object );
440 void UpdateManager::AddAnimation( OwnerPointer< SceneGraph::Animation >& animation )
442 mImpl->animations.PushBack( animation.Release() );
445 void UpdateManager::StopAnimation( Animation* animation )
447 DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
449 bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
451 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
454 void UpdateManager::RemoveAnimation( Animation* animation )
456 DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
458 animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
460 DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
463 bool UpdateManager::IsAnimationRunning() const
465 bool isRunning(false);
466 AnimationContainer& animations = mImpl->animations;
468 // Find any animation that isn't stopped or paused
470 const AnimationIter endIter = animations.End();
471 for ( AnimationIter iter = animations.Begin(); !isRunning && iter != endIter; ++iter )
473 const Animation::State state = (*iter)->GetState();
475 if (state != Animation::Stopped &&
476 state != Animation::Paused)
485 void UpdateManager::AddPropertyNotification( OwnerPointer< PropertyNotification >& propertyNotification )
487 mImpl->propertyNotifications.PushBack( propertyNotification.Release() );
490 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
492 mImpl->propertyNotifications.EraseObject( propertyNotification );
495 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
497 DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
498 propertyNotification->SetNotifyMode( notifyMode );
501 void UpdateManager::AddShader( OwnerPointer< Shader >& shader )
503 mImpl->shaders.PushBack( shader.Release() );
506 void UpdateManager::RemoveShader( Shader* shader )
508 // Find the shader and destroy it
509 EraseUsingDiscardQueue( mImpl->shaders, shader, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
512 void UpdateManager::SetShaderProgram( Shader* shader,
513 Internal::ShaderDataPtr shaderData, bool modifiesGeometry )
518 typedef MessageValue3< Shader, Internal::ShaderDataPtr, ProgramCache*, bool> DerivedType;
520 // Reserve some memory inside the render queue
521 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
523 // Construct message in the render queue memory; note that delete should not be called on the return value
524 new (slot) DerivedType( shader, &Shader::SetProgram, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
528 void UpdateManager::SaveBinary( Internal::ShaderDataPtr shaderData )
530 DALI_ASSERT_DEBUG( shaderData && "No NULL shader data pointers please." );
531 DALI_ASSERT_DEBUG( shaderData->GetBufferSize() > 0 && "Shader binary empty so nothing to save." );
533 // lock as update might be sending previously compiled shaders to event thread
534 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
535 mImpl->renderCompiledShaders.push_back( shaderData );
539 void UpdateManager::SetShaderSaver( ShaderSaver& upstream )
541 mImpl->shaderSaver = &upstream;
544 void UpdateManager::AddRenderer( OwnerPointer< Renderer >& renderer )
546 renderer->ConnectToSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
547 mImpl->renderers.PushBack( renderer.Release() );
550 void UpdateManager::RemoveRenderer( Renderer* renderer )
552 // Find the renderer and destroy it
553 EraseUsingDiscardQueue( mImpl->renderers, renderer, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
554 // Need to remove the render object as well
555 renderer->DisconnectFromSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
558 void UpdateManager::SetPanGestureProcessor( PanGesture* panGestureProcessor )
560 DALI_ASSERT_DEBUG( NULL != panGestureProcessor );
562 mImpl->panGestureProcessor = panGestureProcessor;
565 void UpdateManager::AddTextureSet( OwnerPointer< TextureSet >& textureSet )
567 mImpl->textureSets.PushBack( textureSet.Release() );
570 void UpdateManager::RemoveTextureSet( TextureSet* textureSet )
572 mImpl->textureSets.EraseObject( textureSet );
575 RenderTaskList* UpdateManager::GetRenderTaskList( bool systemLevel )
579 // copy the list, this is only likely to happen once in application life cycle
580 return &(mImpl->taskList);
584 // copy the list, this is only likely to happen once in application life cycle
585 return &(mImpl->systemLevelTaskList);
589 unsigned int* UpdateManager::ReserveMessageSlot( std::size_t size, bool updateScene )
591 return mImpl->messageQueue.ReserveMessageSlot( size, updateScene );
594 void UpdateManager::EventProcessingStarted()
596 mImpl->messageQueue.EventProcessingStarted();
599 bool UpdateManager::FlushQueue()
601 return mImpl->messageQueue.FlushQueue();
604 void UpdateManager::ResetProperties( BufferIndex bufferIndex )
606 // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
607 mImpl->animationFinishedDuringUpdate = false;
609 // Animated properties have to be reset to their original value each frame
611 // Reset root properties
614 mImpl->root->ResetToBaseValues( bufferIndex );
616 if ( mImpl->systemLevelRoot )
618 mImpl->systemLevelRoot->ResetToBaseValues( bufferIndex );
621 // Reset all the nodes
622 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
623 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
624 for( ;iter != endIter; ++iter )
626 (*iter)->ResetToBaseValues( bufferIndex );
629 // Reset system-level render-task list properties to base values
630 ResetToBaseValues( mImpl->systemLevelTaskList.GetTasks(), bufferIndex );
632 // Reset render-task list properties to base values.
633 ResetToBaseValues( mImpl->taskList.GetTasks(), bufferIndex );
635 // Reset custom object properties to base values
636 ResetToBaseValues( mImpl->customObjects, bufferIndex );
638 // Reset animatable renderer properties to base values
639 ResetToBaseValues( mImpl->renderers, bufferIndex );
641 // Reset animatable shader properties to base values
642 ResetToBaseValues( mImpl->shaders, bufferIndex );
645 bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds )
647 bool gestureUpdated( false );
649 if( mImpl->panGestureProcessor )
651 // gesture processor only supports default properties
652 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
653 gestureUpdated |= mImpl->panGestureProcessor->UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
656 return gestureUpdated;
659 void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
661 AnimationContainer &animations = mImpl->animations;
662 AnimationIter iter = animations.Begin();
663 bool animationLooped = false;
665 while ( iter != animations.End() )
667 Animation* animation = *iter;
668 bool finished = false;
670 bool progressMarkerReached = false;
671 animation->Update( bufferIndex, elapsedSeconds, looped, finished, progressMarkerReached );
673 if ( progressMarkerReached )
675 mImpl->notificationManager.QueueMessage( Internal::NotifyProgressReachedMessage( mImpl->animationPlaylist, animation ) );
678 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
679 animationLooped = animationLooped || looped;
681 // Remove animations that had been destroyed but were still waiting for an update
682 if (animation->GetState() == Animation::Destroyed)
684 iter = animations.Erase(iter);
692 // queue the notification on finished or looped (to update loop count)
693 if ( mImpl->animationFinishedDuringUpdate || animationLooped )
695 // The application should be notified by NotificationManager, in another thread
696 mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationPlaylist );
700 void UpdateManager::ConstrainCustomObjects( BufferIndex bufferIndex )
702 //Constrain custom objects (in construction order)
703 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
704 const OwnerContainer< PropertyOwner* >::Iterator endIter = customObjects.End();
705 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); endIter != iter; ++iter )
707 PropertyOwner& object = **iter;
708 ConstrainPropertyOwner( object, bufferIndex );
712 void UpdateManager::ConstrainRenderTasks( BufferIndex bufferIndex )
714 // Constrain system-level render-tasks
715 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
716 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter )
718 RenderTask& task = **iter;
719 ConstrainPropertyOwner( task, bufferIndex );
722 // Constrain render-tasks
723 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
724 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter )
726 RenderTask& task = **iter;
727 ConstrainPropertyOwner( task, bufferIndex );
731 void UpdateManager::ConstrainShaders( BufferIndex bufferIndex )
733 // constrain shaders... (in construction order)
734 ShaderOwner& shaders = mImpl->shaders;
735 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
737 Shader& shader = **iter;
738 ConstrainPropertyOwner( shader, bufferIndex );
742 void UpdateManager::ProcessPropertyNotifications( BufferIndex bufferIndex )
744 PropertyNotificationContainer ¬ifications = mImpl->propertyNotifications;
745 PropertyNotificationIter iter = notifications.Begin();
747 while ( iter != notifications.End() )
749 PropertyNotification* notification = *iter;
750 bool valid = notification->Check( bufferIndex );
753 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
759 void UpdateManager::ForwardCompiledShadersToEventThread()
761 DALI_ASSERT_DEBUG( (mImpl->shaderSaver != 0) && "shaderSaver should be wired-up during startup." );
762 if( mImpl->shaderSaver )
764 // lock and swap the queues
766 // render might be attempting to send us more binaries at the same time
767 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
768 mImpl->renderCompiledShaders.swap( mImpl->updateCompiledShaders );
771 if( mImpl->updateCompiledShaders.size() > 0 )
773 ShaderSaver& factory = *mImpl->shaderSaver;
774 ShaderDataBinaryQueue::iterator i = mImpl->updateCompiledShaders.begin();
775 ShaderDataBinaryQueue::iterator end = mImpl->updateCompiledShaders.end();
776 for( ; i != end; ++i )
778 mImpl->notificationManager.QueueMessage( ShaderCompiledMessage( factory, *i ) );
780 // we don't need them in update anymore
781 mImpl->updateCompiledShaders.clear();
786 void UpdateManager::UpdateRenderers( BufferIndex bufferIndex )
788 const unsigned int rendererCount = mImpl->renderers.Count();
789 for( unsigned int i = 0; i < rendererCount; ++i )
792 ConstrainPropertyOwner( *mImpl->renderers[i], bufferIndex );
794 mImpl->renderers[i]->PrepareRender( bufferIndex );
798 void UpdateManager::UpdateNodes( BufferIndex bufferIndex )
800 mImpl->nodeDirtyFlags = NothingFlag;
807 // Prepare resources, update shaders, for each node
808 // And add the renderers to the sorted layers. Start from root, which is also a layer
809 mImpl->nodeDirtyFlags = UpdateNodeTree( *( mImpl->root ),
811 mImpl->renderQueue );
813 if ( mImpl->systemLevelRoot )
815 mImpl->nodeDirtyFlags |= UpdateNodeTree( *( mImpl->systemLevelRoot ),
817 mImpl->renderQueue );
821 unsigned int UpdateManager::Update( float elapsedSeconds,
822 unsigned int lastVSyncTimeMilliseconds,
823 unsigned int nextVSyncTimeMilliseconds )
825 const BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
827 //Clear nodes/resources which were previously discarded
828 mImpl->discardQueue.Clear( bufferIndex );
830 //Process Touches & Gestures
831 const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
833 bool updateScene = // The scene-graph requires an update if..
834 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
835 IsAnimationRunning() || // ..at least one animation is running OR
836 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
837 gestureUpdated; // ..a gesture property was updated
840 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
841 // values if the scene was updated in the previous frame.
842 if( updateScene || mImpl->previousUpdateScene )
844 //Reset properties from the previous update
845 ResetProperties( bufferIndex );
846 mImpl->transformManager.ResetToBaseValue();
849 // Process the queued scene messages. Note, MessageQueue::FlushQueue may be called
850 // between calling IsSceneUpdateRequired() above and here, so updateScene should
852 updateScene |= mImpl->messageQueue.ProcessMessages( bufferIndex );
854 //Forward compiled shader programs to event thread for saving
855 ForwardCompiledShadersToEventThread();
857 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
858 // renderer lists if the scene was updated in the previous frame.
859 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
860 if( updateScene || mImpl->previousUpdateScene )
863 Animate( bufferIndex, elapsedSeconds );
865 //Constraint custom objects
866 ConstrainCustomObjects( bufferIndex );
868 //Clear the lists of renderers from the previous update
869 for( size_t i(0); i<mImpl->sortedLayers.size(); ++i )
871 mImpl->sortedLayers[i]->ClearRenderables();
874 for( size_t i(0); i<mImpl->systemLevelSortedLayers.size(); ++i )
876 mImpl->systemLevelSortedLayers[i]->ClearRenderables();
879 //Update node hierarchy, apply constraints and perform sorting / culling.
880 //This will populate each Layer with a list of renderers which are ready.
881 UpdateNodes( bufferIndex );
883 //Apply constraints to RenderTasks, shaders
884 ConstrainRenderTasks( bufferIndex );
885 ConstrainShaders( bufferIndex );
887 //Update renderers and apply constraints
888 UpdateRenderers( bufferIndex );
890 //Update the trnasformations of all the nodes
891 mImpl->transformManager.Update();
893 //Process Property Notifications
894 ProcessPropertyNotifications( bufferIndex );
896 //Process the RenderTasks; this creates the instructions for rendering the next frame.
897 //reset the update buffer index and make sure there is enough room in the instruction container
898 mImpl->renderInstructions.ResetAndReserve( bufferIndex,
899 mImpl->taskList.GetTasks().Count() + mImpl->systemLevelTaskList.GetTasks().Count() );
901 if ( NULL != mImpl->root )
903 mImpl->renderTaskProcessor.Process( bufferIndex,
907 mImpl->renderInstructions );
909 // Process the system-level RenderTasks last
910 if ( NULL != mImpl->systemLevelRoot )
912 mImpl->renderTaskProcessor.Process( bufferIndex,
913 mImpl->systemLevelTaskList,
914 *mImpl->systemLevelRoot,
915 mImpl->systemLevelSortedLayers,
916 mImpl->renderInstructions );
921 // check the countdown and notify (note, at the moment this is only done for normal tasks, not for systemlevel tasks)
922 bool doRenderOnceNotify = false;
923 mImpl->renderTaskWaiting = false;
924 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
925 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(), endIter = tasks.End();
926 endIter != iter; ++iter )
928 RenderTask& renderTask(*(*iter));
930 renderTask.UpdateState();
932 if( renderTask.IsWaitingToRender() &&
933 renderTask.ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
935 mImpl->renderTaskWaiting = true; // keep update/render threads alive
938 if( renderTask.HasRendered() )
940 doRenderOnceNotify = true;
944 if( doRenderOnceNotify )
946 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
947 mImpl->notificationManager.QueueCompleteNotification( mImpl->taskList.GetCompleteNotificationInterface() );
950 // Macro is undefined in release build.
951 SNAPSHOT_NODE_LOGGING;
953 // A ResetProperties() may be required in the next frame
954 mImpl->previousUpdateScene = updateScene;
956 // Check whether further updates are required
957 unsigned int keepUpdating = KeepUpdatingCheck( elapsedSeconds );
959 // tell the update manager that we're done so the queue can be given to event thread
960 mImpl->notificationManager.UpdateCompleted();
962 // The update has finished; swap the double-buffering indices
963 mSceneGraphBuffers.Swap();
968 unsigned int UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
970 // Update the duration set via Stage::KeepRendering()
971 if ( mImpl->keepRenderingSeconds > 0.0f )
973 mImpl->keepRenderingSeconds -= elapsedSeconds;
976 unsigned int keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
978 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
979 // Keep updating until no messages are received and no animations are running.
980 // If an animation has just finished, update at least once more for Discard end-actions.
981 // No need to check for renderQueue as there is always a render after update and if that
982 // render needs another update it will tell the adaptor to call update again
984 if ( mImpl->keepRenderingSeconds > 0.0f )
986 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
989 if ( IsAnimationRunning() ||
990 mImpl->animationFinishedDuringUpdate )
992 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
995 if ( mImpl->renderTaskWaiting )
997 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
1000 return keepUpdatingRequest;
1003 void UpdateManager::SetBackgroundColor( const Vector4& color )
1005 typedef MessageValue1< RenderManager, Vector4 > DerivedType;
1007 // Reserve some memory inside the render queue
1008 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1010 // Construct message in the render queue memory; note that delete should not be called on the return value
1011 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
1014 void UpdateManager::SetDefaultSurfaceRect( const Rect<int>& rect )
1016 typedef MessageValue1< RenderManager, Rect<int> > DerivedType;
1018 // Reserve some memory inside the render queue
1019 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1021 // Construct message in the render queue memory; note that delete should not be called on the return value
1022 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1025 void UpdateManager::KeepRendering( float durationSeconds )
1027 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1030 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, bool systemLevel )
1034 // just copy the vector of pointers
1035 mImpl->sortedLayers = layers;
1039 mImpl->systemLevelSortedLayers = layers;
1043 void UpdateManager::SetDepthIndices( OwnerPointer< NodeDepths >& nodeDepths )
1045 // note,this vector is already in depth order. It could be used as-is to
1046 // remove sorting in update algorithm. However, it lacks layer boundary markers.
1047 for( std::vector<NodeDepthPair>::iterator iter = nodeDepths->nodeDepths.begin(),
1048 end = nodeDepths->nodeDepths.end() ;
1049 iter != end ; ++iter )
1051 iter->node->SetDepthIndex( iter->sortedDepth );
1055 void UpdateManager::AddSampler( OwnerPointer< Render::Sampler >& sampler )
1057 // Message has ownership of Sampler while in transit from update to render
1058 typedef MessageValue1< RenderManager, OwnerPointer< Render::Sampler > > DerivedType;
1060 // Reserve some memory inside the render queue
1061 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1063 // Construct message in the render queue memory; note that delete should not be called on the return value
1064 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddSampler, sampler );
1067 void UpdateManager::RemoveSampler( Render::Sampler* sampler )
1069 typedef MessageValue1< RenderManager, Render::Sampler* > DerivedType;
1071 // Reserve some memory inside the render queue
1072 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1074 // Construct message in the render queue memory; note that delete should not be called on the return value
1075 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveSampler, sampler );
1078 void UpdateManager::SetFilterMode( Render::Sampler* sampler, unsigned int minFilterMode, unsigned int magFilterMode )
1080 typedef MessageValue3< RenderManager, Render::Sampler*, unsigned int, unsigned int > DerivedType;
1082 // Reserve some memory inside the render queue
1083 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1085 // Construct message in the render queue memory; note that delete should not be called on the return value
1086 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetFilterMode, sampler, minFilterMode, magFilterMode );
1089 void UpdateManager::SetWrapMode( Render::Sampler* sampler, unsigned int rWrapMode, unsigned int sWrapMode, unsigned int tWrapMode )
1091 typedef MessageValue4< RenderManager, Render::Sampler*, unsigned int, unsigned int, unsigned int > DerivedType;
1093 // Reserve some memory inside the render queue
1094 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1096 // Construct message in the render queue memory; note that delete should not be called on the return value
1097 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetWrapMode, sampler, rWrapMode, sWrapMode, tWrapMode );
1100 void UpdateManager::AddPropertyBuffer( OwnerPointer< Render::PropertyBuffer >& propertyBuffer )
1102 // Message has ownership of format while in transit from update -> render
1103 typedef MessageValue1< RenderManager, OwnerPointer< Render::PropertyBuffer > > DerivedType;
1105 // Reserve some memory inside the render queue
1106 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1108 // Construct message in the render queue memory; note that delete should not be called on the return value
1109 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddPropertyBuffer, propertyBuffer );
1112 void UpdateManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer )
1114 typedef MessageValue1< RenderManager, Render::PropertyBuffer* > DerivedType;
1116 // Reserve some memory inside the render queue
1117 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1119 // Construct message in the render queue memory; note that delete should not be called on the return value
1120 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemovePropertyBuffer, propertyBuffer );
1123 void UpdateManager::SetPropertyBufferFormat( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Render::PropertyBuffer::Format>& format )
1125 // Message has ownership of format while in transit from update -> render
1126 typedef MessageValue2< RenderManager, Render::PropertyBuffer*, OwnerPointer< Render::PropertyBuffer::Format > > DerivedType;
1128 // Reserve some memory inside the render queue
1129 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1131 // Construct message in the render queue memory; note that delete should not be called on the return value
1132 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferFormat, propertyBuffer, format );
1135 void UpdateManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Vector<char> >& data, size_t size )
1137 // Message has ownership of format while in transit from update -> render
1138 typedef MessageValue3< RenderManager, Render::PropertyBuffer*, OwnerPointer< Dali::Vector<char> >, size_t > DerivedType;
1140 // Reserve some memory inside the render queue
1141 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1143 // Construct message in the render queue memory; note that delete should not be called on the return value
1144 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferData, propertyBuffer, data, size );
1147 void UpdateManager::AddGeometry( OwnerPointer< Render::Geometry >& geometry )
1149 // Message has ownership of format while in transit from update -> render
1150 typedef MessageValue1< RenderManager, OwnerPointer< Render::Geometry > > DerivedType;
1152 // Reserve some memory inside the render queue
1153 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1155 // Construct message in the render queue memory; note that delete should not be called on the return value
1156 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddGeometry, geometry );
1159 void UpdateManager::RemoveGeometry( Render::Geometry* geometry )
1161 typedef MessageValue1< RenderManager, Render::Geometry* > DerivedType;
1163 // Reserve some memory inside the render queue
1164 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1166 // Construct message in the render queue memory; note that delete should not be called on the return value
1167 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveGeometry, geometry );
1170 void UpdateManager::SetGeometryType( Render::Geometry* geometry, unsigned int geometryType )
1172 typedef MessageValue2< RenderManager, Render::Geometry*, unsigned int > DerivedType;
1174 // Reserve some memory inside the render queue
1175 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1177 // Construct message in the render queue memory; note that delete should not be called on the return value
1178 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetGeometryType, geometry, geometryType );
1181 void UpdateManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector<unsigned short>& indices )
1183 typedef IndexBufferMessage< RenderManager > DerivedType;
1185 // Reserve some memory inside the render queue
1186 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1188 // Construct message in the render queue memory; note that delete should not be called on the return value
1189 new (slot) DerivedType( &mImpl->renderManager, geometry, indices );
1192 void UpdateManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1194 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1196 // Reserve some memory inside the render queue
1197 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1199 // Construct message in the render queue memory; note that delete should not be called on the return value
1200 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveVertexBuffer, geometry, propertyBuffer );
1203 void UpdateManager::AttachVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1205 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1207 // Reserve some memory inside the render queue
1208 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1210 // Construct message in the render queue memory; note that delete should not be called on the return value
1211 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AttachVertexBuffer, geometry, propertyBuffer );
1214 void UpdateManager::AddTexture( OwnerPointer< Render::Texture >& texture )
1216 // Message has ownership of Texture while in transit from update -> render
1217 typedef MessageValue1< RenderManager, OwnerPointer< Render::Texture > > DerivedType;
1219 // Reserve some memory inside the render queue
1220 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1222 // Construct message in the render queue memory; note that delete should not be called on the return value
1223 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddTexture, texture );
1226 void UpdateManager::RemoveTexture( Render::Texture* texture)
1228 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1230 // Reserve some memory inside the render queue
1231 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1233 // Construct message in the render queue memory; note that delete should not be called on the return value
1234 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveTexture, texture );
1237 void UpdateManager::UploadTexture( Render::Texture* texture, PixelDataPtr pixelData, const Texture::UploadParams& params )
1239 typedef MessageValue3< RenderManager, Render::Texture*, PixelDataPtr, Texture::UploadParams > DerivedType;
1241 // Reserve some memory inside the message queue
1242 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1244 // Construct message in the message queue memory; note that delete should not be called on the return value
1245 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::UploadTexture, texture, pixelData, params );
1248 void UpdateManager::GenerateMipmaps( Render::Texture* texture )
1250 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1252 // Reserve some memory inside the render queue
1253 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1255 // Construct message in the render queue memory; note that delete should not be called on the return value
1256 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::GenerateMipmaps, texture );
1259 void UpdateManager::AddFrameBuffer( Render::FrameBuffer* frameBuffer )
1261 typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType;
1263 // Reserve some memory inside the render queue
1264 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1266 // Construct message in the render queue memory; note that delete should not be called on the return value
1267 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddFrameBuffer, frameBuffer );
1270 void UpdateManager::RemoveFrameBuffer( Render::FrameBuffer* frameBuffer)
1272 typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType;
1274 // Reserve some memory inside the render queue
1275 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1277 // Construct message in the render queue memory; note that delete should not be called on the return value
1278 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveFrameBuffer, frameBuffer );
1281 void UpdateManager::AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, unsigned int mipmapLevel, unsigned int layer )
1283 typedef MessageValue4< RenderManager, Render::FrameBuffer*, Render::Texture*, unsigned int, unsigned int > DerivedType;
1285 // Reserve some memory inside the render queue
1286 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1288 // Construct message in the render queue memory; note that delete should not be called on the return value
1289 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AttachColorTextureToFrameBuffer, frameBuffer, texture, mipmapLevel, layer );
1292 } // namespace SceneGraph
1294 } // namespace Internal