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 ),
202 renderersAdded( false )
204 sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue );
206 // create first 'dummy' node
212 // Disconnect render tasks from nodes, before destroying the nodes
213 RenderTaskList::RenderTaskContainer& tasks = taskList.GetTasks();
214 for (RenderTaskList::RenderTaskContainer::Iterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
216 (*iter)->SetSourceNode( NULL );
218 // ..repeat for system level RenderTasks
219 RenderTaskList::RenderTaskContainer& systemLevelTasks = systemLevelTaskList.GetTasks();
220 for (RenderTaskList::RenderTaskContainer::Iterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
222 (*iter)->SetSourceNode( NULL );
225 // UpdateManager owns the Nodes. Although Nodes are pool allocated they contain heap allocated parts
226 // like custom properties, which get released here
227 Vector<Node*>::Iterator iter = nodes.Begin()+1;
228 Vector<Node*>::Iterator endIter = nodes.End();
229 for(;iter!=endIter;++iter)
231 (*iter)->OnDestroy();
235 // If there is root, reset it, otherwise do nothing as rendering was never started
240 Node::Delete( root );
244 if( systemLevelRoot )
246 systemLevelRoot->OnDestroy();
248 Node::Delete( systemLevelRoot );
249 systemLevelRoot = NULL;
252 delete sceneController;
255 SceneGraphBuffers sceneGraphBuffers; ///< Used to keep track of which buffers are being written or read
256 RenderMessageDispatcher renderMessageDispatcher; ///< Used for passing messages to the render-thread
257 NotificationManager& notificationManager; ///< Queues notification messages for the event-thread.
258 TransformManager transformManager; ///< Used to update the transformation matrices of the nodes
259 CompleteNotificationInterface& animationPlaylist; ///< Holds handles to all the animations
260 PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
261 ShaderSaver* shaderSaver; ///< Saves shader binaries.
262 DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
263 RenderController& renderController; ///< render controller
264 SceneControllerImpl* sceneController; ///< scene controller
265 RenderManager& renderManager; ///< This is responsible for rendering the results of each "update"
266 RenderQueue& renderQueue; ///< Used to queue messages for the next render
267 RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions
268 RenderTaskProcessor& renderTaskProcessor; ///< Handles RenderTasks and RenderInstrucitons
270 Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
272 RenderTaskList taskList; ///< The list of scene graph render-tasks
273 RenderTaskList systemLevelTaskList; ///< Separate render-tasks for system-level content
275 Layer* root; ///< The root node (root is a layer)
276 Layer* systemLevelRoot; ///< A separate root-node for system-level content
278 Vector<Node*> nodes; ///< A container of all instantiated nodes
280 SortedLayerPointers sortedLayers; ///< A container of Layer pointers sorted by depth
281 SortedLayerPointers systemLevelSortedLayers; ///< A separate container of system-level Layers
283 CameraOwner cameras; ///< A container of cameras
284 CustomObjectOwner customObjects; ///< A container of owned objects (with custom properties)
286 AnimationContainer animations; ///< A container of owned animations
287 PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
289 RendererOwner renderers; ///< A container of owned renderers
290 TextureSetOwner textureSets; ///< A container of owned texture sets
291 ShaderOwner shaders; ///< A container of owned shaders
292 OwnerPointer<PanGesture> panGestureProcessor; ///< Owned pan gesture processor; it lives for the lifecycle of UpdateManager
294 MessageQueue messageQueue; ///< The messages queued from the event-thread
295 ShaderDataBinaryQueue renderCompiledShaders; ///< Shaders compiled on Render thread are inserted here for update thread to pass on to event thread.
296 ShaderDataBinaryQueue updateCompiledShaders; ///< Shaders to be sent from Update to Event
297 Mutex compiledShaderMutex; ///< lock to ensure no corruption on the renderCompiledShaders
299 float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
300 int nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
301 int frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
303 bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
304 bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
305 bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
306 bool renderersAdded; ///< Flag to keep track when renderers have been added to avoid unnecessary processing
310 Impl( const Impl& ); ///< Undefined
311 Impl& operator=( const Impl& ); ///< Undefined
314 UpdateManager::UpdateManager( NotificationManager& notificationManager,
315 CompleteNotificationInterface& animationFinishedNotifier,
316 PropertyNotifier& propertyNotifier,
317 DiscardQueue& discardQueue,
318 RenderController& controller,
319 RenderManager& renderManager,
320 RenderQueue& renderQueue,
321 RenderTaskProcessor& renderTaskProcessor )
324 mImpl = new Impl( notificationManager,
325 animationFinishedNotifier,
332 renderTaskProcessor );
336 UpdateManager::~UpdateManager()
341 void UpdateManager::InstallRoot( OwnerPointer<Layer>& layer, bool systemLevel )
343 DALI_ASSERT_DEBUG( layer->IsLayer() );
344 DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
348 DALI_ASSERT_DEBUG( mImpl->root == NULL && "Root Node already installed" );
349 mImpl->root = layer.Release();
350 mImpl->root->CreateTransform( &mImpl->transformManager );
351 mImpl->root->SetRoot(true);
355 DALI_ASSERT_DEBUG( mImpl->systemLevelRoot == NULL && "System-level Root Node already installed" );
356 mImpl->systemLevelRoot = layer.Release();
357 mImpl->systemLevelRoot->CreateTransform( &mImpl->transformManager );
358 mImpl->systemLevelRoot->SetRoot(true);
363 void UpdateManager::AddNode( OwnerPointer<Node>& node )
365 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
367 // Nodes must be sorted by pointer
368 Node* rawNode = node.Release();
369 Vector<Node*>::Iterator begin = mImpl->nodes.Begin();
370 for( Vector<Node*>::Iterator iter = mImpl->nodes.End()-1; iter >= begin; --iter )
372 if( rawNode > (*iter) )
374 mImpl->nodes.Insert((iter+1), rawNode );
375 rawNode->CreateTransform( &mImpl->transformManager );
381 void UpdateManager::ConnectNode( Node* parent, Node* node )
383 DALI_ASSERT_ALWAYS( NULL != parent );
384 DALI_ASSERT_ALWAYS( NULL != node );
385 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
387 parent->ConnectChild( node );
390 void UpdateManager::DisconnectNode( Node* node )
392 Node* parent = node->GetParent();
393 DALI_ASSERT_ALWAYS( NULL != parent );
394 parent->SetDirtyFlag( ChildDeletedFlag ); // make parent dirty so that render items dont get reused
396 parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node );
399 void UpdateManager::DestroyNode( Node* node )
401 DALI_ASSERT_ALWAYS( NULL != node );
402 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
404 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
405 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
406 for(;iter!=endIter;++iter)
410 mImpl->nodes.Erase(iter);
415 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
417 // Notify the Node about impending destruction
421 void UpdateManager::AddCamera( OwnerPointer< Camera >& camera )
423 mImpl->cameras.PushBack( camera.Release() ); // takes ownership
426 void UpdateManager::RemoveCamera( const Camera* camera )
428 // Find the camera and destroy it
429 EraseUsingDiscardQueue( mImpl->cameras, const_cast<Camera*>( camera ), mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
432 void UpdateManager::AddObject( OwnerPointer<PropertyOwner>& object )
434 mImpl->customObjects.PushBack( object.Release() );
437 void UpdateManager::RemoveObject( PropertyOwner* object )
439 mImpl->customObjects.EraseObject( object );
442 void UpdateManager::AddAnimation( OwnerPointer< SceneGraph::Animation >& animation )
444 mImpl->animations.PushBack( animation.Release() );
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( OwnerPointer< PropertyNotification >& propertyNotification )
489 mImpl->propertyNotifications.PushBack( propertyNotification.Release() );
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( OwnerPointer< Shader >& shader )
505 mImpl->shaders.PushBack( shader.Release() );
508 void UpdateManager::RemoveShader( Shader* shader )
510 // Find the shader and destroy it
511 EraseUsingDiscardQueue( mImpl->shaders, shader, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
514 void UpdateManager::SetShaderProgram( Shader* shader,
515 Internal::ShaderDataPtr shaderData, bool modifiesGeometry )
520 typedef MessageValue3< Shader, Internal::ShaderDataPtr, ProgramCache*, bool> DerivedType;
522 // Reserve some memory inside the render queue
523 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
525 // Construct message in the render queue memory; note that delete should not be called on the return value
526 new (slot) DerivedType( shader, &Shader::SetProgram, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
530 void UpdateManager::SaveBinary( Internal::ShaderDataPtr shaderData )
532 DALI_ASSERT_DEBUG( shaderData && "No NULL shader data pointers please." );
533 DALI_ASSERT_DEBUG( shaderData->GetBufferSize() > 0 && "Shader binary empty so nothing to save." );
535 // lock as update might be sending previously compiled shaders to event thread
536 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
537 mImpl->renderCompiledShaders.push_back( shaderData );
541 void UpdateManager::SetShaderSaver( ShaderSaver& upstream )
543 mImpl->shaderSaver = &upstream;
546 void UpdateManager::AddRenderer( OwnerPointer< Renderer >& renderer )
548 renderer->ConnectToSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
549 mImpl->renderers.PushBack( renderer.Release() );
550 mImpl->renderersAdded = true;
553 void UpdateManager::RemoveRenderer( Renderer* renderer )
555 // Find the renderer and destroy it
556 EraseUsingDiscardQueue( mImpl->renderers, renderer, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
557 // Need to remove the render object as well
558 renderer->DisconnectFromSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
561 void UpdateManager::SetPanGestureProcessor( PanGesture* panGestureProcessor )
563 DALI_ASSERT_DEBUG( NULL != panGestureProcessor );
565 mImpl->panGestureProcessor = panGestureProcessor;
568 void UpdateManager::AddTextureSet( OwnerPointer< TextureSet >& textureSet )
570 mImpl->textureSets.PushBack( textureSet.Release() );
573 void UpdateManager::RemoveTextureSet( TextureSet* textureSet )
575 mImpl->textureSets.EraseObject( textureSet );
578 RenderTaskList* UpdateManager::GetRenderTaskList( bool systemLevel )
582 // copy the list, this is only likely to happen once in application life cycle
583 return &(mImpl->taskList);
587 // copy the list, this is only likely to happen once in application life cycle
588 return &(mImpl->systemLevelTaskList);
592 unsigned int* UpdateManager::ReserveMessageSlot( std::size_t size, bool updateScene )
594 return mImpl->messageQueue.ReserveMessageSlot( size, updateScene );
597 void UpdateManager::EventProcessingStarted()
599 mImpl->messageQueue.EventProcessingStarted();
602 bool UpdateManager::FlushQueue()
604 return mImpl->messageQueue.FlushQueue();
607 void UpdateManager::ResetProperties( BufferIndex bufferIndex )
609 // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
610 mImpl->animationFinishedDuringUpdate = false;
612 // Animated properties have to be reset to their original value each frame
614 // Reset root properties
617 mImpl->root->ResetToBaseValues( bufferIndex );
619 if ( mImpl->systemLevelRoot )
621 mImpl->systemLevelRoot->ResetToBaseValues( bufferIndex );
624 // Reset all the nodes
625 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
626 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
627 for( ;iter != endIter; ++iter )
629 (*iter)->ResetToBaseValues( bufferIndex );
632 // Reset system-level render-task list properties to base values
633 ResetToBaseValues( mImpl->systemLevelTaskList.GetTasks(), bufferIndex );
635 // Reset render-task list properties to base values.
636 ResetToBaseValues( mImpl->taskList.GetTasks(), bufferIndex );
638 // Reset custom object properties to base values
639 ResetToBaseValues( mImpl->customObjects, bufferIndex );
641 // Reset animatable renderer properties to base values
642 ResetToBaseValues( mImpl->renderers, bufferIndex );
644 // Reset animatable shader properties to base values
645 ResetToBaseValues( mImpl->shaders, bufferIndex );
648 bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds )
650 bool gestureUpdated( false );
652 if( mImpl->panGestureProcessor )
654 // gesture processor only supports default properties
655 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
656 gestureUpdated |= mImpl->panGestureProcessor->UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
659 return gestureUpdated;
662 void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
664 AnimationContainer &animations = mImpl->animations;
665 AnimationIter iter = animations.Begin();
666 bool animationLooped = false;
668 while ( iter != animations.End() )
670 Animation* animation = *iter;
671 bool finished = false;
673 bool progressMarkerReached = false;
674 animation->Update( bufferIndex, elapsedSeconds, looped, finished, progressMarkerReached );
676 if ( progressMarkerReached )
678 mImpl->notificationManager.QueueMessage( Internal::NotifyProgressReachedMessage( mImpl->animationPlaylist, animation ) );
681 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
682 animationLooped = animationLooped || looped;
684 // Remove animations that had been destroyed but were still waiting for an update
685 if (animation->GetState() == Animation::Destroyed)
687 iter = animations.Erase(iter);
695 // queue the notification on finished or looped (to update loop count)
696 if ( mImpl->animationFinishedDuringUpdate || animationLooped )
698 // The application should be notified by NotificationManager, in another thread
699 mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationPlaylist );
703 void UpdateManager::ConstrainCustomObjects( BufferIndex bufferIndex )
705 //Constrain custom objects (in construction order)
706 OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
707 const OwnerContainer< PropertyOwner* >::Iterator endIter = customObjects.End();
708 for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); endIter != iter; ++iter )
710 PropertyOwner& object = **iter;
711 ConstrainPropertyOwner( object, bufferIndex );
715 void UpdateManager::ConstrainRenderTasks( BufferIndex bufferIndex )
717 // Constrain system-level render-tasks
718 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
719 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter )
721 RenderTask& task = **iter;
722 ConstrainPropertyOwner( task, bufferIndex );
725 // Constrain render-tasks
726 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
727 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter )
729 RenderTask& task = **iter;
730 ConstrainPropertyOwner( task, bufferIndex );
734 void UpdateManager::ConstrainShaders( BufferIndex bufferIndex )
736 // constrain shaders... (in construction order)
737 ShaderOwner& shaders = mImpl->shaders;
738 for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
740 Shader& shader = **iter;
741 ConstrainPropertyOwner( shader, bufferIndex );
745 void UpdateManager::ProcessPropertyNotifications( BufferIndex bufferIndex )
747 PropertyNotificationContainer ¬ifications = mImpl->propertyNotifications;
748 PropertyNotificationIter iter = notifications.Begin();
750 while ( iter != notifications.End() )
752 PropertyNotification* notification = *iter;
753 bool valid = notification->Check( bufferIndex );
756 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
762 void UpdateManager::ForwardCompiledShadersToEventThread()
764 DALI_ASSERT_DEBUG( (mImpl->shaderSaver != 0) && "shaderSaver should be wired-up during startup." );
765 if( mImpl->shaderSaver )
767 // lock and swap the queues
769 // render might be attempting to send us more binaries at the same time
770 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
771 mImpl->renderCompiledShaders.swap( mImpl->updateCompiledShaders );
774 if( mImpl->updateCompiledShaders.size() > 0 )
776 ShaderSaver& factory = *mImpl->shaderSaver;
777 ShaderDataBinaryQueue::iterator i = mImpl->updateCompiledShaders.begin();
778 ShaderDataBinaryQueue::iterator end = mImpl->updateCompiledShaders.end();
779 for( ; i != end; ++i )
781 mImpl->notificationManager.QueueMessage( ShaderCompiledMessage( factory, *i ) );
783 // we don't need them in update anymore
784 mImpl->updateCompiledShaders.clear();
789 void UpdateManager::UpdateRenderers( BufferIndex bufferIndex )
791 const unsigned int rendererCount = mImpl->renderers.Count();
792 for( unsigned int i = 0; i < rendererCount; ++i )
795 ConstrainPropertyOwner( *mImpl->renderers[i], bufferIndex );
797 mImpl->renderers[i]->PrepareRender( bufferIndex );
801 void UpdateManager::UpdateNodes( BufferIndex bufferIndex )
803 mImpl->nodeDirtyFlags = NothingFlag;
810 // Prepare resources, update shaders, for each node
811 // And add the renderers to the sorted layers. Start from root, which is also a layer
812 mImpl->nodeDirtyFlags = UpdateNodeTree( *( mImpl->root ),
814 mImpl->renderQueue );
816 if ( mImpl->systemLevelRoot )
818 mImpl->nodeDirtyFlags |= UpdateNodeTree( *( mImpl->systemLevelRoot ),
820 mImpl->renderQueue );
824 unsigned int UpdateManager::Update( float elapsedSeconds,
825 unsigned int lastVSyncTimeMilliseconds,
826 unsigned int nextVSyncTimeMilliseconds )
828 const BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
830 //Clear nodes/resources which were previously discarded
831 mImpl->discardQueue.Clear( bufferIndex );
833 //Process Touches & Gestures
834 const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
836 bool updateScene = // The scene-graph requires an update if..
837 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
838 IsAnimationRunning() || // ..at least one animation is running OR
839 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
840 gestureUpdated; // ..a gesture property was updated
843 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
844 // values if the scene was updated in the previous frame.
845 if( updateScene || mImpl->previousUpdateScene )
847 //Reset properties from the previous update
848 ResetProperties( bufferIndex );
849 mImpl->transformManager.ResetToBaseValue();
852 // Process the queued scene messages. Note, MessageQueue::FlushQueue may be called
853 // between calling IsSceneUpdateRequired() above and here, so updateScene should
855 updateScene |= mImpl->messageQueue.ProcessMessages( bufferIndex );
857 //Forward compiled shader programs to event thread for saving
858 ForwardCompiledShadersToEventThread();
860 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
861 // renderer lists if the scene was updated in the previous frame.
862 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
863 if( updateScene || mImpl->previousUpdateScene )
866 Animate( bufferIndex, elapsedSeconds );
868 //Constraint custom objects
869 ConstrainCustomObjects( bufferIndex );
871 //Clear the lists of renderers from the previous update
872 for( size_t i(0); i<mImpl->sortedLayers.size(); ++i )
874 mImpl->sortedLayers[i]->ClearRenderables();
877 for( size_t i(0); i<mImpl->systemLevelSortedLayers.size(); ++i )
879 mImpl->systemLevelSortedLayers[i]->ClearRenderables();
882 //Update node hierarchy, apply constraints and perform sorting / culling.
883 //This will populate each Layer with a list of renderers which are ready.
884 UpdateNodes( bufferIndex );
886 //Apply constraints to RenderTasks, shaders
887 ConstrainRenderTasks( bufferIndex );
888 ConstrainShaders( bufferIndex );
890 //Update renderers and apply constraints
891 UpdateRenderers( bufferIndex );
893 //Update the trnasformations of all the nodes
894 mImpl->transformManager.Update();
896 //Process Property Notifications
897 ProcessPropertyNotifications( bufferIndex );
900 const CameraOwner::Iterator endCameraIterator = mImpl->cameras.End();
901 for( CameraOwner::Iterator cameraIterator = mImpl->cameras.Begin(); endCameraIterator != cameraIterator; ++cameraIterator )
903 ( *cameraIterator )->Update( bufferIndex );
906 //Process the RenderTasks if renderers exist. This creates the instructions for rendering the next frame.
907 //reset the update buffer index and make sure there is enough room in the instruction container
908 if( mImpl->renderersAdded )
910 mImpl->renderInstructions.ResetAndReserve( bufferIndex,
911 mImpl->taskList.GetTasks().Count() + mImpl->systemLevelTaskList.GetTasks().Count() );
913 if ( NULL != mImpl->root )
915 mImpl->renderTaskProcessor.Process( bufferIndex,
919 mImpl->renderInstructions );
921 // Process the system-level RenderTasks last
922 if ( NULL != mImpl->systemLevelRoot )
924 mImpl->renderTaskProcessor.Process( bufferIndex,
925 mImpl->systemLevelTaskList,
926 *mImpl->systemLevelRoot,
927 mImpl->systemLevelSortedLayers,
928 mImpl->renderInstructions );
934 // check the countdown and notify (note, at the moment this is only done for normal tasks, not for systemlevel tasks)
935 bool doRenderOnceNotify = false;
936 mImpl->renderTaskWaiting = false;
937 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
938 for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(), endIter = tasks.End();
939 endIter != iter; ++iter )
941 RenderTask& renderTask(*(*iter));
943 renderTask.UpdateState();
945 if( renderTask.IsWaitingToRender() &&
946 renderTask.ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
948 mImpl->renderTaskWaiting = true; // keep update/render threads alive
951 if( renderTask.HasRendered() )
953 doRenderOnceNotify = true;
957 if( doRenderOnceNotify )
959 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
960 mImpl->notificationManager.QueueCompleteNotification( mImpl->taskList.GetCompleteNotificationInterface() );
963 // Macro is undefined in release build.
964 SNAPSHOT_NODE_LOGGING;
966 // A ResetProperties() may be required in the next frame
967 mImpl->previousUpdateScene = updateScene;
969 // Check whether further updates are required
970 unsigned int keepUpdating = KeepUpdatingCheck( elapsedSeconds );
972 // tell the update manager that we're done so the queue can be given to event thread
973 mImpl->notificationManager.UpdateCompleted();
975 // The update has finished; swap the double-buffering indices
976 mSceneGraphBuffers.Swap();
981 unsigned int UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
983 // Update the duration set via Stage::KeepRendering()
984 if ( mImpl->keepRenderingSeconds > 0.0f )
986 mImpl->keepRenderingSeconds -= elapsedSeconds;
989 unsigned int keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
991 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
992 // Keep updating until no messages are received and no animations are running.
993 // If an animation has just finished, update at least once more for Discard end-actions.
994 // No need to check for renderQueue as there is always a render after update and if that
995 // render needs another update it will tell the adaptor to call update again
997 if ( mImpl->keepRenderingSeconds > 0.0f )
999 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
1002 if ( IsAnimationRunning() ||
1003 mImpl->animationFinishedDuringUpdate )
1005 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
1008 if ( mImpl->renderTaskWaiting )
1010 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
1013 return keepUpdatingRequest;
1016 void UpdateManager::SetBackgroundColor( const Vector4& color )
1018 typedef MessageValue1< RenderManager, Vector4 > 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::SetBackgroundColor, color );
1027 void UpdateManager::SetDefaultSurfaceRect( const Rect<int>& rect )
1029 typedef MessageValue1< RenderManager, Rect<int> > DerivedType;
1031 // Reserve some memory inside the render queue
1032 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1034 // Construct message in the render queue memory; note that delete should not be called on the return value
1035 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1038 void UpdateManager::KeepRendering( float durationSeconds )
1040 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1043 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, bool systemLevel )
1047 // just copy the vector of pointers
1048 mImpl->sortedLayers = layers;
1052 mImpl->systemLevelSortedLayers = layers;
1056 void UpdateManager::SetDepthIndices( OwnerPointer< NodeDepths >& nodeDepths )
1058 // note,this vector is already in depth order. It could be used as-is to
1059 // remove sorting in update algorithm. However, it lacks layer boundary markers.
1060 for( std::vector<NodeDepthPair>::iterator iter = nodeDepths->nodeDepths.begin(),
1061 end = nodeDepths->nodeDepths.end() ;
1062 iter != end ; ++iter )
1064 iter->node->SetDepthIndex( iter->sortedDepth );
1068 void UpdateManager::AddSampler( OwnerPointer< Render::Sampler >& sampler )
1070 // Message has ownership of Sampler while in transit from update to render
1071 typedef MessageValue1< RenderManager, OwnerPointer< Render::Sampler > > DerivedType;
1073 // Reserve some memory inside the render queue
1074 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1076 // Construct message in the render queue memory; note that delete should not be called on the return value
1077 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddSampler, sampler );
1080 void UpdateManager::RemoveSampler( Render::Sampler* sampler )
1082 typedef MessageValue1< RenderManager, Render::Sampler* > DerivedType;
1084 // Reserve some memory inside the render queue
1085 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1087 // Construct message in the render queue memory; note that delete should not be called on the return value
1088 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveSampler, sampler );
1091 void UpdateManager::SetFilterMode( Render::Sampler* sampler, unsigned int minFilterMode, unsigned int magFilterMode )
1093 typedef MessageValue3< RenderManager, Render::Sampler*, unsigned int, unsigned int > DerivedType;
1095 // Reserve some memory inside the render queue
1096 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1098 // Construct message in the render queue memory; note that delete should not be called on the return value
1099 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetFilterMode, sampler, minFilterMode, magFilterMode );
1102 void UpdateManager::SetWrapMode( Render::Sampler* sampler, unsigned int rWrapMode, unsigned int sWrapMode, unsigned int tWrapMode )
1104 typedef MessageValue4< RenderManager, Render::Sampler*, unsigned int, unsigned int, unsigned int > DerivedType;
1106 // Reserve some memory inside the render queue
1107 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1109 // Construct message in the render queue memory; note that delete should not be called on the return value
1110 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetWrapMode, sampler, rWrapMode, sWrapMode, tWrapMode );
1113 void UpdateManager::AddPropertyBuffer( OwnerPointer< Render::PropertyBuffer >& propertyBuffer )
1115 // Message has ownership of format while in transit from update -> render
1116 typedef MessageValue1< RenderManager, OwnerPointer< Render::PropertyBuffer > > DerivedType;
1118 // Reserve some memory inside the render queue
1119 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1121 // Construct message in the render queue memory; note that delete should not be called on the return value
1122 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddPropertyBuffer, propertyBuffer );
1125 void UpdateManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer )
1127 typedef MessageValue1< RenderManager, Render::PropertyBuffer* > DerivedType;
1129 // Reserve some memory inside the render queue
1130 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1132 // Construct message in the render queue memory; note that delete should not be called on the return value
1133 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemovePropertyBuffer, propertyBuffer );
1136 void UpdateManager::SetPropertyBufferFormat( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Render::PropertyBuffer::Format>& format )
1138 // Message has ownership of format while in transit from update -> render
1139 typedef MessageValue2< RenderManager, Render::PropertyBuffer*, OwnerPointer< Render::PropertyBuffer::Format > > DerivedType;
1141 // Reserve some memory inside the render queue
1142 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1144 // Construct message in the render queue memory; note that delete should not be called on the return value
1145 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferFormat, propertyBuffer, format );
1148 void UpdateManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Vector<char> >& data, size_t size )
1150 // Message has ownership of format while in transit from update -> render
1151 typedef MessageValue3< RenderManager, Render::PropertyBuffer*, OwnerPointer< Dali::Vector<char> >, size_t > DerivedType;
1153 // Reserve some memory inside the render queue
1154 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1156 // Construct message in the render queue memory; note that delete should not be called on the return value
1157 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferData, propertyBuffer, data, size );
1160 void UpdateManager::AddGeometry( OwnerPointer< Render::Geometry >& geometry )
1162 // Message has ownership of format while in transit from update -> render
1163 typedef MessageValue1< RenderManager, OwnerPointer< Render::Geometry > > DerivedType;
1165 // Reserve some memory inside the render queue
1166 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1168 // Construct message in the render queue memory; note that delete should not be called on the return value
1169 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddGeometry, geometry );
1172 void UpdateManager::RemoveGeometry( Render::Geometry* geometry )
1174 typedef MessageValue1< RenderManager, Render::Geometry* > DerivedType;
1176 // Reserve some memory inside the render queue
1177 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1179 // Construct message in the render queue memory; note that delete should not be called on the return value
1180 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveGeometry, geometry );
1183 void UpdateManager::SetGeometryType( Render::Geometry* geometry, unsigned int geometryType )
1185 typedef MessageValue2< RenderManager, Render::Geometry*, unsigned int > DerivedType;
1187 // Reserve some memory inside the render queue
1188 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1190 // Construct message in the render queue memory; note that delete should not be called on the return value
1191 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetGeometryType, geometry, geometryType );
1194 void UpdateManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector<unsigned short>& indices )
1196 typedef IndexBufferMessage< RenderManager > DerivedType;
1198 // Reserve some memory inside the render queue
1199 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1201 // Construct message in the render queue memory; note that delete should not be called on the return value
1202 new (slot) DerivedType( &mImpl->renderManager, geometry, indices );
1205 void UpdateManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1207 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1209 // Reserve some memory inside the render queue
1210 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1212 // Construct message in the render queue memory; note that delete should not be called on the return value
1213 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveVertexBuffer, geometry, propertyBuffer );
1216 void UpdateManager::AttachVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1218 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1220 // Reserve some memory inside the render queue
1221 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1223 // Construct message in the render queue memory; note that delete should not be called on the return value
1224 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AttachVertexBuffer, geometry, propertyBuffer );
1227 void UpdateManager::AddTexture( OwnerPointer< Render::Texture >& texture )
1229 // Message has ownership of Texture while in transit from update -> render
1230 typedef MessageValue1< RenderManager, OwnerPointer< Render::Texture > > DerivedType;
1232 // Reserve some memory inside the render queue
1233 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1235 // Construct message in the render queue memory; note that delete should not be called on the return value
1236 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddTexture, texture );
1239 void UpdateManager::RemoveTexture( Render::Texture* texture)
1241 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1243 // Reserve some memory inside the render queue
1244 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1246 // Construct message in the render queue memory; note that delete should not be called on the return value
1247 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveTexture, texture );
1250 void UpdateManager::UploadTexture( Render::Texture* texture, PixelDataPtr pixelData, const Texture::UploadParams& params )
1252 typedef MessageValue3< RenderManager, Render::Texture*, PixelDataPtr, Texture::UploadParams > DerivedType;
1254 // Reserve some memory inside the message queue
1255 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1257 // Construct message in the message queue memory; note that delete should not be called on the return value
1258 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::UploadTexture, texture, pixelData, params );
1261 void UpdateManager::GenerateMipmaps( Render::Texture* texture )
1263 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1265 // Reserve some memory inside the render queue
1266 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1268 // Construct message in the render queue memory; note that delete should not be called on the return value
1269 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::GenerateMipmaps, texture );
1272 void UpdateManager::AddFrameBuffer( Render::FrameBuffer* frameBuffer )
1274 typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType;
1276 // Reserve some memory inside the render queue
1277 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1279 // Construct message in the render queue memory; note that delete should not be called on the return value
1280 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddFrameBuffer, frameBuffer );
1283 void UpdateManager::RemoveFrameBuffer( Render::FrameBuffer* frameBuffer)
1285 typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType;
1287 // Reserve some memory inside the render queue
1288 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1290 // Construct message in the render queue memory; note that delete should not be called on the return value
1291 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveFrameBuffer, frameBuffer );
1294 void UpdateManager::AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, unsigned int mipmapLevel, unsigned int layer )
1296 typedef MessageValue4< RenderManager, Render::FrameBuffer*, Render::Texture*, unsigned int, unsigned int > DerivedType;
1298 // Reserve some memory inside the render queue
1299 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1301 // Construct message in the render queue memory; note that delete should not be called on the return value
1302 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AttachColorTextureToFrameBuffer, frameBuffer, texture, mipmapLevel, layer );
1305 } // namespace SceneGraph
1307 } // namespace Internal