2 * Copyright (c) 2019 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&& scene : mImpl->scenes )
76 if ( scene && scene->root )\
78 mImpl->frameCounter = 0;\
79 PrintNodeTree( *scene->root, mSceneGraphBuffers.GetUpdateBufferIndex(), "" );\
83 mImpl->frameCounter++;
85 #define SNAPSHOT_NODE_LOGGING
88 #if defined(DEBUG_ENABLED)
89 extern Debug::Filter* gRenderTaskLogFilter;
92 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_UPDATE_MANAGER" );
93 } // unnamed namespace
97 using namespace Dali::Integration;
98 using Dali::Internal::Update::MessageQueue;
112 * Helper to Erase an object from OwnerContainer using discard queue
113 * @param container to remove from
114 * @param object to remove
115 * @param discardQueue to put the object to
116 * @param updateBufferIndex to use
119 inline void EraseUsingDiscardQueue( OwnerContainer<T*>& container, T* object, DiscardQueue& discardQueue, BufferIndex updateBufferIndex )
121 DALI_ASSERT_DEBUG( object && "NULL object not allowed" );
123 // need to use the reference version of auto as we need the pointer to the pointer for the Release call below
124 for( auto&& iter : container )
126 if ( iter == object )
128 // Transfer ownership to the discard queue, this keeps the object alive, until the render-thread has finished with it
129 discardQueue.Add( updateBufferIndex, container.Release( &iter ) ); // take the address of the reference to a pointer (iter)
130 return; // return as we only ever remove one object. Iterators to container are now invalidated as well so cannot continue
136 * Descends into node's hierarchy and sorts the children of each child according to their depth-index.
137 * @param[in] node The node whose hierarchy to descend
139 void SortSiblingNodesRecursively( Node& node )
141 NodeContainer& container = node.GetChildren();
142 std::sort( container.Begin(), container.End(),
143 []( Node* a, Node* b ) { return a->GetDepthIndex() < b->GetDepthIndex(); } );
145 // Descend tree and sort as well
146 for( auto&& iter : container )
148 SortSiblingNodesRecursively( *iter );
152 } // unnamed namespace
155 * Structure to contain UpdateManager internal data
157 struct UpdateManager::Impl
159 // SceneInfo keeps the root node of the Scene, its scene graph render task list, and the list of Layer pointers sorted by depth
162 SceneInfo( Layer* root ) ///< Constructor
167 ~SceneInfo() = default; ///< Default non-virtual destructor
168 SceneInfo( SceneInfo&& rhs ) = default; ///< Move constructor
169 SceneInfo& operator=( SceneInfo&& rhs ) = default; ///< Move assignment operator
170 SceneInfo& operator=( const SceneInfo& rhs ) = delete; ///< Assignment operator
171 SceneInfo( const SceneInfo& rhs ) = delete; ///< Copy constructor
173 Layer* root{ nullptr }; ///< Root node (root is a layer). The layer is not stored in the node memory pool.
174 OwnerPointer< RenderTaskList > taskList; ///< Scene graph render task list
175 SortedLayerPointers sortedLayerList; ///< List of Layer pointers sorted by depth (one list of sorted layers per root)
178 Impl( NotificationManager& notificationManager,
179 CompleteNotificationInterface& animationPlaylist,
180 PropertyNotifier& propertyNotifier,
181 DiscardQueue& discardQueue,
182 RenderController& renderController,
183 RenderManager& renderManager,
184 RenderQueue& renderQueue,
185 SceneGraphBuffers& sceneGraphBuffers,
186 RenderTaskProcessor& renderTaskProcessor )
187 : renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ),
188 notificationManager( notificationManager ),
190 animationPlaylist( animationPlaylist ),
191 propertyNotifier( propertyNotifier ),
193 discardQueue( discardQueue ),
194 renderController( renderController ),
195 sceneController( NULL ),
196 renderManager( renderManager ),
197 renderQueue( renderQueue ),
198 renderInstructions( renderManager.GetRenderInstructionContainer() ),
199 renderTaskProcessor( renderTaskProcessor ),
200 backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
204 panGestureProcessor( NULL ),
205 messageQueue( renderController, sceneGraphBuffers ),
206 frameCallbackProcessor( NULL ),
207 keepRenderingSeconds( 0.0f ),
208 nodeDirtyFlags( NodePropertyFlags::TRANSFORM ), // set to TransformFlag to ensure full update the first time through Update()
210 renderingBehavior( DevelStage::Rendering::IF_REQUIRED ),
211 animationFinishedDuringUpdate( false ),
212 previousUpdateScene( false ),
213 renderTaskWaiting( false ),
214 renderersAdded( false ),
215 surfaceRectChanged( false )
217 sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue );
219 // create first 'dummy' node
225 // Disconnect render tasks from nodes, before destroying the nodes
226 for( auto&& scene : scenes )
228 if ( scene && scene->taskList )
230 RenderTaskList::RenderTaskContainer& tasks = scene->taskList->GetTasks();
231 for ( auto&& task : tasks )
233 task->SetSourceNode( NULL );
238 // UpdateManager owns the Nodes. Although Nodes are pool allocated they contain heap allocated parts
239 // like custom properties, which get released here
240 Vector<Node*>::Iterator iter = nodes.Begin()+1;
241 Vector<Node*>::Iterator endIter = nodes.End();
242 for(;iter!=endIter;++iter)
244 (*iter)->OnDestroy();
248 for( auto&& scene : scenes )
250 if ( scene && scene->root )
252 scene->root->OnDestroy();
253 Node::Delete( scene->root );
258 delete sceneController;
262 * Lazy init for FrameCallbackProcessor.
263 * @param[in] updateManager A reference to the update-manager
265 FrameCallbackProcessor& GetFrameCallbackProcessor( UpdateManager& updateManager )
267 if( ! frameCallbackProcessor )
269 frameCallbackProcessor = new FrameCallbackProcessor( updateManager, transformManager );
271 return *frameCallbackProcessor;
274 SceneGraphBuffers sceneGraphBuffers; ///< Used to keep track of which buffers are being written or read
275 RenderMessageDispatcher renderMessageDispatcher; ///< Used for passing messages to the render-thread
276 NotificationManager& notificationManager; ///< Queues notification messages for the event-thread.
277 TransformManager transformManager; ///< Used to update the transformation matrices of the nodes
278 CompleteNotificationInterface& animationPlaylist; ///< Holds handles to all the animations
279 PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
280 ShaderSaver* shaderSaver; ///< Saves shader binaries.
281 DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
282 RenderController& renderController; ///< render controller
283 SceneControllerImpl* sceneController; ///< scene controller
284 RenderManager& renderManager; ///< This is responsible for rendering the results of each "update"
285 RenderQueue& renderQueue; ///< Used to queue messages for the next render
286 RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions
287 RenderTaskProcessor& renderTaskProcessor; ///< Handles RenderTasks and RenderInstrucitons
289 Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
291 using SceneInfoPtr = std::unique_ptr< SceneInfo >;
292 std::vector< SceneInfoPtr > scenes; ///< A container of SceneInfo.
294 Vector<Node*> nodes; ///< A container of all instantiated nodes
296 OwnerContainer< Camera* > cameras; ///< A container of cameras
297 OwnerContainer< PropertyOwner* > customObjects; ///< A container of owned objects (with custom properties)
299 OwnerContainer< PropertyResetterBase* > propertyResetters; ///< A container of property resetters
300 OwnerContainer< Animation* > animations; ///< A container of owned animations
301 PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
302 OwnerContainer< Renderer* > renderers; ///< A container of owned renderers
303 OwnerContainer< TextureSet* > textureSets; ///< A container of owned texture sets
304 OwnerContainer< Shader* > shaders; ///< A container of owned shaders
305 OwnerPointer< PanGesture > panGestureProcessor; ///< Owned pan gesture processor; it lives for the lifecycle of UpdateManager
307 MessageQueue messageQueue; ///< The messages queued from the event-thread
308 std::vector<Internal::ShaderDataPtr> renderCompiledShaders; ///< Shaders compiled on Render thread are inserted here for update thread to pass on to event thread.
309 std::vector<Internal::ShaderDataPtr> updateCompiledShaders; ///< Shaders to be sent from Update to Event
310 Mutex compiledShaderMutex; ///< lock to ensure no corruption on the renderCompiledShaders
312 OwnerPointer<FrameCallbackProcessor> frameCallbackProcessor; ///< Owned FrameCallbackProcessor, only created if required.
314 float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
315 NodePropertyFlags nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
316 uint32_t frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
318 DevelStage::Rendering renderingBehavior; ///< Set via DevelStage::SetRenderingBehavior
320 bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
321 bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
322 bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
323 bool renderersAdded; ///< Flag to keep track when renderers have been added to avoid unnecessary processing
324 bool surfaceRectChanged; ///< True if the default surface rect is changed
328 Impl( const Impl& ); ///< Undefined
329 Impl& operator=( const Impl& ); ///< Undefined
332 UpdateManager::UpdateManager( NotificationManager& notificationManager,
333 CompleteNotificationInterface& animationFinishedNotifier,
334 PropertyNotifier& propertyNotifier,
335 DiscardQueue& discardQueue,
336 RenderController& controller,
337 RenderManager& renderManager,
338 RenderQueue& renderQueue,
339 RenderTaskProcessor& renderTaskProcessor )
342 mImpl = new Impl( notificationManager,
343 animationFinishedNotifier,
350 renderTaskProcessor );
354 UpdateManager::~UpdateManager()
359 void UpdateManager::InstallRoot( OwnerPointer<Layer>& layer )
361 DALI_ASSERT_DEBUG( layer->IsLayer() );
362 DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
364 Layer* rootLayer = layer.Release();
366 DALI_ASSERT_DEBUG( std::find_if( mImpl->scenes.begin(), mImpl->scenes.end(),
367 [rootLayer]( Impl::SceneInfoPtr& scene )
369 return scene && scene->root == rootLayer;
371 ) == mImpl->scenes.end() && "Root Node already installed" );
373 rootLayer->CreateTransform( &mImpl->transformManager );
374 rootLayer->SetRoot(true);
376 mImpl->scenes.emplace_back( new Impl::SceneInfo( rootLayer ) );
379 void UpdateManager::UninstallRoot( Layer* layer )
381 DALI_ASSERT_DEBUG( layer->IsLayer() );
382 DALI_ASSERT_DEBUG( layer->GetParent() == NULL );
384 for (auto iter = mImpl->scenes.begin(); iter != mImpl->scenes.end(); ++iter)
386 if( (*iter) && (*iter)->root == layer )
388 mImpl->scenes.erase( iter );
393 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), layer );
395 // Notify the layer about impending destruction
399 void UpdateManager::AddNode( OwnerPointer<Node>& node )
401 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
403 // Nodes must be sorted by pointer
404 Node* rawNode = node.Release();
405 DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] AddNode\n", rawNode );
407 Vector<Node*>::Iterator begin = mImpl->nodes.Begin();
408 for( Vector<Node*>::Iterator iter = mImpl->nodes.End()-1; iter >= begin; --iter )
410 if( rawNode > (*iter) )
412 mImpl->nodes.Insert((iter+1), rawNode );
413 rawNode->CreateTransform( &mImpl->transformManager );
419 void UpdateManager::ConnectNode( Node* parent, Node* node )
421 DALI_ASSERT_ALWAYS( NULL != parent );
422 DALI_ASSERT_ALWAYS( NULL != node );
423 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
425 DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] ConnectNode\n", node );
427 parent->ConnectChild( node );
429 // Inform the frame-callback-processor, if set, about the node-hierarchy changing
430 if( mImpl->frameCallbackProcessor )
432 mImpl->frameCallbackProcessor->NodeHierarchyChanged();
436 void UpdateManager::DisconnectNode( Node* node )
438 DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] DisconnectNode\n", node );
440 Node* parent = node->GetParent();
441 DALI_ASSERT_ALWAYS( NULL != parent );
442 parent->SetDirtyFlag( NodePropertyFlags::CHILD_DELETED ); // make parent dirty so that render items dont get reused
444 parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node );
446 // Inform the frame-callback-processor, if set, about the node-hierarchy changing
447 if( mImpl->frameCallbackProcessor )
449 mImpl->frameCallbackProcessor->NodeHierarchyChanged();
453 void UpdateManager::DestroyNode( Node* node )
455 DALI_ASSERT_ALWAYS( NULL != node );
456 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
458 DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] DestroyNode\n", node );
460 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
461 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
462 for(;iter!=endIter;++iter)
466 mImpl->nodes.Erase(iter);
471 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
473 // Notify the Node about impending destruction
477 void UpdateManager::AddCamera( OwnerPointer< Camera >& camera )
479 mImpl->cameras.PushBack( camera.Release() ); // takes ownership
482 void UpdateManager::RemoveCamera( Camera* camera )
484 // Find the camera and destroy it
485 EraseUsingDiscardQueue( mImpl->cameras, camera, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
488 void UpdateManager::AddObject( OwnerPointer<PropertyOwner>& object )
490 mImpl->customObjects.PushBack( object.Release() );
493 void UpdateManager::RemoveObject( PropertyOwner* object )
495 mImpl->customObjects.EraseObject( object );
498 void UpdateManager::AddRenderTaskList( OwnerPointer<RenderTaskList>& taskList )
500 RenderTaskList* taskListPointer = taskList.Release();
501 taskListPointer->SetRenderMessageDispatcher( &mImpl->renderMessageDispatcher );
503 mImpl->scenes.back()->taskList = taskListPointer;
506 void UpdateManager::RemoveRenderTaskList( RenderTaskList* taskList )
508 for ( auto&& scene : mImpl->scenes )
510 if ( scene && scene->taskList == taskList )
512 scene->taskList.Reset();
518 void UpdateManager::AddAnimation( OwnerPointer< SceneGraph::Animation >& animation )
520 mImpl->animations.PushBack( animation.Release() );
523 void UpdateManager::StopAnimation( Animation* animation )
525 DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
527 bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
529 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
532 void UpdateManager::RemoveAnimation( Animation* animation )
534 DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
536 animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
538 DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
541 bool UpdateManager::IsAnimationRunning() const
543 // Find any animation that isn't stopped or paused
544 for ( auto&& iter : mImpl->animations )
546 const Animation::State state = iter->GetState();
548 if (state != Animation::Stopped &&
549 state != Animation::Paused)
551 return true; // stop iteration as soon as first one is found
558 void UpdateManager::AddPropertyResetter( OwnerPointer<PropertyResetterBase>& propertyResetter )
560 propertyResetter->Initialize();
561 mImpl->propertyResetters.PushBack( propertyResetter.Release() );
564 void UpdateManager::AddPropertyNotification( OwnerPointer< PropertyNotification >& propertyNotification )
566 mImpl->propertyNotifications.PushBack( propertyNotification.Release() );
569 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
571 mImpl->propertyNotifications.EraseObject( propertyNotification );
574 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
576 DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
577 propertyNotification->SetNotifyMode( notifyMode );
580 void UpdateManager::AddShader( OwnerPointer< Shader >& shader )
582 mImpl->shaders.PushBack( shader.Release() );
585 void UpdateManager::RemoveShader( Shader* shader )
587 // Find the shader and destroy it
588 EraseUsingDiscardQueue( mImpl->shaders, shader, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
591 void UpdateManager::SetShaderProgram( Shader* shader,
592 Internal::ShaderDataPtr shaderData, bool modifiesGeometry )
597 typedef MessageValue3< Shader, Internal::ShaderDataPtr, ProgramCache*, bool> DerivedType;
599 // Reserve some memory inside the render queue
600 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
602 // Construct message in the render queue memory; note that delete should not be called on the return value
603 new (slot) DerivedType( shader, &Shader::SetProgram, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
607 void UpdateManager::SaveBinary( Internal::ShaderDataPtr shaderData )
609 DALI_ASSERT_DEBUG( shaderData && "No NULL shader data pointers please." );
610 DALI_ASSERT_DEBUG( shaderData->GetBufferSize() > 0 && "Shader binary empty so nothing to save." );
612 // lock as update might be sending previously compiled shaders to event thread
613 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
614 mImpl->renderCompiledShaders.push_back( shaderData );
618 void UpdateManager::SetShaderSaver( ShaderSaver& upstream )
620 mImpl->shaderSaver = &upstream;
623 void UpdateManager::AddRenderer( OwnerPointer< Renderer >& renderer )
625 DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] AddRenderer\n", renderer.Get() );
627 renderer->ConnectToSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
628 mImpl->renderers.PushBack( renderer.Release() );
629 mImpl->renderersAdded = true;
632 void UpdateManager::RemoveRenderer( Renderer* renderer )
634 DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] RemoveRenderer\n", renderer );
636 // Find the renderer and destroy it
637 EraseUsingDiscardQueue( mImpl->renderers, renderer, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
638 // Need to remove the render object as well
639 renderer->DisconnectFromSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
642 void UpdateManager::SetPanGestureProcessor( PanGesture* panGestureProcessor )
644 DALI_ASSERT_DEBUG( NULL != panGestureProcessor );
646 mImpl->panGestureProcessor = panGestureProcessor;
649 void UpdateManager::AddTextureSet( OwnerPointer< TextureSet >& textureSet )
651 mImpl->textureSets.PushBack( textureSet.Release() );
654 void UpdateManager::RemoveTextureSet( TextureSet* textureSet )
656 mImpl->textureSets.EraseObject( textureSet );
659 uint32_t* UpdateManager::ReserveMessageSlot( uint32_t size, bool updateScene )
661 return mImpl->messageQueue.ReserveMessageSlot( size, updateScene );
664 void UpdateManager::EventProcessingStarted()
666 mImpl->messageQueue.EventProcessingStarted();
669 bool UpdateManager::FlushQueue()
671 return mImpl->messageQueue.FlushQueue();
674 void UpdateManager::ResetProperties( BufferIndex bufferIndex )
676 // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
677 mImpl->animationFinishedDuringUpdate = false;
679 // Reset all animating / constrained properties
680 std::vector<PropertyResetterBase*>toDelete;
681 for( auto&& element : mImpl->propertyResetters )
683 element->ResetToBaseValue( bufferIndex );
684 if( element->IsFinished() )
686 toDelete.push_back( element );
690 // If a resetter is no longer required (the animator or constraint has been removed), delete it.
691 for( auto&& elementPtr : toDelete )
693 mImpl->propertyResetters.EraseObject( elementPtr );
696 // Clear node dirty flags
697 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
698 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
699 for( ;iter != endIter; ++iter )
701 (*iter)->ResetDirtyFlags( bufferIndex );
705 bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, uint32_t lastVSyncTimeMilliseconds, uint32_t nextVSyncTimeMilliseconds )
707 bool gestureUpdated( false );
709 if( mImpl->panGestureProcessor )
711 // gesture processor only supports default properties
712 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
713 gestureUpdated |= mImpl->panGestureProcessor->UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
716 return gestureUpdated;
719 void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
721 auto&& iter = mImpl->animations.Begin();
722 bool animationLooped = false;
724 while ( iter != mImpl->animations.End() )
726 Animation* animation = *iter;
727 bool finished = false;
729 bool progressMarkerReached = false;
730 animation->Update( bufferIndex, elapsedSeconds, looped, finished, progressMarkerReached );
732 if ( progressMarkerReached )
734 mImpl->notificationManager.QueueMessage( Internal::NotifyProgressReachedMessage( mImpl->animationPlaylist, animation ) );
737 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
738 animationLooped = animationLooped || looped;
740 // Remove animations that had been destroyed but were still waiting for an update
741 if (animation->GetState() == Animation::Destroyed)
743 iter = mImpl->animations.Erase(iter);
751 // queue the notification on finished or looped (to update loop count)
752 if ( mImpl->animationFinishedDuringUpdate || animationLooped )
754 // The application should be notified by NotificationManager, in another thread
755 mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationPlaylist );
759 void UpdateManager::ConstrainCustomObjects( BufferIndex bufferIndex )
761 //Constrain custom objects (in construction order)
762 for ( auto&& object : mImpl->customObjects )
764 ConstrainPropertyOwner( *object, bufferIndex );
768 void UpdateManager::ConstrainRenderTasks( BufferIndex bufferIndex )
770 // Constrain render-tasks
771 for ( auto&& scene : mImpl->scenes )
773 if ( scene && scene->taskList )
775 RenderTaskList::RenderTaskContainer& tasks = scene->taskList->GetTasks();
776 for ( auto&& task : tasks )
778 ConstrainPropertyOwner( *task, bufferIndex );
784 void UpdateManager::ConstrainShaders( BufferIndex bufferIndex )
786 // constrain shaders... (in construction order)
787 for ( auto&& shader : mImpl->shaders )
789 ConstrainPropertyOwner( *shader, bufferIndex );
793 void UpdateManager::ProcessPropertyNotifications( BufferIndex bufferIndex )
795 for( auto&& notification : mImpl->propertyNotifications )
797 bool valid = notification->Check( bufferIndex );
800 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
805 void UpdateManager::ForwardCompiledShadersToEventThread()
807 DALI_ASSERT_DEBUG( (mImpl->shaderSaver != 0) && "shaderSaver should be wired-up during startup." );
808 if( mImpl->shaderSaver )
810 // lock and swap the queues
812 // render might be attempting to send us more binaries at the same time
813 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
814 mImpl->renderCompiledShaders.swap( mImpl->updateCompiledShaders );
817 if( mImpl->updateCompiledShaders.size() > 0 )
819 ShaderSaver& factory = *mImpl->shaderSaver;
820 for( auto&& shader : mImpl->updateCompiledShaders )
822 mImpl->notificationManager.QueueMessage( ShaderCompiledMessage( factory, shader ) );
824 // we don't need them in update anymore
825 mImpl->updateCompiledShaders.clear();
830 void UpdateManager::UpdateRenderers( BufferIndex bufferIndex )
832 for( auto&& renderer : mImpl->renderers )
835 ConstrainPropertyOwner( *renderer, bufferIndex );
837 renderer->PrepareRender( bufferIndex );
841 void UpdateManager::UpdateNodes( BufferIndex bufferIndex )
843 mImpl->nodeDirtyFlags = NodePropertyFlags::NOTHING;
845 for ( auto&& scene : mImpl->scenes )
847 if ( scene && scene->root )
849 // Prepare resources, update shaders, for each node
850 // And add the renderers to the sorted layers. Start from root, which is also a layer
851 mImpl->nodeDirtyFlags |= UpdateNodeTree( *scene->root,
853 mImpl->renderQueue );
858 uint32_t UpdateManager::Update( float elapsedSeconds,
859 uint32_t lastVSyncTimeMilliseconds,
860 uint32_t nextVSyncTimeMilliseconds,
861 bool renderToFboEnabled,
862 bool isRenderingToFbo )
864 const BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
866 //Clear nodes/resources which were previously discarded
867 mImpl->discardQueue.Clear( bufferIndex );
869 //Process Touches & Gestures
870 const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
872 bool updateScene = // The scene-graph requires an update if..
873 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
874 IsAnimationRunning() || // ..at least one animation is running OR
875 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
876 gestureUpdated; // ..a gesture property was updated
878 bool keepRendererRendering = false;
880 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
881 // values if the scene was updated in the previous frame.
882 if( updateScene || mImpl->previousUpdateScene )
884 //Reset properties from the previous update
885 ResetProperties( bufferIndex );
886 mImpl->transformManager.ResetToBaseValue();
889 // Process the queued scene messages. Note, MessageQueue::FlushQueue may be called
890 // between calling IsSceneUpdateRequired() above and here, so updateScene should
892 updateScene |= mImpl->messageQueue.ProcessMessages( bufferIndex );
894 //Forward compiled shader programs to event thread for saving
895 ForwardCompiledShadersToEventThread();
897 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
898 // renderer lists if the scene was updated in the previous frame.
899 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
900 if( updateScene || mImpl->previousUpdateScene )
903 Animate( bufferIndex, elapsedSeconds );
905 //Constraint custom objects
906 ConstrainCustomObjects( bufferIndex );
908 //Clear the lists of renderers from the previous update
909 for( auto&& scene : mImpl->scenes )
913 for( auto&& layer : scene->sortedLayerList )
917 layer->ClearRenderables();
923 // Call the frame-callback-processor if set
924 if( mImpl->frameCallbackProcessor )
926 mImpl->frameCallbackProcessor->Update( bufferIndex, elapsedSeconds );
929 //Update node hierarchy, apply constraints and perform sorting / culling.
930 //This will populate each Layer with a list of renderers which are ready.
931 UpdateNodes( bufferIndex );
933 //Apply constraints to RenderTasks, shaders
934 ConstrainRenderTasks( bufferIndex );
935 ConstrainShaders( bufferIndex );
937 //Update renderers and apply constraints
938 UpdateRenderers( bufferIndex );
940 //Update the transformations of all the nodes
941 mImpl->transformManager.Update();
943 //Process Property Notifications
944 ProcessPropertyNotifications( bufferIndex );
947 for( auto&& cameraIterator : mImpl->cameras )
949 cameraIterator->Update( bufferIndex );
952 //Process the RenderTasks if renderers exist. This creates the instructions for rendering the next frame.
953 //reset the update buffer index and make sure there is enough room in the instruction container
954 if( mImpl->renderersAdded )
956 // Calculate how many render tasks we have in total
957 std::size_t numberOfRenderTasks = 0;
958 for (auto&& scene : mImpl->scenes )
960 if ( scene && scene->taskList )
962 numberOfRenderTasks += scene->taskList->GetTasks().Count();
966 mImpl->renderInstructions.ResetAndReserve( bufferIndex,
967 static_cast<uint32_t>( numberOfRenderTasks ) );
969 for ( auto&& scene : mImpl->scenes )
971 if ( scene && scene->root && scene->taskList )
973 keepRendererRendering |= mImpl->renderTaskProcessor.Process( bufferIndex,
976 scene->sortedLayerList,
977 mImpl->renderInstructions,
983 DALI_LOG_INFO( gLogFilter, Debug::General,
984 "Update: numberOfRenderTasks(%d), Render Instructions(%d)\n",
985 numberOfRenderTasks, mImpl->renderInstructions.Count( bufferIndex ) );
989 // If any node is dirty, i.e. a property has changed or a child has been deleted, and we do not have any instructions to send, then generate a dummy instruction to force another render
990 if( ( mImpl->nodeDirtyFlags != NodePropertyFlags::NOTHING ) && ( mImpl->renderInstructions.Count( bufferIndex ) == 0 ) )
992 DALI_LOG_INFO( gLogFilter, Debug::General, "Node flags dirty, creating dummy instruction\n" );
993 mImpl->renderInstructions.GetNextInstruction( bufferIndex ); // This creates and adds an empty instruction. We do not need to modify it.
998 for ( auto&& scene : mImpl->scenes )
1000 if ( scene && scene->root && scene->taskList )
1002 RenderTaskList::RenderTaskContainer& tasks = scene->taskList->GetTasks();
1004 // check the countdown and notify
1005 bool doRenderOnceNotify = false;
1006 mImpl->renderTaskWaiting = false;
1007 for ( auto&& renderTask : tasks )
1009 renderTask->UpdateState();
1011 if( renderTask->IsWaitingToRender() &&
1012 renderTask->ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
1014 mImpl->renderTaskWaiting = true; // keep update/render threads alive
1017 if( renderTask->HasRendered() )
1019 doRenderOnceNotify = true;
1023 if( doRenderOnceNotify )
1025 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
1026 mImpl->notificationManager.QueueCompleteNotification( scene->taskList->GetCompleteNotificationInterface() );
1031 // Macro is undefined in release build.
1032 SNAPSHOT_NODE_LOGGING;
1034 // A ResetProperties() may be required in the next frame
1035 mImpl->previousUpdateScene = updateScene;
1037 // Check whether further updates are required
1038 uint32_t keepUpdating = KeepUpdatingCheck( elapsedSeconds );
1040 if( keepRendererRendering )
1042 keepUpdating |= KeepUpdating::STAGE_KEEP_RENDERING;
1045 // tell the update manager that we're done so the queue can be given to event thread
1046 mImpl->notificationManager.UpdateCompleted();
1048 // The update has finished; swap the double-buffering indices
1049 mSceneGraphBuffers.Swap();
1051 return keepUpdating;
1054 uint32_t UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
1056 // Update the duration set via Stage::KeepRendering()
1057 if ( mImpl->keepRenderingSeconds > 0.0f )
1059 mImpl->keepRenderingSeconds -= elapsedSeconds;
1062 uint32_t keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
1064 // If the rendering behavior is set to continuously render, then continue to render.
1065 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
1066 // Keep updating until no messages are received and no animations are running.
1067 // If an animation has just finished, update at least once more for Discard end-actions.
1068 // No need to check for renderQueue as there is always a render after update and if that
1069 // render needs another update it will tell the adaptor to call update again
1071 if ( ( mImpl->renderingBehavior == DevelStage::Rendering::CONTINUOUSLY ) ||
1072 ( mImpl->keepRenderingSeconds > 0.0f ) )
1074 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
1077 if ( IsAnimationRunning() ||
1078 mImpl->animationFinishedDuringUpdate )
1080 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
1083 if ( mImpl->renderTaskWaiting )
1085 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
1088 return keepUpdatingRequest;
1091 void UpdateManager::SetBackgroundColor( const Vector4& color )
1093 typedef MessageValue1< RenderManager, Vector4 > DerivedType;
1095 // Reserve some memory inside the render queue
1096 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1098 // Construct message in the render queue memory; note that delete should not be called on the return value
1099 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
1102 void UpdateManager::SetDefaultSurfaceRect( const Rect<int32_t>& rect )
1104 mImpl->surfaceRectChanged = true;
1106 typedef MessageValue1< RenderManager, Rect<int32_t> > DerivedType;
1108 // Reserve some memory inside the render queue
1109 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1111 // Construct message in the render queue memory; note that delete should not be called on the return value
1112 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1115 void UpdateManager::KeepRendering( float durationSeconds )
1117 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1120 void UpdateManager::SetRenderingBehavior( DevelStage::Rendering renderingBehavior )
1122 mImpl->renderingBehavior = renderingBehavior;
1125 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, const Layer* rootLayer )
1127 for ( auto&& scene : mImpl->scenes )
1129 if ( scene && scene->root == rootLayer )
1131 scene->sortedLayerList = layers;
1137 void UpdateManager::SetDepthIndices( OwnerPointer< NodeDepths >& nodeDepths )
1139 // note,this vector is already in depth order. It could be used as-is to
1140 // remove sorting in update algorithm. However, it lacks layer boundary markers.
1141 for( auto&& iter : nodeDepths->nodeDepths )
1143 iter.node->SetDepthIndex( iter.sortedDepth );
1146 for ( auto&& scene : mImpl->scenes )
1150 // Go through node hierarchy and rearrange siblings according to depth-index
1151 SortSiblingNodesRecursively( *scene->root );
1156 bool UpdateManager::IsDefaultSurfaceRectChanged()
1158 bool surfaceRectChanged = mImpl->surfaceRectChanged;
1161 mImpl->surfaceRectChanged = false;
1163 return surfaceRectChanged;
1166 void UpdateManager::AddFrameCallback( OwnerPointer< FrameCallback >& frameCallback, const Node* rootNode )
1168 mImpl->GetFrameCallbackProcessor( *this ).AddFrameCallback( frameCallback, rootNode );
1171 void UpdateManager::RemoveFrameCallback( FrameCallbackInterface* frameCallback )
1173 mImpl->GetFrameCallbackProcessor( *this ).RemoveFrameCallback( frameCallback );
1176 void UpdateManager::AddSampler( OwnerPointer< Render::Sampler >& sampler )
1178 // Message has ownership of Sampler while in transit from update to render
1179 typedef MessageValue1< RenderManager, OwnerPointer< Render::Sampler > > DerivedType;
1181 // Reserve some memory inside the render queue
1182 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1184 // Construct message in the render queue memory; note that delete should not be called on the return value
1185 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddSampler, sampler );
1188 void UpdateManager::RemoveSampler( Render::Sampler* sampler )
1190 typedef MessageValue1< RenderManager, Render::Sampler* > DerivedType;
1192 // Reserve some memory inside the render queue
1193 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1195 // Construct message in the render queue memory; note that delete should not be called on the return value
1196 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveSampler, sampler );
1199 void UpdateManager::SetFilterMode( Render::Sampler* sampler, uint32_t minFilterMode, uint32_t magFilterMode )
1201 typedef MessageValue3< RenderManager, Render::Sampler*, uint32_t, uint32_t > DerivedType;
1203 // Reserve some memory inside the render queue
1204 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1206 // Construct message in the render queue memory; note that delete should not be called on the return value
1207 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetFilterMode, sampler, minFilterMode, magFilterMode );
1210 void UpdateManager::SetWrapMode( Render::Sampler* sampler, uint32_t rWrapMode, uint32_t sWrapMode, uint32_t tWrapMode )
1212 typedef MessageValue4< RenderManager, Render::Sampler*, uint32_t, uint32_t, uint32_t > DerivedType;
1214 // Reserve some memory inside the render queue
1215 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1217 // Construct message in the render queue memory; note that delete should not be called on the return value
1218 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetWrapMode, sampler, rWrapMode, sWrapMode, tWrapMode );
1221 void UpdateManager::AddPropertyBuffer( OwnerPointer< Render::PropertyBuffer >& propertyBuffer )
1223 // Message has ownership of format while in transit from update -> render
1224 typedef MessageValue1< RenderManager, OwnerPointer< Render::PropertyBuffer > > DerivedType;
1226 // Reserve some memory inside the render queue
1227 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1229 // Construct message in the render queue memory; note that delete should not be called on the return value
1230 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddPropertyBuffer, propertyBuffer );
1233 void UpdateManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer )
1235 typedef MessageValue1< RenderManager, Render::PropertyBuffer* > DerivedType;
1237 // Reserve some memory inside the render queue
1238 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1240 // Construct message in the render queue memory; note that delete should not be called on the return value
1241 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemovePropertyBuffer, propertyBuffer );
1244 void UpdateManager::SetPropertyBufferFormat( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Render::PropertyBuffer::Format>& format )
1246 // Message has ownership of format while in transit from update -> render
1247 typedef MessageValue2< RenderManager, Render::PropertyBuffer*, OwnerPointer< Render::PropertyBuffer::Format > > DerivedType;
1249 // Reserve some memory inside the render queue
1250 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1252 // Construct message in the render queue memory; note that delete should not be called on the return value
1253 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferFormat, propertyBuffer, format );
1256 void UpdateManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Vector<uint8_t> >& data, uint32_t size )
1258 // Message has ownership of format while in transit from update -> render
1259 typedef MessageValue3< RenderManager, Render::PropertyBuffer*, OwnerPointer< Dali::Vector<uint8_t> >, uint32_t > 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::SetPropertyBufferData, propertyBuffer, data, size );
1268 void UpdateManager::AddGeometry( OwnerPointer< Render::Geometry >& geometry )
1270 // Message has ownership of format while in transit from update -> render
1271 typedef MessageValue1< RenderManager, OwnerPointer< Render::Geometry > > DerivedType;
1273 // Reserve some memory inside the render queue
1274 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1276 // Construct message in the render queue memory; note that delete should not be called on the return value
1277 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddGeometry, geometry );
1280 void UpdateManager::RemoveGeometry( Render::Geometry* geometry )
1282 typedef MessageValue1< RenderManager, Render::Geometry* > 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::RemoveGeometry, geometry );
1291 void UpdateManager::SetGeometryType( Render::Geometry* geometry, uint32_t geometryType )
1293 typedef MessageValue2< RenderManager, Render::Geometry*, uint32_t > 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::SetGeometryType, geometry, geometryType );
1302 void UpdateManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector<uint16_t>& indices )
1304 typedef IndexBufferMessage< RenderManager > 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, geometry, indices );
1313 void UpdateManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1315 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > 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::RemoveVertexBuffer, geometry, propertyBuffer );
1324 void UpdateManager::AttachVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1326 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1328 // Reserve some memory inside the render queue
1329 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1331 // Construct message in the render queue memory; note that delete should not be called on the return value
1332 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AttachVertexBuffer, geometry, propertyBuffer );
1335 void UpdateManager::AddTexture( OwnerPointer< Render::Texture >& texture )
1337 // Message has ownership of Texture while in transit from update -> render
1338 typedef MessageValue1< RenderManager, OwnerPointer< Render::Texture > > DerivedType;
1340 // Reserve some memory inside the render queue
1341 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1343 // Construct message in the render queue memory; note that delete should not be called on the return value
1344 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddTexture, texture );
1347 void UpdateManager::RemoveTexture( Render::Texture* texture)
1349 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1351 // Reserve some memory inside the render queue
1352 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1354 // Construct message in the render queue memory; note that delete should not be called on the return value
1355 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveTexture, texture );
1358 void UpdateManager::UploadTexture( Render::Texture* texture, PixelDataPtr pixelData, const Texture::UploadParams& params )
1360 typedef MessageValue3< RenderManager, Render::Texture*, PixelDataPtr, Texture::UploadParams > DerivedType;
1362 // Reserve some memory inside the message queue
1363 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1365 // Construct message in the message queue memory; note that delete should not be called on the return value
1366 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::UploadTexture, texture, pixelData, params );
1369 void UpdateManager::GenerateMipmaps( Render::Texture* texture )
1371 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1373 // Reserve some memory inside the render queue
1374 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1376 // Construct message in the render queue memory; note that delete should not be called on the return value
1377 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::GenerateMipmaps, texture );
1380 void UpdateManager::AddFrameBuffer( OwnerPointer< Render::FrameBuffer >& frameBuffer )
1382 typedef MessageValue1< RenderManager, OwnerPointer< Render::FrameBuffer > > DerivedType;
1384 // Reserve some memory inside the render queue
1385 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1387 // Construct message in the render queue memory; note that delete should not be called on the return value
1388 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddFrameBuffer, frameBuffer );
1391 void UpdateManager::RemoveFrameBuffer( Render::FrameBuffer* frameBuffer)
1393 typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType;
1395 // Reserve some memory inside the render queue
1396 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1398 // Construct message in the render queue memory; note that delete should not be called on the return value
1399 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveFrameBuffer, frameBuffer );
1402 void UpdateManager::AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel, uint32_t layer )
1404 typedef MessageValue4< RenderManager, Render::FrameBuffer*, Render::Texture*, uint32_t, uint32_t > DerivedType;
1406 // Reserve some memory inside the render queue
1407 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1409 // Construct message in the render queue memory; note that delete should not be called on the return value
1410 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AttachColorTextureToFrameBuffer, frameBuffer, texture, mipmapLevel, layer );
1413 } // namespace SceneGraph
1415 } // namespace Internal