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/scene-graph-frame-callback.h>
51 #include <dali/internal/update/manager/update-algorithms.h>
52 #include <dali/internal/update/manager/update-manager-debug.h>
53 #include <dali/internal/update/manager/transform-manager.h>
54 #include <dali/internal/update/nodes/node.h>
55 #include <dali/internal/update/nodes/scene-graph-layer.h>
56 #include <dali/internal/update/queue/update-message-queue.h>
57 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
58 #include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
59 #include <dali/internal/update/render-tasks/scene-graph-camera.h>
61 #include <dali/internal/render/common/render-instruction-container.h>
62 #include <dali/internal/render/common/render-manager.h>
63 #include <dali/internal/render/queue/render-queue.h>
64 #include <dali/internal/render/shaders/scene-graph-shader.h>
66 // Un-comment to enable node tree debug logging
67 //#define NODE_TREE_LOGGING 1
69 #if ( defined( DEBUG_ENABLED ) && defined( NODE_TREE_LOGGING ) )
70 #define SNAPSHOT_NODE_LOGGING \
71 const uint32_t FRAME_COUNT_TRIGGER = 16;\
72 if( mImpl->frameCounter >= FRAME_COUNT_TRIGGER )\
74 for( auto root : mImpl->roots )
78 mImpl->frameCounter = 0;\
79 PrintNodeTree( *root, mSceneGraphBuffers.GetUpdateBufferIndex(), "" );\
83 mImpl->frameCounter++;
85 #define SNAPSHOT_NODE_LOGGING
88 #if defined(DEBUG_ENABLED)
89 extern Debug::Filter* gRenderTaskLogFilter;
93 using namespace Dali::Integration;
94 using Dali::Internal::Update::MessageQueue;
108 * Helper to reset animate-able objects to base values
109 * @param container to iterate over
110 * @param updateBufferIndex to use
113 inline void ResetToBaseValues( OwnerContainer<T*>& container, BufferIndex updateBufferIndex )
115 // Reset animatable properties to base values
116 // use reference to avoid extra copies of the iterator
117 for( auto&& iter : container )
119 iter->ResetToBaseValues( updateBufferIndex );
124 * Helper to Erase an object from OwnerContainer using discard queue
125 * @param container to remove from
126 * @param object to remove
127 * @param discardQueue to put the object to
128 * @param updateBufferIndex to use
131 inline void EraseUsingDiscardQueue( OwnerContainer<T*>& container, T* object, DiscardQueue& discardQueue, BufferIndex updateBufferIndex )
133 DALI_ASSERT_DEBUG( object && "NULL object not allowed" );
135 // need to use the reference version of auto as we need the pointer to the pointer for the Release call below
136 for( auto&& iter : container )
138 if ( iter == object )
140 // Transfer ownership to the discard queue, this keeps the object alive, until the render-thread has finished with it
141 discardQueue.Add( updateBufferIndex, container.Release( &iter ) ); // take the address of the reference to a pointer (iter)
142 return; // return as we only ever remove one object. Iterators to container are now invalidated as well so cannot continue
148 * Descends into node's hierarchy and sorts the children of each child according to their depth-index.
149 * @param[in] node The node whose hierarchy to descend
151 void SortSiblingNodesRecursively( Node& node )
153 NodeContainer& container = node.GetChildren();
154 std::sort( container.Begin(), container.End(),
155 []( Node* a, Node* b ) { return a->GetDepthIndex() < b->GetDepthIndex(); } );
157 // Descend tree and sort as well
158 for( auto&& iter : container )
160 SortSiblingNodesRecursively( *iter );
164 } // unnamed namespace
167 * Structure to contain UpdateManager internal data
169 struct UpdateManager::Impl
171 Impl( NotificationManager& notificationManager,
172 CompleteNotificationInterface& animationPlaylist,
173 PropertyNotifier& propertyNotifier,
174 DiscardQueue& discardQueue,
175 RenderController& renderController,
176 RenderManager& renderManager,
177 RenderQueue& renderQueue,
178 SceneGraphBuffers& sceneGraphBuffers,
179 RenderTaskProcessor& renderTaskProcessor )
180 : renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ),
181 notificationManager( notificationManager ),
183 animationPlaylist( animationPlaylist ),
184 propertyNotifier( propertyNotifier ),
186 discardQueue( discardQueue ),
187 renderController( renderController ),
188 sceneController( NULL ),
189 renderManager( renderManager ),
190 renderQueue( renderQueue ),
191 renderInstructions( renderManager.GetRenderInstructionContainer() ),
192 renderTaskProcessor( renderTaskProcessor ),
193 backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
197 panGestureProcessor( NULL ),
198 messageQueue( renderController, sceneGraphBuffers ),
199 frameCallbackProcessor( NULL ),
200 keepRenderingSeconds( 0.0f ),
201 nodeDirtyFlags( NodePropertyFlags::TRANSFORM ), // set to TransformFlag to ensure full update the first time through Update()
203 renderingBehavior( DevelStage::Rendering::IF_REQUIRED ),
204 animationFinishedDuringUpdate( false ),
205 previousUpdateScene( false ),
206 renderTaskWaiting( false ),
207 renderersAdded( false ),
208 surfaceRectChanged( false )
210 sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue );
212 // create first 'dummy' node
218 // Disconnect render tasks from nodes, before destroying the nodes
219 for( auto taskList : taskLists )
221 RenderTaskList::RenderTaskContainer& tasks = taskList->GetTasks();
222 for ( auto&& task : tasks )
224 task->SetSourceNode( NULL );
228 // UpdateManager owns the Nodes. Although Nodes are pool allocated they contain heap allocated parts
229 // like custom properties, which get released here
230 Vector<Node*>::Iterator iter = nodes.Begin()+1;
231 Vector<Node*>::Iterator endIter = nodes.End();
232 for(;iter!=endIter;++iter)
234 (*iter)->OnDestroy();
238 for( auto root : roots )
243 delete sceneController;
247 * Lazy init for FrameCallbackProcessor.
249 FrameCallbackProcessor& GetFrameCallbackProcessor()
251 if( ! frameCallbackProcessor )
253 frameCallbackProcessor = new FrameCallbackProcessor( transformManager );
255 return *frameCallbackProcessor;
258 SceneGraphBuffers sceneGraphBuffers; ///< Used to keep track of which buffers are being written or read
259 RenderMessageDispatcher renderMessageDispatcher; ///< Used for passing messages to the render-thread
260 NotificationManager& notificationManager; ///< Queues notification messages for the event-thread.
261 TransformManager transformManager; ///< Used to update the transformation matrices of the nodes
262 CompleteNotificationInterface& animationPlaylist; ///< Holds handles to all the animations
263 PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
264 ShaderSaver* shaderSaver; ///< Saves shader binaries.
265 DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
266 RenderController& renderController; ///< render controller
267 SceneControllerImpl* sceneController; ///< scene controller
268 RenderManager& renderManager; ///< This is responsible for rendering the results of each "update"
269 RenderQueue& renderQueue; ///< Used to queue messages for the next render
270 RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions
271 RenderTaskProcessor& renderTaskProcessor; ///< Handles RenderTasks and RenderInstrucitons
273 Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
275 OwnerContainer<RenderTaskList*> taskLists; ///< A container of scene graph render task lists
277 OwnerContainer<Layer*> roots; ///< A container of root nodes (root is a layer). The layers are not stored in the node memory pool.
279 Vector<Node*> nodes; ///< A container of all instantiated nodes
281 std::vector<SortedLayerPointers> sortedLayerLists; ///< A container of lists of Layer pointers sorted by depth (one list of sorted layers per root)
283 OwnerContainer< Camera* > cameras; ///< A container of cameras
284 OwnerContainer< PropertyOwner* > customObjects; ///< A container of owned objects (with custom properties)
286 OwnerContainer< PropertyResetterBase* > propertyResetters; ///< A container of property resetters
287 AnimationContainer animations; ///< A container of owned animations
288 PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
289 OwnerContainer< Renderer* > renderers; ///< A container of owned renderers
290 OwnerContainer< TextureSet* > textureSets; ///< A container of owned texture sets
291 OwnerContainer< Shader* > 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 std::vector<Internal::ShaderDataPtr> renderCompiledShaders; ///< Shaders compiled on Render thread are inserted here for update thread to pass on to event thread.
296 std::vector<Internal::ShaderDataPtr> updateCompiledShaders; ///< Shaders to be sent from Update to Event
297 Mutex compiledShaderMutex; ///< lock to ensure no corruption on the renderCompiledShaders
299 OwnerPointer<FrameCallbackProcessor> frameCallbackProcessor; ///< Owned FrameCallbackProcessor, only created if required.
301 float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
302 NodePropertyFlags nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
303 uint32_t frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
305 DevelStage::Rendering renderingBehavior; ///< Set via DevelStage::SetRenderingBehavior
307 bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
308 bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
309 bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
310 bool renderersAdded; ///< Flag to keep track when renderers have been added to avoid unnecessary processing
311 bool surfaceRectChanged; ///< True if the default surface rect is changed
315 Impl( const Impl& ); ///< Undefined
316 Impl& operator=( const Impl& ); ///< Undefined
319 UpdateManager::UpdateManager( NotificationManager& notificationManager,
320 CompleteNotificationInterface& animationFinishedNotifier,
321 PropertyNotifier& propertyNotifier,
322 DiscardQueue& discardQueue,
323 RenderController& controller,
324 RenderManager& renderManager,
325 RenderQueue& renderQueue,
326 RenderTaskProcessor& renderTaskProcessor )
329 mImpl = new Impl( notificationManager,
330 animationFinishedNotifier,
337 renderTaskProcessor );
341 UpdateManager::~UpdateManager()
346 void UpdateManager::InstallRoot( OwnerPointer<Layer>& layer )
348 DALI_ASSERT_DEBUG( layer->IsLayer() );
349 DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
351 Layer* rootLayer = layer.Release();
353 DALI_ASSERT_DEBUG( std::find( mImpl->roots.begin(), mImpl->roots.end(), rootLayer ) == mImpl->roots.end() && "Root Node already installed" );
355 rootLayer->CreateTransform( &mImpl->transformManager );
356 rootLayer->SetRoot(true);
357 mImpl->roots.PushBack( rootLayer );
360 void UpdateManager::AddNode( OwnerPointer<Node>& node )
362 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
364 // Nodes must be sorted by pointer
365 Node* rawNode = node.Release();
366 Vector<Node*>::Iterator begin = mImpl->nodes.Begin();
367 for( Vector<Node*>::Iterator iter = mImpl->nodes.End()-1; iter >= begin; --iter )
369 if( rawNode > (*iter) )
371 mImpl->nodes.Insert((iter+1), rawNode );
372 rawNode->CreateTransform( &mImpl->transformManager );
378 void UpdateManager::ConnectNode( Node* parent, Node* node )
380 DALI_ASSERT_ALWAYS( NULL != parent );
381 DALI_ASSERT_ALWAYS( NULL != node );
382 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
384 parent->ConnectChild( node );
386 // Inform the frame-callback-processor, if set, about the node-hierarchy changing
387 if( mImpl->frameCallbackProcessor )
389 mImpl->frameCallbackProcessor->NodeHierarchyChanged();
393 void UpdateManager::DisconnectNode( Node* node )
395 Node* parent = node->GetParent();
396 DALI_ASSERT_ALWAYS( NULL != parent );
397 parent->SetDirtyFlag( NodePropertyFlags::CHILD_DELETED ); // make parent dirty so that render items dont get reused
399 parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node );
401 // Inform the frame-callback-processor, if set, about the node-hierarchy changing
402 if( mImpl->frameCallbackProcessor )
404 mImpl->frameCallbackProcessor->NodeHierarchyChanged();
408 void UpdateManager::DestroyNode( Node* node )
410 DALI_ASSERT_ALWAYS( NULL != node );
411 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
413 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
414 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
415 for(;iter!=endIter;++iter)
419 mImpl->nodes.Erase(iter);
424 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
426 // Notify the Node about impending destruction
430 void UpdateManager::AddCamera( OwnerPointer< Camera >& camera )
432 mImpl->cameras.PushBack( camera.Release() ); // takes ownership
435 void UpdateManager::RemoveCamera( const Camera* camera )
437 // Find the camera and destroy it
438 EraseUsingDiscardQueue( mImpl->cameras, const_cast<Camera*>( camera ), mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
441 void UpdateManager::AddObject( OwnerPointer<PropertyOwner>& object )
443 mImpl->customObjects.PushBack( object.Release() );
446 void UpdateManager::RemoveObject( PropertyOwner* object )
448 mImpl->customObjects.EraseObject( object );
451 void UpdateManager::AddRenderTaskList( OwnerPointer<RenderTaskList>& taskList )
453 RenderTaskList* taskListPointer = taskList.Release();
454 taskListPointer->SetRenderMessageDispatcher( &mImpl->renderMessageDispatcher );
455 mImpl->taskLists.PushBack( taskListPointer );
458 void UpdateManager::RemoveRenderTaskList( RenderTaskList* taskList )
460 mImpl->taskLists.EraseObject( taskList );
463 void UpdateManager::AddAnimation( OwnerPointer< SceneGraph::Animation >& animation )
465 mImpl->animations.PushBack( animation.Release() );
468 void UpdateManager::StopAnimation( Animation* animation )
470 DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
472 bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
474 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
477 void UpdateManager::RemoveAnimation( Animation* animation )
479 DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
481 animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
483 DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
486 bool UpdateManager::IsAnimationRunning() const
488 // Find any animation that isn't stopped or paused
489 for ( auto&& iter : mImpl->animations )
491 const Animation::State state = iter->GetState();
493 if (state != Animation::Stopped &&
494 state != Animation::Paused)
496 return true; // stop iteration as soon as first one is found
503 void UpdateManager::AddPropertyResetter( OwnerPointer<PropertyResetterBase>& propertyResetter )
505 propertyResetter->Initialize();
506 mImpl->propertyResetters.PushBack( propertyResetter.Release() );
509 void UpdateManager::AddPropertyNotification( OwnerPointer< PropertyNotification >& propertyNotification )
511 mImpl->propertyNotifications.PushBack( propertyNotification.Release() );
514 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
516 mImpl->propertyNotifications.EraseObject( propertyNotification );
519 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
521 DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
522 propertyNotification->SetNotifyMode( notifyMode );
525 void UpdateManager::AddShader( OwnerPointer< Shader >& shader )
527 mImpl->shaders.PushBack( shader.Release() );
530 void UpdateManager::RemoveShader( Shader* shader )
532 // Find the shader and destroy it
533 EraseUsingDiscardQueue( mImpl->shaders, shader, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
536 void UpdateManager::SetShaderProgram( Shader* shader,
537 Internal::ShaderDataPtr shaderData, bool modifiesGeometry )
542 typedef MessageValue3< Shader, Internal::ShaderDataPtr, ProgramCache*, bool> DerivedType;
544 // Reserve some memory inside the render queue
545 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
547 // Construct message in the render queue memory; note that delete should not be called on the return value
548 new (slot) DerivedType( shader, &Shader::SetProgram, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
552 void UpdateManager::SaveBinary( Internal::ShaderDataPtr shaderData )
554 DALI_ASSERT_DEBUG( shaderData && "No NULL shader data pointers please." );
555 DALI_ASSERT_DEBUG( shaderData->GetBufferSize() > 0 && "Shader binary empty so nothing to save." );
557 // lock as update might be sending previously compiled shaders to event thread
558 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
559 mImpl->renderCompiledShaders.push_back( shaderData );
563 void UpdateManager::SetShaderSaver( ShaderSaver& upstream )
565 mImpl->shaderSaver = &upstream;
568 void UpdateManager::AddRenderer( OwnerPointer< Renderer >& renderer )
570 renderer->ConnectToSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
571 mImpl->renderers.PushBack( renderer.Release() );
572 mImpl->renderersAdded = true;
575 void UpdateManager::RemoveRenderer( Renderer* renderer )
577 // Find the renderer and destroy it
578 EraseUsingDiscardQueue( mImpl->renderers, renderer, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
579 // Need to remove the render object as well
580 renderer->DisconnectFromSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
583 void UpdateManager::SetPanGestureProcessor( PanGesture* panGestureProcessor )
585 DALI_ASSERT_DEBUG( NULL != panGestureProcessor );
587 mImpl->panGestureProcessor = panGestureProcessor;
590 void UpdateManager::AddTextureSet( OwnerPointer< TextureSet >& textureSet )
592 mImpl->textureSets.PushBack( textureSet.Release() );
595 void UpdateManager::RemoveTextureSet( TextureSet* textureSet )
597 mImpl->textureSets.EraseObject( textureSet );
600 uint32_t* UpdateManager::ReserveMessageSlot( uint32_t size, bool updateScene )
602 return mImpl->messageQueue.ReserveMessageSlot( size, updateScene );
605 void UpdateManager::EventProcessingStarted()
607 mImpl->messageQueue.EventProcessingStarted();
610 bool UpdateManager::FlushQueue()
612 return mImpl->messageQueue.FlushQueue();
615 void UpdateManager::ResetProperties( BufferIndex bufferIndex )
617 // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
618 mImpl->animationFinishedDuringUpdate = false;
620 // Reset all animating / constrained properties
621 std::vector<PropertyResetterBase*>toDelete;
622 for( auto&& element : mImpl->propertyResetters )
624 element->ResetToBaseValue( bufferIndex );
625 if( element->IsFinished() )
627 toDelete.push_back( element );
631 // If a resetter is no longer required (the animator or constraint has been removed), delete it.
632 for( auto&& elementPtr : toDelete )
634 mImpl->propertyResetters.EraseObject( elementPtr );
637 // Clear node dirty flags
638 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
639 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
640 for( ;iter != endIter; ++iter )
642 (*iter)->ResetDirtyFlags( bufferIndex );
646 bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, uint32_t lastVSyncTimeMilliseconds, uint32_t nextVSyncTimeMilliseconds )
648 bool gestureUpdated( false );
650 if( mImpl->panGestureProcessor )
652 // gesture processor only supports default properties
653 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
654 gestureUpdated |= mImpl->panGestureProcessor->UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
657 return gestureUpdated;
660 void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
662 AnimationContainer &animations = mImpl->animations;
663 AnimationIter iter = animations.Begin();
664 bool animationLooped = false;
666 while ( iter != animations.End() )
668 Animation* animation = *iter;
669 bool finished = false;
671 bool progressMarkerReached = false;
672 animation->Update( bufferIndex, elapsedSeconds, looped, finished, progressMarkerReached );
674 if ( progressMarkerReached )
676 mImpl->notificationManager.QueueMessage( Internal::NotifyProgressReachedMessage( mImpl->animationPlaylist, animation ) );
679 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
680 animationLooped = animationLooped || looped;
682 // Remove animations that had been destroyed but were still waiting for an update
683 if (animation->GetState() == Animation::Destroyed)
685 iter = animations.Erase(iter);
693 // queue the notification on finished or looped (to update loop count)
694 if ( mImpl->animationFinishedDuringUpdate || animationLooped )
696 // The application should be notified by NotificationManager, in another thread
697 mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationPlaylist );
701 void UpdateManager::ConstrainCustomObjects( BufferIndex bufferIndex )
703 //Constrain custom objects (in construction order)
704 for ( auto&& object : mImpl->customObjects )
706 ConstrainPropertyOwner( *object, bufferIndex );
710 void UpdateManager::ConstrainRenderTasks( BufferIndex bufferIndex )
712 // Constrain render-tasks
713 for( auto taskList : mImpl->taskLists )
715 RenderTaskList::RenderTaskContainer& tasks = taskList->GetTasks();
716 for ( auto&& task : tasks )
718 ConstrainPropertyOwner( *task, bufferIndex );
723 void UpdateManager::ConstrainShaders( BufferIndex bufferIndex )
725 // constrain shaders... (in construction order)
726 for ( auto&& shader : mImpl->shaders )
728 ConstrainPropertyOwner( *shader, bufferIndex );
732 void UpdateManager::ProcessPropertyNotifications( BufferIndex bufferIndex )
734 for( auto&& notification : mImpl->propertyNotifications )
736 bool valid = notification->Check( bufferIndex );
739 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
744 void UpdateManager::ForwardCompiledShadersToEventThread()
746 DALI_ASSERT_DEBUG( (mImpl->shaderSaver != 0) && "shaderSaver should be wired-up during startup." );
747 if( mImpl->shaderSaver )
749 // lock and swap the queues
751 // render might be attempting to send us more binaries at the same time
752 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
753 mImpl->renderCompiledShaders.swap( mImpl->updateCompiledShaders );
756 if( mImpl->updateCompiledShaders.size() > 0 )
758 ShaderSaver& factory = *mImpl->shaderSaver;
759 for( auto&& shader : mImpl->updateCompiledShaders )
761 mImpl->notificationManager.QueueMessage( ShaderCompiledMessage( factory, shader ) );
763 // we don't need them in update anymore
764 mImpl->updateCompiledShaders.clear();
769 void UpdateManager::UpdateRenderers( BufferIndex bufferIndex )
771 for( auto&& renderer : mImpl->renderers )
774 ConstrainPropertyOwner( *renderer, bufferIndex );
776 renderer->PrepareRender( bufferIndex );
780 void UpdateManager::UpdateNodes( BufferIndex bufferIndex )
782 mImpl->nodeDirtyFlags = NodePropertyFlags::NOTHING;
784 for( auto&& rootLayer : mImpl->roots )
786 // Prepare resources, update shaders, for each node
787 // And add the renderers to the sorted layers. Start from root, which is also a layer
788 mImpl->nodeDirtyFlags |= UpdateNodeTree( *rootLayer,
790 mImpl->renderQueue );
794 uint32_t UpdateManager::Update( float elapsedSeconds,
795 uint32_t lastVSyncTimeMilliseconds,
796 uint32_t nextVSyncTimeMilliseconds,
797 bool renderToFboEnabled,
798 bool isRenderingToFbo )
800 const BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
802 //Clear nodes/resources which were previously discarded
803 mImpl->discardQueue.Clear( bufferIndex );
805 //Process Touches & Gestures
806 const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
808 bool updateScene = // The scene-graph requires an update if..
809 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
810 IsAnimationRunning() || // ..at least one animation is running OR
811 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
812 gestureUpdated; // ..a gesture property was updated
815 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
816 // values if the scene was updated in the previous frame.
817 if( updateScene || mImpl->previousUpdateScene )
819 //Reset properties from the previous update
820 ResetProperties( bufferIndex );
821 mImpl->transformManager.ResetToBaseValue();
824 // Process the queued scene messages. Note, MessageQueue::FlushQueue may be called
825 // between calling IsSceneUpdateRequired() above and here, so updateScene should
827 updateScene |= mImpl->messageQueue.ProcessMessages( bufferIndex );
829 //Forward compiled shader programs to event thread for saving
830 ForwardCompiledShadersToEventThread();
832 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
833 // renderer lists if the scene was updated in the previous frame.
834 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
835 if( updateScene || mImpl->previousUpdateScene )
838 Animate( bufferIndex, elapsedSeconds );
840 //Constraint custom objects
841 ConstrainCustomObjects( bufferIndex );
843 //Clear the lists of renderers from the previous update
844 for( auto sortedLayers : mImpl->sortedLayerLists )
846 for( auto&& layer : sortedLayers )
848 layer->ClearRenderables();
852 //Update node hierarchy, apply constraints and perform sorting / culling.
853 //This will populate each Layer with a list of renderers which are ready.
854 UpdateNodes( bufferIndex );
856 //Apply constraints to RenderTasks, shaders
857 ConstrainRenderTasks( bufferIndex );
858 ConstrainShaders( bufferIndex );
860 //Update renderers and apply constraints
861 UpdateRenderers( bufferIndex );
863 // Call the frame-callback-processor if set
864 if( mImpl->frameCallbackProcessor )
866 mImpl->frameCallbackProcessor->Update( bufferIndex, elapsedSeconds );
869 //Update the transformations of all the nodes
870 mImpl->transformManager.Update();
872 //Process Property Notifications
873 ProcessPropertyNotifications( bufferIndex );
876 for( auto&& cameraIterator : mImpl->cameras )
878 cameraIterator->Update( bufferIndex );
881 //Process the RenderTasks if renderers exist. This creates the instructions for rendering the next frame.
882 //reset the update buffer index and make sure there is enough room in the instruction container
883 if( mImpl->renderersAdded )
885 // Calculate how many render tasks we have in total
886 VectorBase::SizeType numberOfRenderTasks = 0;
888 const VectorBase::SizeType taskListCount = mImpl->taskLists.Count();
889 for ( VectorBase::SizeType index = 0u; index < taskListCount; index++ )
891 numberOfRenderTasks += mImpl->taskLists[index]->GetTasks().Count();
894 mImpl->renderInstructions.ResetAndReserve( bufferIndex,
895 static_cast<uint32_t>( numberOfRenderTasks ) );
897 for ( VectorBase::SizeType index = 0u; index < taskListCount; index++ )
899 if ( NULL != mImpl->roots[index] )
901 mImpl->renderTaskProcessor.Process( bufferIndex,
902 *mImpl->taskLists[index],
903 *mImpl->roots[index],
904 mImpl->sortedLayerLists[index],
905 mImpl->renderInstructions,
913 for( auto taskList : mImpl->taskLists )
915 RenderTaskList::RenderTaskContainer& tasks = taskList->GetTasks();
917 // check the countdown and notify
918 bool doRenderOnceNotify = false;
919 mImpl->renderTaskWaiting = false;
920 for ( auto&& renderTask : tasks )
922 renderTask->UpdateState();
924 if( renderTask->IsWaitingToRender() &&
925 renderTask->ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
927 mImpl->renderTaskWaiting = true; // keep update/render threads alive
930 if( renderTask->HasRendered() )
932 doRenderOnceNotify = true;
936 if( doRenderOnceNotify )
938 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
939 mImpl->notificationManager.QueueCompleteNotification( taskList->GetCompleteNotificationInterface() );
943 // Macro is undefined in release build.
944 SNAPSHOT_NODE_LOGGING;
946 // A ResetProperties() may be required in the next frame
947 mImpl->previousUpdateScene = updateScene;
949 // Check whether further updates are required
950 uint32_t keepUpdating = KeepUpdatingCheck( elapsedSeconds );
952 // tell the update manager that we're done so the queue can be given to event thread
953 mImpl->notificationManager.UpdateCompleted();
955 // The update has finished; swap the double-buffering indices
956 mSceneGraphBuffers.Swap();
961 uint32_t UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
963 // Update the duration set via Stage::KeepRendering()
964 if ( mImpl->keepRenderingSeconds > 0.0f )
966 mImpl->keepRenderingSeconds -= elapsedSeconds;
969 uint32_t keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
971 // If the rendering behavior is set to continuously render, then continue to render.
972 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
973 // Keep updating until no messages are received and no animations are running.
974 // If an animation has just finished, update at least once more for Discard end-actions.
975 // No need to check for renderQueue as there is always a render after update and if that
976 // render needs another update it will tell the adaptor to call update again
978 if ( ( mImpl->renderingBehavior == DevelStage::Rendering::CONTINUOUSLY ) ||
979 ( mImpl->keepRenderingSeconds > 0.0f ) )
981 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
984 if ( IsAnimationRunning() ||
985 mImpl->animationFinishedDuringUpdate )
987 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
990 if ( mImpl->renderTaskWaiting )
992 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
995 return keepUpdatingRequest;
998 void UpdateManager::SetBackgroundColor( const Vector4& color )
1000 typedef MessageValue1< RenderManager, Vector4 > DerivedType;
1002 // Reserve some memory inside the render queue
1003 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1005 // Construct message in the render queue memory; note that delete should not be called on the return value
1006 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
1009 void UpdateManager::SetDefaultSurfaceRect( const Rect<int32_t>& rect )
1011 mImpl->surfaceRectChanged = true;
1013 typedef MessageValue1< RenderManager, Rect<int32_t> > DerivedType;
1015 // Reserve some memory inside the render queue
1016 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1018 // Construct message in the render queue memory; note that delete should not be called on the return value
1019 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1022 void UpdateManager::KeepRendering( float durationSeconds )
1024 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1027 void UpdateManager::SetRenderingBehavior( DevelStage::Rendering renderingBehavior )
1029 mImpl->renderingBehavior = renderingBehavior;
1032 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, const Layer* rootLayer )
1034 const VectorBase::SizeType rootCount = mImpl->roots.Count();
1036 // Make sure we reserve the correct size for the container so that
1037 // we can save the sorted layers in the same order as the root layer
1038 mImpl->sortedLayerLists.resize( rootCount );
1040 for ( VectorBase::SizeType rootIndex = 0u; rootIndex < rootCount; rootIndex++ )
1042 Layer* root = mImpl->roots[rootIndex];
1043 if ( root == rootLayer )
1045 mImpl->sortedLayerLists[rootIndex] = layers;
1051 void UpdateManager::SetDepthIndices( OwnerPointer< NodeDepths >& nodeDepths )
1053 // note,this vector is already in depth order. It could be used as-is to
1054 // remove sorting in update algorithm. However, it lacks layer boundary markers.
1055 for( auto&& iter : nodeDepths->nodeDepths )
1057 iter.node->SetDepthIndex( iter.sortedDepth );
1060 for( auto root : mImpl->roots )
1062 // Go through node hierarchy and rearrange siblings according to depth-index
1063 SortSiblingNodesRecursively( *root );
1067 bool UpdateManager::IsDefaultSurfaceRectChanged()
1069 bool surfaceRectChanged = mImpl->surfaceRectChanged;
1072 mImpl->surfaceRectChanged = false;
1074 return surfaceRectChanged;
1077 void UpdateManager::AddFrameCallback( OwnerPointer< FrameCallback >& frameCallback, const Node* rootNode )
1079 mImpl->GetFrameCallbackProcessor().AddFrameCallback( frameCallback, rootNode );
1082 void UpdateManager::RemoveFrameCallback( FrameCallbackInterface* frameCallback )
1084 mImpl->GetFrameCallbackProcessor().RemoveFrameCallback( frameCallback );
1087 void UpdateManager::AddSampler( OwnerPointer< Render::Sampler >& sampler )
1089 // Message has ownership of Sampler while in transit from update to render
1090 typedef MessageValue1< RenderManager, OwnerPointer< Render::Sampler > > DerivedType;
1092 // Reserve some memory inside the render queue
1093 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1095 // Construct message in the render queue memory; note that delete should not be called on the return value
1096 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddSampler, sampler );
1099 void UpdateManager::RemoveSampler( Render::Sampler* sampler )
1101 typedef MessageValue1< RenderManager, Render::Sampler* > DerivedType;
1103 // Reserve some memory inside the render queue
1104 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1106 // Construct message in the render queue memory; note that delete should not be called on the return value
1107 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveSampler, sampler );
1110 void UpdateManager::SetFilterMode( Render::Sampler* sampler, uint32_t minFilterMode, uint32_t magFilterMode )
1112 typedef MessageValue3< RenderManager, Render::Sampler*, uint32_t, uint32_t > DerivedType;
1114 // Reserve some memory inside the render queue
1115 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1117 // Construct message in the render queue memory; note that delete should not be called on the return value
1118 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetFilterMode, sampler, minFilterMode, magFilterMode );
1121 void UpdateManager::SetWrapMode( Render::Sampler* sampler, uint32_t rWrapMode, uint32_t sWrapMode, uint32_t tWrapMode )
1123 typedef MessageValue4< RenderManager, Render::Sampler*, uint32_t, uint32_t, uint32_t > DerivedType;
1125 // Reserve some memory inside the render queue
1126 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1128 // Construct message in the render queue memory; note that delete should not be called on the return value
1129 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetWrapMode, sampler, rWrapMode, sWrapMode, tWrapMode );
1132 void UpdateManager::AddPropertyBuffer( OwnerPointer< Render::PropertyBuffer >& propertyBuffer )
1134 // Message has ownership of format while in transit from update -> render
1135 typedef MessageValue1< RenderManager, OwnerPointer< Render::PropertyBuffer > > DerivedType;
1137 // Reserve some memory inside the render queue
1138 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1140 // Construct message in the render queue memory; note that delete should not be called on the return value
1141 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddPropertyBuffer, propertyBuffer );
1144 void UpdateManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer )
1146 typedef MessageValue1< RenderManager, Render::PropertyBuffer* > DerivedType;
1148 // Reserve some memory inside the render queue
1149 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1151 // Construct message in the render queue memory; note that delete should not be called on the return value
1152 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemovePropertyBuffer, propertyBuffer );
1155 void UpdateManager::SetPropertyBufferFormat( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Render::PropertyBuffer::Format>& format )
1157 // Message has ownership of format while in transit from update -> render
1158 typedef MessageValue2< RenderManager, Render::PropertyBuffer*, OwnerPointer< Render::PropertyBuffer::Format > > DerivedType;
1160 // Reserve some memory inside the render queue
1161 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1163 // Construct message in the render queue memory; note that delete should not be called on the return value
1164 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferFormat, propertyBuffer, format );
1167 void UpdateManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Vector<uint8_t> >& data, uint32_t size )
1169 // Message has ownership of format while in transit from update -> render
1170 typedef MessageValue3< RenderManager, Render::PropertyBuffer*, OwnerPointer< Dali::Vector<uint8_t> >, uint32_t > DerivedType;
1172 // Reserve some memory inside the render queue
1173 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1175 // Construct message in the render queue memory; note that delete should not be called on the return value
1176 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferData, propertyBuffer, data, size );
1179 void UpdateManager::AddGeometry( OwnerPointer< Render::Geometry >& geometry )
1181 // Message has ownership of format while in transit from update -> render
1182 typedef MessageValue1< RenderManager, OwnerPointer< Render::Geometry > > DerivedType;
1184 // Reserve some memory inside the render queue
1185 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1187 // Construct message in the render queue memory; note that delete should not be called on the return value
1188 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddGeometry, geometry );
1191 void UpdateManager::RemoveGeometry( Render::Geometry* geometry )
1193 typedef MessageValue1< RenderManager, Render::Geometry* > DerivedType;
1195 // Reserve some memory inside the render queue
1196 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1198 // Construct message in the render queue memory; note that delete should not be called on the return value
1199 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveGeometry, geometry );
1202 void UpdateManager::SetGeometryType( Render::Geometry* geometry, uint32_t geometryType )
1204 typedef MessageValue2< RenderManager, Render::Geometry*, uint32_t > DerivedType;
1206 // Reserve some memory inside the render queue
1207 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1209 // Construct message in the render queue memory; note that delete should not be called on the return value
1210 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetGeometryType, geometry, geometryType );
1213 void UpdateManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector<uint16_t>& indices )
1215 typedef IndexBufferMessage< RenderManager > DerivedType;
1217 // Reserve some memory inside the render queue
1218 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1220 // Construct message in the render queue memory; note that delete should not be called on the return value
1221 new (slot) DerivedType( &mImpl->renderManager, geometry, indices );
1224 void UpdateManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1226 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1228 // Reserve some memory inside the render queue
1229 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1231 // Construct message in the render queue memory; note that delete should not be called on the return value
1232 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveVertexBuffer, geometry, propertyBuffer );
1235 void UpdateManager::AttachVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1237 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1239 // Reserve some memory inside the render queue
1240 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1242 // Construct message in the render queue memory; note that delete should not be called on the return value
1243 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AttachVertexBuffer, geometry, propertyBuffer );
1246 void UpdateManager::AddTexture( OwnerPointer< Render::Texture >& texture )
1248 // Message has ownership of Texture while in transit from update -> render
1249 typedef MessageValue1< RenderManager, OwnerPointer< Render::Texture > > DerivedType;
1251 // Reserve some memory inside the render queue
1252 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1254 // Construct message in the render queue memory; note that delete should not be called on the return value
1255 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddTexture, texture );
1258 void UpdateManager::RemoveTexture( Render::Texture* texture)
1260 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1262 // Reserve some memory inside the render queue
1263 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1265 // Construct message in the render queue memory; note that delete should not be called on the return value
1266 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveTexture, texture );
1269 void UpdateManager::UploadTexture( Render::Texture* texture, PixelDataPtr pixelData, const Texture::UploadParams& params )
1271 typedef MessageValue3< RenderManager, Render::Texture*, PixelDataPtr, Texture::UploadParams > DerivedType;
1273 // Reserve some memory inside the message queue
1274 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1276 // Construct message in the message queue memory; note that delete should not be called on the return value
1277 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::UploadTexture, texture, pixelData, params );
1280 void UpdateManager::GenerateMipmaps( Render::Texture* texture )
1282 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1284 // Reserve some memory inside the render queue
1285 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1287 // Construct message in the render queue memory; note that delete should not be called on the return value
1288 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::GenerateMipmaps, texture );
1291 void UpdateManager::AddFrameBuffer( Render::FrameBuffer* frameBuffer )
1293 typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType;
1295 // Reserve some memory inside the render queue
1296 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1298 // Construct message in the render queue memory; note that delete should not be called on the return value
1299 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddFrameBuffer, frameBuffer );
1302 void UpdateManager::RemoveFrameBuffer( Render::FrameBuffer* frameBuffer)
1304 typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType;
1306 // Reserve some memory inside the render queue
1307 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1309 // Construct message in the render queue memory; note that delete should not be called on the return value
1310 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveFrameBuffer, frameBuffer );
1313 void UpdateManager::AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel, uint32_t layer )
1315 typedef MessageValue4< RenderManager, Render::FrameBuffer*, Render::Texture*, uint32_t, uint32_t > DerivedType;
1317 // Reserve some memory inside the render queue
1318 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1320 // Construct message in the render queue memory; note that delete should not be called on the return value
1321 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AttachColorTextureToFrameBuffer, frameBuffer, texture, mipmapLevel, layer );
1324 } // namespace SceneGraph
1326 } // namespace Internal