2 * Copyright (c) 2018 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/frame-callback-processor.h>
48 #include <dali/internal/update/manager/render-task-processor.h>
49 #include <dali/internal/update/manager/sorted-layers.h>
50 #include <dali/internal/update/manager/update-algorithms.h>
51 #include <dali/internal/update/manager/update-manager-debug.h>
52 #include <dali/internal/update/manager/transform-manager.h>
53 #include <dali/internal/update/nodes/node.h>
54 #include <dali/internal/update/nodes/scene-graph-layer.h>
55 #include <dali/internal/update/queue/update-message-queue.h>
56 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
57 #include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
58 #include <dali/internal/update/render-tasks/scene-graph-camera.h>
60 #include <dali/internal/render/common/render-instruction-container.h>
61 #include <dali/internal/render/common/render-manager.h>
62 #include <dali/internal/render/queue/render-queue.h>
63 #include <dali/internal/render/shaders/scene-graph-shader.h>
65 // Un-comment to enable node tree debug logging
66 //#define NODE_TREE_LOGGING 1
68 #if ( defined( DEBUG_ENABLED ) && defined( NODE_TREE_LOGGING ) )
69 #define SNAPSHOT_NODE_LOGGING \
70 const uint32_t FRAME_COUNT_TRIGGER = 16;\
71 if( mImpl->frameCounter >= FRAME_COUNT_TRIGGER )\
73 for( auto root : mImpl->roots )
77 mImpl->frameCounter = 0;\
78 PrintNodeTree( *root, mSceneGraphBuffers.GetUpdateBufferIndex(), "" );\
82 mImpl->frameCounter++;
84 #define SNAPSHOT_NODE_LOGGING
87 #if defined(DEBUG_ENABLED)
88 extern Debug::Filter* gRenderTaskLogFilter;
92 using namespace Dali::Integration;
93 using Dali::Internal::Update::MessageQueue;
107 * Helper to reset animate-able objects to base values
108 * @param container to iterate over
109 * @param updateBufferIndex to use
112 inline void ResetToBaseValues( OwnerContainer<T*>& container, BufferIndex updateBufferIndex )
114 // Reset animatable properties to base values
115 // use reference to avoid extra copies of the iterator
116 for( auto&& iter : container )
118 iter->ResetToBaseValues( updateBufferIndex );
123 * Helper to Erase an object from OwnerContainer using discard queue
124 * @param container to remove from
125 * @param object to remove
126 * @param discardQueue to put the object to
127 * @param updateBufferIndex to use
130 inline void EraseUsingDiscardQueue( OwnerContainer<T*>& container, T* object, DiscardQueue& discardQueue, BufferIndex updateBufferIndex )
132 DALI_ASSERT_DEBUG( object && "NULL object not allowed" );
134 // need to use the reference version of auto as we need the pointer to the pointer for the Release call below
135 for( auto&& iter : container )
137 if ( iter == object )
139 // Transfer ownership to the discard queue, this keeps the object alive, until the render-thread has finished with it
140 discardQueue.Add( updateBufferIndex, container.Release( &iter ) ); // take the address of the reference to a pointer (iter)
141 return; // return as we only ever remove one object. Iterators to container are now invalidated as well so cannot continue
147 * Descends into node's hierarchy and sorts the children of each child according to their depth-index.
148 * @param[in] node The node whose hierarchy to descend
150 void SortSiblingNodesRecursively( Node& node )
152 NodeContainer& container = node.GetChildren();
153 std::sort( container.Begin(), container.End(),
154 []( Node* a, Node* b ) { return a->GetDepthIndex() < b->GetDepthIndex(); } );
156 // Descend tree and sort as well
157 for( auto&& iter : container )
159 SortSiblingNodesRecursively( *iter );
163 } // unnamed namespace
166 * Structure to contain UpdateManager internal data
168 struct UpdateManager::Impl
170 Impl( NotificationManager& notificationManager,
171 CompleteNotificationInterface& animationPlaylist,
172 PropertyNotifier& propertyNotifier,
173 DiscardQueue& discardQueue,
174 RenderController& renderController,
175 RenderManager& renderManager,
176 RenderQueue& renderQueue,
177 SceneGraphBuffers& sceneGraphBuffers,
178 RenderTaskProcessor& renderTaskProcessor )
179 : renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ),
180 notificationManager( notificationManager ),
182 animationPlaylist( animationPlaylist ),
183 propertyNotifier( propertyNotifier ),
185 discardQueue( discardQueue ),
186 renderController( renderController ),
187 sceneController( NULL ),
188 renderManager( renderManager ),
189 renderQueue( renderQueue ),
190 renderInstructions( renderManager.GetRenderInstructionContainer() ),
191 renderTaskProcessor( renderTaskProcessor ),
192 backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
196 panGestureProcessor( NULL ),
197 messageQueue( renderController, sceneGraphBuffers ),
198 frameCallbackProcessor( NULL ),
199 keepRenderingSeconds( 0.0f ),
200 nodeDirtyFlags( NodePropertyFlags::TRANSFORM ), // set to TransformFlag to ensure full update the first time through Update()
202 renderingBehavior( DevelStage::Rendering::IF_REQUIRED ),
203 animationFinishedDuringUpdate( false ),
204 previousUpdateScene( false ),
205 renderTaskWaiting( false ),
206 renderersAdded( false ),
207 surfaceRectChanged( false )
209 sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue );
211 // create first 'dummy' node
217 // Disconnect render tasks from nodes, before destroying the nodes
218 for( auto taskList : taskLists )
220 RenderTaskList::RenderTaskContainer& tasks = taskList->GetTasks();
221 for ( auto&& task : tasks )
223 task->SetSourceNode( NULL );
227 // UpdateManager owns the Nodes. Although Nodes are pool allocated they contain heap allocated parts
228 // like custom properties, which get released here
229 Vector<Node*>::Iterator iter = nodes.Begin()+1;
230 Vector<Node*>::Iterator endIter = nodes.End();
231 for(;iter!=endIter;++iter)
233 (*iter)->OnDestroy();
237 for( auto root : roots )
242 delete sceneController;
246 * Lazy init for FrameCallbackProcessor.
248 FrameCallbackProcessor& GetFrameCallbackProcessor()
250 if( ! frameCallbackProcessor )
252 frameCallbackProcessor = new FrameCallbackProcessor( transformManager );
254 return *frameCallbackProcessor;
257 SceneGraphBuffers sceneGraphBuffers; ///< Used to keep track of which buffers are being written or read
258 RenderMessageDispatcher renderMessageDispatcher; ///< Used for passing messages to the render-thread
259 NotificationManager& notificationManager; ///< Queues notification messages for the event-thread.
260 TransformManager transformManager; ///< Used to update the transformation matrices of the nodes
261 CompleteNotificationInterface& animationPlaylist; ///< Holds handles to all the animations
262 PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
263 ShaderSaver* shaderSaver; ///< Saves shader binaries.
264 DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
265 RenderController& renderController; ///< render controller
266 SceneControllerImpl* sceneController; ///< scene controller
267 RenderManager& renderManager; ///< This is responsible for rendering the results of each "update"
268 RenderQueue& renderQueue; ///< Used to queue messages for the next render
269 RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions
270 RenderTaskProcessor& renderTaskProcessor; ///< Handles RenderTasks and RenderInstrucitons
272 Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
274 OwnerContainer<RenderTaskList*> taskLists; ///< A container of scene graph render task lists
276 OwnerContainer<Layer*> roots; ///< A container of root nodes (root is a layer). The layers are not stored in the node memory pool.
278 Vector<Node*> nodes; ///< A container of all instantiated nodes
280 std::vector<SortedLayerPointers> sortedLayerLists; ///< A container of lists of Layer pointers sorted by depth (one list of sorted layers per root)
282 OwnerContainer< Camera* > cameras; ///< A container of cameras
283 OwnerContainer< PropertyOwner* > customObjects; ///< A container of owned objects (with custom properties)
285 OwnerContainer< PropertyResetterBase* > propertyResetters; ///< A container of property resetters
286 AnimationContainer animations; ///< A container of owned animations
287 PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
288 OwnerContainer< Renderer* > renderers; ///< A container of owned renderers
289 OwnerContainer< TextureSet* > textureSets; ///< A container of owned texture sets
290 OwnerContainer< Shader* > 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 std::vector<Internal::ShaderDataPtr> renderCompiledShaders; ///< Shaders compiled on Render thread are inserted here for update thread to pass on to event thread.
295 std::vector<Internal::ShaderDataPtr> updateCompiledShaders; ///< Shaders to be sent from Update to Event
296 Mutex compiledShaderMutex; ///< lock to ensure no corruption on the renderCompiledShaders
298 OwnerPointer<FrameCallbackProcessor> frameCallbackProcessor; ///< Owned FrameCallbackProcessor, only created if required.
300 float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
301 NodePropertyFlags nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
302 uint32_t frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
304 DevelStage::Rendering renderingBehavior; ///< Set via DevelStage::SetRenderingBehavior
306 bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
307 bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
308 bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
309 bool renderersAdded; ///< Flag to keep track when renderers have been added to avoid unnecessary processing
310 bool surfaceRectChanged; ///< True if the default surface rect is changed
314 Impl( const Impl& ); ///< Undefined
315 Impl& operator=( const Impl& ); ///< Undefined
318 UpdateManager::UpdateManager( NotificationManager& notificationManager,
319 CompleteNotificationInterface& animationFinishedNotifier,
320 PropertyNotifier& propertyNotifier,
321 DiscardQueue& discardQueue,
322 RenderController& controller,
323 RenderManager& renderManager,
324 RenderQueue& renderQueue,
325 RenderTaskProcessor& renderTaskProcessor )
328 mImpl = new Impl( notificationManager,
329 animationFinishedNotifier,
336 renderTaskProcessor );
340 UpdateManager::~UpdateManager()
345 void UpdateManager::InstallRoot( OwnerPointer<Layer>& layer )
347 DALI_ASSERT_DEBUG( layer->IsLayer() );
348 DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
350 Layer* rootLayer = layer.Release();
352 DALI_ASSERT_DEBUG( std::find( mImpl->roots.begin(), mImpl->roots.end(), rootLayer ) == mImpl->roots.end() && "Root Node already installed" );
354 rootLayer->CreateTransform( &mImpl->transformManager );
355 rootLayer->SetRoot(true);
356 mImpl->roots.PushBack( rootLayer );
359 void UpdateManager::AddNode( OwnerPointer<Node>& node )
361 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
363 // Nodes must be sorted by pointer
364 Node* rawNode = node.Release();
365 Vector<Node*>::Iterator begin = mImpl->nodes.Begin();
366 for( Vector<Node*>::Iterator iter = mImpl->nodes.End()-1; iter >= begin; --iter )
368 if( rawNode > (*iter) )
370 mImpl->nodes.Insert((iter+1), rawNode );
371 rawNode->CreateTransform( &mImpl->transformManager );
377 void UpdateManager::ConnectNode( Node* parent, Node* node )
379 DALI_ASSERT_ALWAYS( NULL != parent );
380 DALI_ASSERT_ALWAYS( NULL != node );
381 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
383 parent->ConnectChild( node );
385 // Inform the frame-callback-processor, if set, about the node-hierarchy changing
386 if( mImpl->frameCallbackProcessor )
388 mImpl->frameCallbackProcessor->NodeHierarchyChanged();
392 void UpdateManager::DisconnectNode( Node* node )
394 Node* parent = node->GetParent();
395 DALI_ASSERT_ALWAYS( NULL != parent );
396 parent->SetDirtyFlag( NodePropertyFlags::CHILD_DELETED ); // make parent dirty so that render items dont get reused
398 parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node );
400 // Inform the frame-callback-processor, if set, about the node-hierarchy changing
401 if( mImpl->frameCallbackProcessor )
403 mImpl->frameCallbackProcessor->NodeHierarchyChanged();
407 void UpdateManager::DestroyNode( Node* node )
409 DALI_ASSERT_ALWAYS( NULL != node );
410 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
412 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
413 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
414 for(;iter!=endIter;++iter)
418 mImpl->nodes.Erase(iter);
423 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
425 // Notify the Node about impending destruction
429 void UpdateManager::AddCamera( OwnerPointer< Camera >& camera )
431 mImpl->cameras.PushBack( camera.Release() ); // takes ownership
434 void UpdateManager::RemoveCamera( const Camera* camera )
436 // Find the camera and destroy it
437 EraseUsingDiscardQueue( mImpl->cameras, const_cast<Camera*>( camera ), mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
440 void UpdateManager::AddObject( OwnerPointer<PropertyOwner>& object )
442 mImpl->customObjects.PushBack( object.Release() );
445 void UpdateManager::RemoveObject( PropertyOwner* object )
447 mImpl->customObjects.EraseObject( object );
450 void UpdateManager::AddRenderTaskList( OwnerPointer<RenderTaskList>& taskList )
452 RenderTaskList* taskListPointer = taskList.Release();
453 taskListPointer->SetRenderMessageDispatcher( &mImpl->renderMessageDispatcher );
454 mImpl->taskLists.PushBack( taskListPointer );
457 void UpdateManager::RemoveRenderTaskList( RenderTaskList* taskList )
459 mImpl->taskLists.EraseObject( taskList );
462 void UpdateManager::AddAnimation( OwnerPointer< SceneGraph::Animation >& animation )
464 mImpl->animations.PushBack( animation.Release() );
467 void UpdateManager::StopAnimation( Animation* animation )
469 DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
471 bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
473 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
476 void UpdateManager::RemoveAnimation( Animation* animation )
478 DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
480 animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
482 DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
485 bool UpdateManager::IsAnimationRunning() const
487 // Find any animation that isn't stopped or paused
488 for ( auto&& iter : mImpl->animations )
490 const Animation::State state = iter->GetState();
492 if (state != Animation::Stopped &&
493 state != Animation::Paused)
495 return true; // stop iteration as soon as first one is found
502 void UpdateManager::AddPropertyResetter( OwnerPointer<PropertyResetterBase>& propertyResetter )
504 propertyResetter->Initialize();
505 mImpl->propertyResetters.PushBack( propertyResetter.Release() );
508 void UpdateManager::AddPropertyNotification( OwnerPointer< PropertyNotification >& propertyNotification )
510 mImpl->propertyNotifications.PushBack( propertyNotification.Release() );
513 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
515 mImpl->propertyNotifications.EraseObject( propertyNotification );
518 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
520 DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
521 propertyNotification->SetNotifyMode( notifyMode );
524 void UpdateManager::AddShader( OwnerPointer< Shader >& shader )
526 mImpl->shaders.PushBack( shader.Release() );
529 void UpdateManager::RemoveShader( Shader* shader )
531 // Find the shader and destroy it
532 EraseUsingDiscardQueue( mImpl->shaders, shader, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
535 void UpdateManager::SetShaderProgram( Shader* shader,
536 Internal::ShaderDataPtr shaderData, bool modifiesGeometry )
541 typedef MessageValue3< Shader, Internal::ShaderDataPtr, ProgramCache*, bool> DerivedType;
543 // Reserve some memory inside the render queue
544 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
546 // Construct message in the render queue memory; note that delete should not be called on the return value
547 new (slot) DerivedType( shader, &Shader::SetProgram, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
551 void UpdateManager::SaveBinary( Internal::ShaderDataPtr shaderData )
553 DALI_ASSERT_DEBUG( shaderData && "No NULL shader data pointers please." );
554 DALI_ASSERT_DEBUG( shaderData->GetBufferSize() > 0 && "Shader binary empty so nothing to save." );
556 // lock as update might be sending previously compiled shaders to event thread
557 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
558 mImpl->renderCompiledShaders.push_back( shaderData );
562 void UpdateManager::SetShaderSaver( ShaderSaver& upstream )
564 mImpl->shaderSaver = &upstream;
567 void UpdateManager::AddRenderer( OwnerPointer< Renderer >& renderer )
569 renderer->ConnectToSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
570 mImpl->renderers.PushBack( renderer.Release() );
571 mImpl->renderersAdded = true;
574 void UpdateManager::RemoveRenderer( Renderer* renderer )
576 // Find the renderer and destroy it
577 EraseUsingDiscardQueue( mImpl->renderers, renderer, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
578 // Need to remove the render object as well
579 renderer->DisconnectFromSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
582 void UpdateManager::SetPanGestureProcessor( PanGesture* panGestureProcessor )
584 DALI_ASSERT_DEBUG( NULL != panGestureProcessor );
586 mImpl->panGestureProcessor = panGestureProcessor;
589 void UpdateManager::AddTextureSet( OwnerPointer< TextureSet >& textureSet )
591 mImpl->textureSets.PushBack( textureSet.Release() );
594 void UpdateManager::RemoveTextureSet( TextureSet* textureSet )
596 mImpl->textureSets.EraseObject( textureSet );
599 uint32_t* UpdateManager::ReserveMessageSlot( uint32_t size, bool updateScene )
601 return mImpl->messageQueue.ReserveMessageSlot( size, updateScene );
604 void UpdateManager::EventProcessingStarted()
606 mImpl->messageQueue.EventProcessingStarted();
609 bool UpdateManager::FlushQueue()
611 return mImpl->messageQueue.FlushQueue();
614 void UpdateManager::ResetProperties( BufferIndex bufferIndex )
616 // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
617 mImpl->animationFinishedDuringUpdate = false;
619 // Reset all animating / constrained properties
620 std::vector<PropertyResetterBase*>toDelete;
621 for( auto&& element : mImpl->propertyResetters )
623 element->ResetToBaseValue( bufferIndex );
624 if( element->IsFinished() )
626 toDelete.push_back( element );
630 // If a resetter is no longer required (the animator or constraint has been removed), delete it.
631 for( auto&& elementPtr : toDelete )
633 mImpl->propertyResetters.EraseObject( elementPtr );
636 // Clear node dirty flags
637 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
638 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
639 for( ;iter != endIter; ++iter )
641 (*iter)->ResetDirtyFlags( bufferIndex );
645 bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, uint32_t lastVSyncTimeMilliseconds, uint32_t 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 for ( auto&& object : mImpl->customObjects )
705 ConstrainPropertyOwner( *object, bufferIndex );
709 void UpdateManager::ConstrainRenderTasks( BufferIndex bufferIndex )
711 // Constrain render-tasks
712 for( auto taskList : mImpl->taskLists )
714 RenderTaskList::RenderTaskContainer& tasks = taskList->GetTasks();
715 for ( auto&& task : tasks )
717 ConstrainPropertyOwner( *task, bufferIndex );
722 void UpdateManager::ConstrainShaders( BufferIndex bufferIndex )
724 // constrain shaders... (in construction order)
725 for ( auto&& shader : mImpl->shaders )
727 ConstrainPropertyOwner( *shader, bufferIndex );
731 void UpdateManager::ProcessPropertyNotifications( BufferIndex bufferIndex )
733 for( auto&& notification : mImpl->propertyNotifications )
735 bool valid = notification->Check( bufferIndex );
738 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
743 void UpdateManager::ForwardCompiledShadersToEventThread()
745 DALI_ASSERT_DEBUG( (mImpl->shaderSaver != 0) && "shaderSaver should be wired-up during startup." );
746 if( mImpl->shaderSaver )
748 // lock and swap the queues
750 // render might be attempting to send us more binaries at the same time
751 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
752 mImpl->renderCompiledShaders.swap( mImpl->updateCompiledShaders );
755 if( mImpl->updateCompiledShaders.size() > 0 )
757 ShaderSaver& factory = *mImpl->shaderSaver;
758 for( auto&& shader : mImpl->updateCompiledShaders )
760 mImpl->notificationManager.QueueMessage( ShaderCompiledMessage( factory, shader ) );
762 // we don't need them in update anymore
763 mImpl->updateCompiledShaders.clear();
768 void UpdateManager::UpdateRenderers( BufferIndex bufferIndex )
770 for( auto&& renderer : mImpl->renderers )
773 ConstrainPropertyOwner( *renderer, bufferIndex );
775 renderer->PrepareRender( bufferIndex );
779 void UpdateManager::UpdateNodes( BufferIndex bufferIndex )
781 mImpl->nodeDirtyFlags = NodePropertyFlags::NOTHING;
783 for( auto&& rootLayer : mImpl->roots )
785 // Prepare resources, update shaders, for each node
786 // And add the renderers to the sorted layers. Start from root, which is also a layer
787 mImpl->nodeDirtyFlags |= UpdateNodeTree( *rootLayer,
789 mImpl->renderQueue );
793 uint32_t UpdateManager::Update( float elapsedSeconds,
794 uint32_t lastVSyncTimeMilliseconds,
795 uint32_t nextVSyncTimeMilliseconds,
796 bool renderToFboEnabled,
797 bool isRenderingToFbo )
799 const BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
801 //Clear nodes/resources which were previously discarded
802 mImpl->discardQueue.Clear( bufferIndex );
804 //Process Touches & Gestures
805 const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
807 bool updateScene = // The scene-graph requires an update if..
808 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
809 IsAnimationRunning() || // ..at least one animation is running OR
810 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
811 gestureUpdated; // ..a gesture property was updated
814 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
815 // values if the scene was updated in the previous frame.
816 if( updateScene || mImpl->previousUpdateScene )
818 //Reset properties from the previous update
819 ResetProperties( bufferIndex );
820 mImpl->transformManager.ResetToBaseValue();
823 // Process the queued scene messages. Note, MessageQueue::FlushQueue may be called
824 // between calling IsSceneUpdateRequired() above and here, so updateScene should
826 updateScene |= mImpl->messageQueue.ProcessMessages( bufferIndex );
828 //Forward compiled shader programs to event thread for saving
829 ForwardCompiledShadersToEventThread();
831 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
832 // renderer lists if the scene was updated in the previous frame.
833 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
834 if( updateScene || mImpl->previousUpdateScene )
837 Animate( bufferIndex, elapsedSeconds );
839 //Constraint custom objects
840 ConstrainCustomObjects( bufferIndex );
842 //Clear the lists of renderers from the previous update
843 for( auto sortedLayers : mImpl->sortedLayerLists )
845 for( auto&& layer : sortedLayers )
847 layer->ClearRenderables();
851 //Update node hierarchy, apply constraints and perform sorting / culling.
852 //This will populate each Layer with a list of renderers which are ready.
853 UpdateNodes( bufferIndex );
855 //Apply constraints to RenderTasks, shaders
856 ConstrainRenderTasks( bufferIndex );
857 ConstrainShaders( bufferIndex );
859 //Update renderers and apply constraints
860 UpdateRenderers( bufferIndex );
862 // Call the frame-callback-processor if set
863 if( mImpl->frameCallbackProcessor )
865 mImpl->frameCallbackProcessor->Update( bufferIndex, elapsedSeconds );
868 //Update the transformations of all the nodes
869 mImpl->transformManager.Update();
871 //Process Property Notifications
872 ProcessPropertyNotifications( bufferIndex );
875 for( auto&& cameraIterator : mImpl->cameras )
877 cameraIterator->Update( bufferIndex );
880 //Process the RenderTasks if renderers exist. This creates the instructions for rendering the next frame.
881 //reset the update buffer index and make sure there is enough room in the instruction container
882 if( mImpl->renderersAdded )
884 // Calculate how many render tasks we have in total
885 VectorBase::SizeType numberOfRenderTasks = 0;
887 const VectorBase::SizeType taskListCount = mImpl->taskLists.Count();
888 for ( VectorBase::SizeType index = 0u; index < taskListCount; index++ )
890 numberOfRenderTasks += mImpl->taskLists[index]->GetTasks().Count();
893 mImpl->renderInstructions.ResetAndReserve( bufferIndex,
894 static_cast<uint32_t>( numberOfRenderTasks ) );
896 for ( VectorBase::SizeType index = 0u; index < taskListCount; index++ )
898 if ( NULL != mImpl->roots[index] )
900 mImpl->renderTaskProcessor.Process( bufferIndex,
901 *mImpl->taskLists[index],
902 *mImpl->roots[index],
903 mImpl->sortedLayerLists[index],
904 mImpl->renderInstructions,
912 for( auto taskList : mImpl->taskLists )
914 RenderTaskList::RenderTaskContainer& tasks = taskList->GetTasks();
916 // check the countdown and notify
917 bool doRenderOnceNotify = false;
918 mImpl->renderTaskWaiting = false;
919 for ( auto&& renderTask : tasks )
921 renderTask->UpdateState();
923 if( renderTask->IsWaitingToRender() &&
924 renderTask->ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
926 mImpl->renderTaskWaiting = true; // keep update/render threads alive
929 if( renderTask->HasRendered() )
931 doRenderOnceNotify = true;
935 if( doRenderOnceNotify )
937 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
938 mImpl->notificationManager.QueueCompleteNotification( taskList->GetCompleteNotificationInterface() );
942 // Macro is undefined in release build.
943 SNAPSHOT_NODE_LOGGING;
945 // A ResetProperties() may be required in the next frame
946 mImpl->previousUpdateScene = updateScene;
948 // Check whether further updates are required
949 uint32_t keepUpdating = KeepUpdatingCheck( elapsedSeconds );
951 // tell the update manager that we're done so the queue can be given to event thread
952 mImpl->notificationManager.UpdateCompleted();
954 // The update has finished; swap the double-buffering indices
955 mSceneGraphBuffers.Swap();
960 uint32_t UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
962 // Update the duration set via Stage::KeepRendering()
963 if ( mImpl->keepRenderingSeconds > 0.0f )
965 mImpl->keepRenderingSeconds -= elapsedSeconds;
968 uint32_t keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
970 // If the rendering behavior is set to continuously render, then continue to render.
971 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
972 // Keep updating until no messages are received and no animations are running.
973 // If an animation has just finished, update at least once more for Discard end-actions.
974 // No need to check for renderQueue as there is always a render after update and if that
975 // render needs another update it will tell the adaptor to call update again
977 if ( ( mImpl->renderingBehavior == DevelStage::Rendering::CONTINUOUSLY ) ||
978 ( mImpl->keepRenderingSeconds > 0.0f ) )
980 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
983 if ( IsAnimationRunning() ||
984 mImpl->animationFinishedDuringUpdate )
986 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
989 if ( mImpl->renderTaskWaiting )
991 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
994 return keepUpdatingRequest;
997 void UpdateManager::SetBackgroundColor( const Vector4& color )
999 typedef MessageValue1< RenderManager, Vector4 > DerivedType;
1001 // Reserve some memory inside the render queue
1002 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1004 // Construct message in the render queue memory; note that delete should not be called on the return value
1005 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
1008 void UpdateManager::SetDefaultSurfaceRect( const Rect<int32_t>& rect )
1010 mImpl->surfaceRectChanged = true;
1012 typedef MessageValue1< RenderManager, Rect<int32_t> > DerivedType;
1014 // Reserve some memory inside the render queue
1015 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1017 // Construct message in the render queue memory; note that delete should not be called on the return value
1018 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1021 void UpdateManager::KeepRendering( float durationSeconds )
1023 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1026 void UpdateManager::SetRenderingBehavior( DevelStage::Rendering renderingBehavior )
1028 mImpl->renderingBehavior = renderingBehavior;
1031 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, const Layer* rootLayer )
1033 const VectorBase::SizeType rootCount = mImpl->roots.Count();
1035 // Make sure we reserve the correct size for the container so that
1036 // we can save the sorted layers in the same order as the root layer
1037 mImpl->sortedLayerLists.resize( rootCount );
1039 for ( VectorBase::SizeType rootIndex = 0u; rootIndex < rootCount; rootIndex++ )
1041 Layer* root = mImpl->roots[rootIndex];
1042 if ( root == rootLayer )
1044 mImpl->sortedLayerLists[rootIndex] = layers;
1050 void UpdateManager::SetDepthIndices( OwnerPointer< NodeDepths >& nodeDepths )
1052 // note,this vector is already in depth order. It could be used as-is to
1053 // remove sorting in update algorithm. However, it lacks layer boundary markers.
1054 for( auto&& iter : nodeDepths->nodeDepths )
1056 iter.node->SetDepthIndex( iter.sortedDepth );
1059 for( auto root : mImpl->roots )
1061 // Go through node hierarchy and rearrange siblings according to depth-index
1062 SortSiblingNodesRecursively( *root );
1066 bool UpdateManager::IsDefaultSurfaceRectChanged()
1068 bool surfaceRectChanged = mImpl->surfaceRectChanged;
1071 mImpl->surfaceRectChanged = false;
1073 return surfaceRectChanged;
1076 void UpdateManager::AddFrameCallback( FrameCallbackInterface* frameCallback, const Node* rootNode )
1078 mImpl->GetFrameCallbackProcessor().AddFrameCallback( frameCallback, rootNode );
1081 void UpdateManager::RemoveFrameCallback( FrameCallbackInterface* frameCallback )
1083 mImpl->GetFrameCallbackProcessor().RemoveFrameCallback( frameCallback );
1086 void UpdateManager::AddSampler( OwnerPointer< Render::Sampler >& sampler )
1088 // Message has ownership of Sampler while in transit from update to render
1089 typedef MessageValue1< RenderManager, OwnerPointer< Render::Sampler > > DerivedType;
1091 // Reserve some memory inside the render queue
1092 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1094 // Construct message in the render queue memory; note that delete should not be called on the return value
1095 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddSampler, sampler );
1098 void UpdateManager::RemoveSampler( Render::Sampler* sampler )
1100 typedef MessageValue1< RenderManager, Render::Sampler* > DerivedType;
1102 // Reserve some memory inside the render queue
1103 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1105 // Construct message in the render queue memory; note that delete should not be called on the return value
1106 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveSampler, sampler );
1109 void UpdateManager::SetFilterMode( Render::Sampler* sampler, uint32_t minFilterMode, uint32_t magFilterMode )
1111 typedef MessageValue3< RenderManager, Render::Sampler*, uint32_t, uint32_t > DerivedType;
1113 // Reserve some memory inside the render queue
1114 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1116 // Construct message in the render queue memory; note that delete should not be called on the return value
1117 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetFilterMode, sampler, minFilterMode, magFilterMode );
1120 void UpdateManager::SetWrapMode( Render::Sampler* sampler, uint32_t rWrapMode, uint32_t sWrapMode, uint32_t tWrapMode )
1122 typedef MessageValue4< RenderManager, Render::Sampler*, uint32_t, uint32_t, uint32_t > DerivedType;
1124 // Reserve some memory inside the render queue
1125 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1127 // Construct message in the render queue memory; note that delete should not be called on the return value
1128 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetWrapMode, sampler, rWrapMode, sWrapMode, tWrapMode );
1131 void UpdateManager::AddPropertyBuffer( OwnerPointer< Render::PropertyBuffer >& propertyBuffer )
1133 // Message has ownership of format while in transit from update -> render
1134 typedef MessageValue1< RenderManager, OwnerPointer< Render::PropertyBuffer > > DerivedType;
1136 // Reserve some memory inside the render queue
1137 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1139 // Construct message in the render queue memory; note that delete should not be called on the return value
1140 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddPropertyBuffer, propertyBuffer );
1143 void UpdateManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer )
1145 typedef MessageValue1< RenderManager, Render::PropertyBuffer* > DerivedType;
1147 // Reserve some memory inside the render queue
1148 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1150 // Construct message in the render queue memory; note that delete should not be called on the return value
1151 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemovePropertyBuffer, propertyBuffer );
1154 void UpdateManager::SetPropertyBufferFormat( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Render::PropertyBuffer::Format>& format )
1156 // Message has ownership of format while in transit from update -> render
1157 typedef MessageValue2< RenderManager, Render::PropertyBuffer*, OwnerPointer< Render::PropertyBuffer::Format > > DerivedType;
1159 // Reserve some memory inside the render queue
1160 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1162 // Construct message in the render queue memory; note that delete should not be called on the return value
1163 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferFormat, propertyBuffer, format );
1166 void UpdateManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Vector<uint8_t> >& data, uint32_t size )
1168 // Message has ownership of format while in transit from update -> render
1169 typedef MessageValue3< RenderManager, Render::PropertyBuffer*, OwnerPointer< Dali::Vector<uint8_t> >, uint32_t > DerivedType;
1171 // Reserve some memory inside the render queue
1172 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1174 // Construct message in the render queue memory; note that delete should not be called on the return value
1175 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferData, propertyBuffer, data, size );
1178 void UpdateManager::AddGeometry( OwnerPointer< Render::Geometry >& geometry )
1180 // Message has ownership of format while in transit from update -> render
1181 typedef MessageValue1< RenderManager, OwnerPointer< Render::Geometry > > DerivedType;
1183 // Reserve some memory inside the render queue
1184 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1186 // Construct message in the render queue memory; note that delete should not be called on the return value
1187 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddGeometry, geometry );
1190 void UpdateManager::RemoveGeometry( Render::Geometry* geometry )
1192 typedef MessageValue1< RenderManager, Render::Geometry* > DerivedType;
1194 // Reserve some memory inside the render queue
1195 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1197 // Construct message in the render queue memory; note that delete should not be called on the return value
1198 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveGeometry, geometry );
1201 void UpdateManager::SetGeometryType( Render::Geometry* geometry, uint32_t geometryType )
1203 typedef MessageValue2< RenderManager, Render::Geometry*, uint32_t > DerivedType;
1205 // Reserve some memory inside the render queue
1206 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1208 // Construct message in the render queue memory; note that delete should not be called on the return value
1209 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetGeometryType, geometry, geometryType );
1212 void UpdateManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector<uint16_t>& indices )
1214 typedef IndexBufferMessage< RenderManager > DerivedType;
1216 // Reserve some memory inside the render queue
1217 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1219 // Construct message in the render queue memory; note that delete should not be called on the return value
1220 new (slot) DerivedType( &mImpl->renderManager, geometry, indices );
1223 void UpdateManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1225 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1227 // Reserve some memory inside the render queue
1228 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1230 // Construct message in the render queue memory; note that delete should not be called on the return value
1231 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveVertexBuffer, geometry, propertyBuffer );
1234 void UpdateManager::AttachVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1236 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1238 // Reserve some memory inside the render queue
1239 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1241 // Construct message in the render queue memory; note that delete should not be called on the return value
1242 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AttachVertexBuffer, geometry, propertyBuffer );
1245 void UpdateManager::AddTexture( OwnerPointer< Render::Texture >& texture )
1247 // Message has ownership of Texture while in transit from update -> render
1248 typedef MessageValue1< RenderManager, OwnerPointer< Render::Texture > > DerivedType;
1250 // Reserve some memory inside the render queue
1251 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1253 // Construct message in the render queue memory; note that delete should not be called on the return value
1254 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddTexture, texture );
1257 void UpdateManager::RemoveTexture( Render::Texture* texture)
1259 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1261 // Reserve some memory inside the render queue
1262 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1264 // Construct message in the render queue memory; note that delete should not be called on the return value
1265 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveTexture, texture );
1268 void UpdateManager::UploadTexture( Render::Texture* texture, PixelDataPtr pixelData, const Texture::UploadParams& params )
1270 typedef MessageValue3< RenderManager, Render::Texture*, PixelDataPtr, Texture::UploadParams > DerivedType;
1272 // Reserve some memory inside the message queue
1273 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1275 // Construct message in the message queue memory; note that delete should not be called on the return value
1276 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::UploadTexture, texture, pixelData, params );
1279 void UpdateManager::GenerateMipmaps( Render::Texture* texture )
1281 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1283 // Reserve some memory inside the render queue
1284 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1286 // Construct message in the render queue memory; note that delete should not be called on the return value
1287 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::GenerateMipmaps, texture );
1290 void UpdateManager::AddFrameBuffer( Render::FrameBuffer* frameBuffer )
1292 typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType;
1294 // Reserve some memory inside the render queue
1295 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1297 // Construct message in the render queue memory; note that delete should not be called on the return value
1298 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddFrameBuffer, frameBuffer );
1301 void UpdateManager::RemoveFrameBuffer( Render::FrameBuffer* frameBuffer)
1303 typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType;
1305 // Reserve some memory inside the render queue
1306 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1308 // Construct message in the render queue memory; note that delete should not be called on the return value
1309 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveFrameBuffer, frameBuffer );
1312 void UpdateManager::AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel, uint32_t layer )
1314 typedef MessageValue4< RenderManager, Render::FrameBuffer*, Render::Texture*, uint32_t, uint32_t > DerivedType;
1316 // Reserve some memory inside the render queue
1317 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1319 // Construct message in the render queue memory; note that delete should not be called on the return value
1320 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AttachColorTextureToFrameBuffer, frameBuffer, texture, mipmapLevel, layer );
1323 } // namespace SceneGraph
1325 } // namespace Internal