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 bool partialUpdateAvailable )
188 : renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ),
189 notificationManager( notificationManager ),
191 animationPlaylist( animationPlaylist ),
192 propertyNotifier( propertyNotifier ),
194 discardQueue( discardQueue ),
195 renderController( renderController ),
196 sceneController( NULL ),
197 renderManager( renderManager ),
198 renderQueue( renderQueue ),
199 renderInstructions( renderManager.GetRenderInstructionContainer() ),
200 renderTaskProcessor( renderTaskProcessor ),
201 backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
205 panGestureProcessor( NULL ),
206 messageQueue( renderController, sceneGraphBuffers ),
207 frameCallbackProcessor( NULL ),
208 keepRenderingSeconds( 0.0f ),
209 nodeDirtyFlags( NodePropertyFlags::TRANSFORM ), // set to TransformFlag to ensure full update the first time through Update()
211 renderingBehavior( DevelStage::Rendering::IF_REQUIRED ),
212 animationFinishedDuringUpdate( false ),
213 previousUpdateScene( false ),
214 renderTaskWaiting( false ),
215 renderersAdded( false ),
216 surfaceRectChanged( false ),
217 partialUpdateAvailable( partialUpdateAvailable )
219 sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue );
221 // create first 'dummy' node
227 // Disconnect render tasks from nodes, before destroying the nodes
228 for( auto&& scene : scenes )
230 if ( scene && scene->taskList )
232 RenderTaskList::RenderTaskContainer& tasks = scene->taskList->GetTasks();
233 for ( auto&& task : tasks )
235 task->SetSourceNode( NULL );
240 // UpdateManager owns the Nodes. Although Nodes are pool allocated they contain heap allocated parts
241 // like custom properties, which get released here
242 Vector<Node*>::Iterator iter = nodes.Begin()+1;
243 Vector<Node*>::Iterator endIter = nodes.End();
244 for(;iter!=endIter;++iter)
246 (*iter)->OnDestroy();
250 for( auto&& scene : scenes )
252 if ( scene && scene->root )
254 scene->root->OnDestroy();
255 Node::Delete( scene->root );
260 delete sceneController;
264 * Lazy init for FrameCallbackProcessor.
265 * @param[in] updateManager A reference to the update-manager
267 FrameCallbackProcessor& GetFrameCallbackProcessor( UpdateManager& updateManager )
269 if( ! frameCallbackProcessor )
271 frameCallbackProcessor = new FrameCallbackProcessor( updateManager, transformManager );
273 return *frameCallbackProcessor;
276 SceneGraphBuffers sceneGraphBuffers; ///< Used to keep track of which buffers are being written or read
277 RenderMessageDispatcher renderMessageDispatcher; ///< Used for passing messages to the render-thread
278 NotificationManager& notificationManager; ///< Queues notification messages for the event-thread.
279 TransformManager transformManager; ///< Used to update the transformation matrices of the nodes
280 CompleteNotificationInterface& animationPlaylist; ///< Holds handles to all the animations
281 PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
282 ShaderSaver* shaderSaver; ///< Saves shader binaries.
283 DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
284 RenderController& renderController; ///< render controller
285 SceneControllerImpl* sceneController; ///< scene controller
286 RenderManager& renderManager; ///< This is responsible for rendering the results of each "update"
287 RenderQueue& renderQueue; ///< Used to queue messages for the next render
288 RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions
289 RenderTaskProcessor& renderTaskProcessor; ///< Handles RenderTasks and RenderInstrucitons
291 Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
293 using SceneInfoPtr = std::unique_ptr< SceneInfo >;
294 std::vector< SceneInfoPtr > scenes; ///< A container of SceneInfo.
296 Vector<Node*> nodes; ///< A container of all instantiated nodes
298 OwnerContainer< Camera* > cameras; ///< A container of cameras
299 OwnerContainer< PropertyOwner* > customObjects; ///< A container of owned objects (with custom properties)
301 OwnerContainer< PropertyResetterBase* > propertyResetters; ///< A container of property resetters
302 OwnerContainer< Animation* > animations; ///< A container of owned animations
303 PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
304 OwnerContainer< Renderer* > renderers; ///< A container of owned renderers
305 OwnerContainer< TextureSet* > textureSets; ///< A container of owned texture sets
306 OwnerContainer< Shader* > shaders; ///< A container of owned shaders
307 OwnerPointer< PanGesture > panGestureProcessor; ///< Owned pan gesture processor; it lives for the lifecycle of UpdateManager
309 MessageQueue messageQueue; ///< The messages queued from the event-thread
310 std::vector<Internal::ShaderDataPtr> renderCompiledShaders; ///< Shaders compiled on Render thread are inserted here for update thread to pass on to event thread.
311 std::vector<Internal::ShaderDataPtr> updateCompiledShaders; ///< Shaders to be sent from Update to Event
312 Mutex compiledShaderMutex; ///< lock to ensure no corruption on the renderCompiledShaders
314 OwnerPointer<FrameCallbackProcessor> frameCallbackProcessor; ///< Owned FrameCallbackProcessor, only created if required.
316 float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
317 NodePropertyFlags nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
318 uint32_t frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
320 DevelStage::Rendering renderingBehavior; ///< Set via DevelStage::SetRenderingBehavior
322 bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
323 bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
324 bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
325 bool renderersAdded; ///< Flag to keep track when renderers have been added to avoid unnecessary processing
326 bool surfaceRectChanged; ///< True if the default surface rect is changed
327 bool partialUpdateAvailable; ///< Whether the partial update is available
331 Impl( const Impl& ); ///< Undefined
332 Impl& operator=( const Impl& ); ///< Undefined
335 UpdateManager::UpdateManager( NotificationManager& notificationManager,
336 CompleteNotificationInterface& animationFinishedNotifier,
337 PropertyNotifier& propertyNotifier,
338 DiscardQueue& discardQueue,
339 RenderController& controller,
340 RenderManager& renderManager,
341 RenderQueue& renderQueue,
342 RenderTaskProcessor& renderTaskProcessor,
343 bool partialUpdateAvailable )
346 mImpl = new Impl( notificationManager,
347 animationFinishedNotifier,
355 partialUpdateAvailable );
359 UpdateManager::~UpdateManager()
364 void UpdateManager::InstallRoot( OwnerPointer<Layer>& layer )
366 DALI_ASSERT_DEBUG( layer->IsLayer() );
367 DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
369 Layer* rootLayer = layer.Release();
371 DALI_ASSERT_DEBUG( std::find_if( mImpl->scenes.begin(), mImpl->scenes.end(),
372 [rootLayer]( Impl::SceneInfoPtr& scene )
374 return scene && scene->root == rootLayer;
376 ) == mImpl->scenes.end() && "Root Node already installed" );
378 rootLayer->CreateTransform( &mImpl->transformManager );
379 rootLayer->SetRoot(true);
381 mImpl->scenes.emplace_back( new Impl::SceneInfo( rootLayer ) );
384 void UpdateManager::UninstallRoot( Layer* layer )
386 DALI_ASSERT_DEBUG( layer->IsLayer() );
387 DALI_ASSERT_DEBUG( layer->GetParent() == NULL );
389 for (auto iter = mImpl->scenes.begin(); iter != mImpl->scenes.end(); ++iter)
391 if( (*iter) && (*iter)->root == layer )
393 mImpl->scenes.erase( iter );
398 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), layer );
400 // Notify the layer about impending destruction
404 void UpdateManager::AddNode( OwnerPointer<Node>& node )
406 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
408 // Nodes must be sorted by pointer
409 Node* rawNode = node.Release();
410 DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] AddNode\n", rawNode );
412 Vector<Node*>::Iterator begin = mImpl->nodes.Begin();
413 for( Vector<Node*>::Iterator iter = mImpl->nodes.End()-1; iter >= begin; --iter )
415 if( rawNode > (*iter) )
417 mImpl->nodes.Insert((iter+1), rawNode );
418 rawNode->CreateTransform( &mImpl->transformManager );
419 rawNode->SetPartialUpdateAvailable( mImpl->partialUpdateAvailable );
425 void UpdateManager::ConnectNode( Node* parent, Node* node )
427 DALI_ASSERT_ALWAYS( NULL != parent );
428 DALI_ASSERT_ALWAYS( NULL != node );
429 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
431 DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] ConnectNode\n", node );
433 parent->ConnectChild( node );
435 parent->SetPropertyDirty( true );
437 // Inform the frame-callback-processor, if set, about the node-hierarchy changing
438 if( mImpl->frameCallbackProcessor )
440 mImpl->frameCallbackProcessor->NodeHierarchyChanged();
444 void UpdateManager::DisconnectNode( Node* node )
446 DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] DisconnectNode\n", node );
448 Node* parent = node->GetParent();
449 DALI_ASSERT_ALWAYS( NULL != parent );
450 parent->SetDirtyFlag( NodePropertyFlags::CHILD_DELETED ); // make parent dirty so that render items dont get reused
452 parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node );
454 // Inform the frame-callback-processor, if set, about the node-hierarchy changing
455 if( mImpl->frameCallbackProcessor )
457 mImpl->frameCallbackProcessor->NodeHierarchyChanged();
461 void UpdateManager::DestroyNode( Node* node )
463 DALI_ASSERT_ALWAYS( NULL != node );
464 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
466 DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] DestroyNode\n", node );
468 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
469 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
470 for(;iter!=endIter;++iter)
474 mImpl->nodes.Erase(iter);
479 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
481 // Notify the Node about impending destruction
485 void UpdateManager::AddCamera( OwnerPointer< Camera >& camera )
487 mImpl->cameras.PushBack( camera.Release() ); // takes ownership
490 void UpdateManager::RemoveCamera( Camera* camera )
492 // Find the camera and destroy it
493 EraseUsingDiscardQueue( mImpl->cameras, camera, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
496 void UpdateManager::AddObject( OwnerPointer<PropertyOwner>& object )
498 mImpl->customObjects.PushBack( object.Release() );
501 void UpdateManager::RemoveObject( PropertyOwner* object )
503 mImpl->customObjects.EraseObject( object );
506 void UpdateManager::AddRenderTaskList( OwnerPointer<RenderTaskList>& taskList )
508 RenderTaskList* taskListPointer = taskList.Release();
509 taskListPointer->SetRenderMessageDispatcher( &mImpl->renderMessageDispatcher );
511 mImpl->scenes.back()->taskList = taskListPointer;
514 void UpdateManager::RemoveRenderTaskList( RenderTaskList* taskList )
516 for ( auto&& scene : mImpl->scenes )
518 if ( scene && scene->taskList == taskList )
520 scene->taskList.Reset();
526 void UpdateManager::AddAnimation( OwnerPointer< SceneGraph::Animation >& animation )
528 mImpl->animations.PushBack( animation.Release() );
531 void UpdateManager::StopAnimation( Animation* animation )
533 DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
535 bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
537 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
540 void UpdateManager::RemoveAnimation( Animation* animation )
542 DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
544 animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
546 DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
549 bool UpdateManager::IsAnimationRunning() const
551 // Find any animation that isn't stopped or paused
552 for ( auto&& iter : mImpl->animations )
554 const Animation::State state = iter->GetState();
556 if (state != Animation::Stopped &&
557 state != Animation::Paused)
559 return true; // stop iteration as soon as first one is found
566 void UpdateManager::AddPropertyResetter( OwnerPointer<PropertyResetterBase>& propertyResetter )
568 propertyResetter->Initialize();
569 mImpl->propertyResetters.PushBack( propertyResetter.Release() );
572 void UpdateManager::AddPropertyNotification( OwnerPointer< PropertyNotification >& propertyNotification )
574 mImpl->propertyNotifications.PushBack( propertyNotification.Release() );
577 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
579 mImpl->propertyNotifications.EraseObject( propertyNotification );
582 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
584 DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
585 propertyNotification->SetNotifyMode( notifyMode );
588 void UpdateManager::AddShader( OwnerPointer< Shader >& shader )
590 mImpl->shaders.PushBack( shader.Release() );
593 void UpdateManager::RemoveShader( Shader* shader )
595 // Find the shader and destroy it
596 EraseUsingDiscardQueue( mImpl->shaders, shader, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
599 void UpdateManager::SetShaderProgram( Shader* shader,
600 Internal::ShaderDataPtr shaderData, bool modifiesGeometry )
605 typedef MessageValue3< Shader, Internal::ShaderDataPtr, ProgramCache*, bool> DerivedType;
607 // Reserve some memory inside the render queue
608 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
610 // Construct message in the render queue memory; note that delete should not be called on the return value
611 new (slot) DerivedType( shader, &Shader::SetProgram, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
615 void UpdateManager::SaveBinary( Internal::ShaderDataPtr shaderData )
617 DALI_ASSERT_DEBUG( shaderData && "No NULL shader data pointers please." );
618 DALI_ASSERT_DEBUG( shaderData->GetBufferSize() > 0 && "Shader binary empty so nothing to save." );
620 // lock as update might be sending previously compiled shaders to event thread
621 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
622 mImpl->renderCompiledShaders.push_back( shaderData );
626 void UpdateManager::SetShaderSaver( ShaderSaver& upstream )
628 mImpl->shaderSaver = &upstream;
631 void UpdateManager::AddRenderer( OwnerPointer< Renderer >& renderer )
633 DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] AddRenderer\n", renderer.Get() );
635 renderer->ConnectToSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
636 mImpl->renderers.PushBack( renderer.Release() );
637 mImpl->renderersAdded = true;
640 void UpdateManager::RemoveRenderer( Renderer* renderer )
642 DALI_LOG_INFO( gLogFilter, Debug::General, "[%x] RemoveRenderer\n", renderer );
644 // Find the renderer and destroy it
645 EraseUsingDiscardQueue( mImpl->renderers, renderer, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
646 // Need to remove the render object as well
647 renderer->DisconnectFromSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
650 void UpdateManager::SetPanGestureProcessor( PanGesture* panGestureProcessor )
652 DALI_ASSERT_DEBUG( NULL != panGestureProcessor );
654 mImpl->panGestureProcessor = panGestureProcessor;
657 void UpdateManager::AddTextureSet( OwnerPointer< TextureSet >& textureSet )
659 mImpl->textureSets.PushBack( textureSet.Release() );
662 void UpdateManager::RemoveTextureSet( TextureSet* textureSet )
664 mImpl->textureSets.EraseObject( textureSet );
667 uint32_t* UpdateManager::ReserveMessageSlot( uint32_t size, bool updateScene )
669 return mImpl->messageQueue.ReserveMessageSlot( size, updateScene );
672 void UpdateManager::EventProcessingStarted()
674 mImpl->messageQueue.EventProcessingStarted();
677 bool UpdateManager::FlushQueue()
679 return mImpl->messageQueue.FlushQueue();
682 void UpdateManager::ResetProperties( BufferIndex bufferIndex )
684 // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
685 mImpl->animationFinishedDuringUpdate = false;
687 // Reset all animating / constrained properties
688 std::vector<PropertyResetterBase*>toDelete;
689 for( auto&& element : mImpl->propertyResetters )
691 element->ResetToBaseValue( bufferIndex );
692 if( element->IsFinished() )
694 toDelete.push_back( element );
698 // If a resetter is no longer required (the animator or constraint has been removed), delete it.
699 for( auto&& elementPtr : toDelete )
701 mImpl->propertyResetters.EraseObject( elementPtr );
704 // Clear node dirty flags
705 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
706 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
707 for( ;iter != endIter; ++iter )
709 (*iter)->ResetDirtyFlags( bufferIndex );
713 bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, uint32_t lastVSyncTimeMilliseconds, uint32_t nextVSyncTimeMilliseconds )
715 bool gestureUpdated( false );
717 if( mImpl->panGestureProcessor )
719 // gesture processor only supports default properties
720 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
721 gestureUpdated |= mImpl->panGestureProcessor->UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
724 return gestureUpdated;
727 void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
729 auto&& iter = mImpl->animations.Begin();
730 bool animationLooped = false;
732 while ( iter != mImpl->animations.End() )
734 Animation* animation = *iter;
735 bool finished = false;
737 bool progressMarkerReached = false;
738 animation->Update( bufferIndex, elapsedSeconds, looped, finished, progressMarkerReached );
740 if ( progressMarkerReached )
742 mImpl->notificationManager.QueueMessage( Internal::NotifyProgressReachedMessage( mImpl->animationPlaylist, animation ) );
745 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
746 animationLooped = animationLooped || looped;
748 // Remove animations that had been destroyed but were still waiting for an update
749 if (animation->GetState() == Animation::Destroyed)
751 iter = mImpl->animations.Erase(iter);
759 // queue the notification on finished or looped (to update loop count)
760 if ( mImpl->animationFinishedDuringUpdate || animationLooped )
762 // The application should be notified by NotificationManager, in another thread
763 mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationPlaylist );
767 void UpdateManager::ConstrainCustomObjects( BufferIndex bufferIndex )
769 //Constrain custom objects (in construction order)
770 for ( auto&& object : mImpl->customObjects )
772 ConstrainPropertyOwner( *object, bufferIndex );
776 void UpdateManager::ConstrainRenderTasks( BufferIndex bufferIndex )
778 // Constrain render-tasks
779 for ( auto&& scene : mImpl->scenes )
781 if ( scene && scene->taskList )
783 RenderTaskList::RenderTaskContainer& tasks = scene->taskList->GetTasks();
784 for ( auto&& task : tasks )
786 ConstrainPropertyOwner( *task, bufferIndex );
792 void UpdateManager::ConstrainShaders( BufferIndex bufferIndex )
794 // constrain shaders... (in construction order)
795 for ( auto&& shader : mImpl->shaders )
797 ConstrainPropertyOwner( *shader, bufferIndex );
801 void UpdateManager::ProcessPropertyNotifications( BufferIndex bufferIndex )
803 for( auto&& notification : mImpl->propertyNotifications )
805 bool valid = notification->Check( bufferIndex );
808 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
813 void UpdateManager::ForwardCompiledShadersToEventThread()
815 DALI_ASSERT_DEBUG( (mImpl->shaderSaver != 0) && "shaderSaver should be wired-up during startup." );
816 if( mImpl->shaderSaver )
818 // lock and swap the queues
820 // render might be attempting to send us more binaries at the same time
821 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
822 mImpl->renderCompiledShaders.swap( mImpl->updateCompiledShaders );
825 if( mImpl->updateCompiledShaders.size() > 0 )
827 ShaderSaver& factory = *mImpl->shaderSaver;
828 for( auto&& shader : mImpl->updateCompiledShaders )
830 mImpl->notificationManager.QueueMessage( ShaderCompiledMessage( factory, shader ) );
832 // we don't need them in update anymore
833 mImpl->updateCompiledShaders.clear();
838 void UpdateManager::UpdateRenderers( BufferIndex bufferIndex )
840 for( auto&& renderer : mImpl->renderers )
843 ConstrainPropertyOwner( *renderer, bufferIndex );
845 renderer->PrepareRender( bufferIndex );
849 void UpdateManager::UpdateNodes( BufferIndex bufferIndex )
851 mImpl->nodeDirtyFlags = NodePropertyFlags::NOTHING;
853 for ( auto&& scene : mImpl->scenes )
855 if ( scene && scene->root )
857 // Prepare resources, update shaders, for each node
858 // And add the renderers to the sorted layers. Start from root, which is also a layer
859 mImpl->nodeDirtyFlags |= UpdateNodeTree( *scene->root,
861 mImpl->renderQueue );
866 uint32_t UpdateManager::Update( float elapsedSeconds,
867 uint32_t lastVSyncTimeMilliseconds,
868 uint32_t nextVSyncTimeMilliseconds,
869 bool renderToFboEnabled,
870 bool isRenderingToFbo )
872 const BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
874 //Clear nodes/resources which were previously discarded
875 mImpl->discardQueue.Clear( bufferIndex );
877 //Process Touches & Gestures
878 const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
880 bool updateScene = // The scene-graph requires an update if..
881 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
882 IsAnimationRunning() || // ..at least one animation is running OR
883 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
884 gestureUpdated; // ..a gesture property was updated
886 bool keepRendererRendering = false;
888 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
889 // values if the scene was updated in the previous frame.
890 if( updateScene || mImpl->previousUpdateScene )
892 //Reset properties from the previous update
893 ResetProperties( bufferIndex );
894 mImpl->transformManager.ResetToBaseValue();
897 // Process the queued scene messages. Note, MessageQueue::FlushQueue may be called
898 // between calling IsSceneUpdateRequired() above and here, so updateScene should
900 updateScene |= mImpl->messageQueue.ProcessMessages( bufferIndex );
902 //Forward compiled shader programs to event thread for saving
903 ForwardCompiledShadersToEventThread();
905 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
906 // renderer lists if the scene was updated in the previous frame.
907 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
908 if( updateScene || mImpl->previousUpdateScene )
911 Animate( bufferIndex, elapsedSeconds );
913 //Constraint custom objects
914 ConstrainCustomObjects( bufferIndex );
916 //Clear the lists of renderers from the previous update
917 for( auto&& scene : mImpl->scenes )
921 for( auto&& layer : scene->sortedLayerList )
925 layer->ClearRenderables();
931 // Call the frame-callback-processor if set
932 if( mImpl->frameCallbackProcessor )
934 mImpl->frameCallbackProcessor->Update( bufferIndex, elapsedSeconds );
937 //Update node hierarchy, apply constraints and perform sorting / culling.
938 //This will populate each Layer with a list of renderers which are ready.
939 UpdateNodes( bufferIndex );
941 //Apply constraints to RenderTasks, shaders
942 ConstrainRenderTasks( bufferIndex );
943 ConstrainShaders( bufferIndex );
945 //Update renderers and apply constraints
946 UpdateRenderers( bufferIndex );
948 //Update the transformations of all the nodes
949 mImpl->transformManager.Update();
951 //Process Property Notifications
952 ProcessPropertyNotifications( bufferIndex );
955 for( auto&& cameraIterator : mImpl->cameras )
957 cameraIterator->Update( bufferIndex );
960 //Process the RenderTasks if renderers exist. This creates the instructions for rendering the next frame.
961 //reset the update buffer index and make sure there is enough room in the instruction container
962 if( mImpl->renderersAdded )
964 // Calculate how many render tasks we have in total
965 std::size_t numberOfRenderTasks = 0;
966 for (auto&& scene : mImpl->scenes )
968 if ( scene && scene->taskList )
970 numberOfRenderTasks += scene->taskList->GetTasks().Count();
974 mImpl->renderInstructions.ResetAndReserve( bufferIndex,
975 static_cast<uint32_t>( numberOfRenderTasks ) );
977 for ( auto&& scene : mImpl->scenes )
979 if ( scene && scene->root && scene->taskList )
981 keepRendererRendering |= mImpl->renderTaskProcessor.Process( bufferIndex,
984 scene->sortedLayerList,
985 mImpl->renderInstructions,
991 DALI_LOG_INFO( gLogFilter, Debug::General,
992 "Update: numberOfRenderTasks(%d), Render Instructions(%d)\n",
993 numberOfRenderTasks, mImpl->renderInstructions.Count( bufferIndex ) );
997 for ( auto&& scene : mImpl->scenes )
999 if ( scene && scene->root && scene->taskList )
1001 RenderTaskList::RenderTaskContainer& tasks = scene->taskList->GetTasks();
1003 // check the countdown and notify
1004 bool doRenderOnceNotify = false;
1005 mImpl->renderTaskWaiting = false;
1006 for ( auto&& renderTask : tasks )
1008 renderTask->UpdateState();
1010 if( renderTask->IsWaitingToRender() &&
1011 renderTask->ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
1013 mImpl->renderTaskWaiting = true; // keep update/render threads alive
1016 if( renderTask->HasRendered() )
1018 doRenderOnceNotify = true;
1022 if( doRenderOnceNotify )
1024 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
1025 mImpl->notificationManager.QueueCompleteNotification( scene->taskList->GetCompleteNotificationInterface() );
1030 // Macro is undefined in release build.
1031 SNAPSHOT_NODE_LOGGING;
1033 // A ResetProperties() may be required in the next frame
1034 mImpl->previousUpdateScene = updateScene;
1036 // Check whether further updates are required
1037 uint32_t keepUpdating = KeepUpdatingCheck( elapsedSeconds );
1039 if( keepRendererRendering )
1041 keepUpdating |= KeepUpdating::STAGE_KEEP_RENDERING;
1044 // tell the update manager that we're done so the queue can be given to event thread
1045 mImpl->notificationManager.UpdateCompleted();
1047 // The update has finished; swap the double-buffering indices
1048 mSceneGraphBuffers.Swap();
1050 return keepUpdating;
1053 uint32_t UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
1055 // Update the duration set via Stage::KeepRendering()
1056 if ( mImpl->keepRenderingSeconds > 0.0f )
1058 mImpl->keepRenderingSeconds -= elapsedSeconds;
1061 uint32_t keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
1063 // If the rendering behavior is set to continuously render, then continue to render.
1064 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
1065 // Keep updating until no messages are received and no animations are running.
1066 // If an animation has just finished, update at least once more for Discard end-actions.
1067 // No need to check for renderQueue as there is always a render after update and if that
1068 // render needs another update it will tell the adaptor to call update again
1070 if ( ( mImpl->renderingBehavior == DevelStage::Rendering::CONTINUOUSLY ) ||
1071 ( mImpl->keepRenderingSeconds > 0.0f ) )
1073 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
1076 if ( IsAnimationRunning() ||
1077 mImpl->animationFinishedDuringUpdate )
1079 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
1082 if ( mImpl->renderTaskWaiting )
1084 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
1087 return keepUpdatingRequest;
1090 void UpdateManager::SetBackgroundColor( const Vector4& color )
1092 typedef MessageValue1< RenderManager, Vector4 > DerivedType;
1094 // Reserve some memory inside the render queue
1095 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1097 // Construct message in the render queue memory; note that delete should not be called on the return value
1098 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
1101 void UpdateManager::SetDefaultSurfaceRect( const Rect<int32_t>& rect )
1103 mImpl->surfaceRectChanged = true;
1105 typedef MessageValue1< RenderManager, Rect<int32_t> > DerivedType;
1107 // Reserve some memory inside the render queue
1108 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1110 // Construct message in the render queue memory; note that delete should not be called on the return value
1111 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1114 void UpdateManager::SetDefaultSurfaceOrientation( int orientation )
1116 typedef MessageValue1< RenderManager, int > DerivedType;
1118 // Reserve some memory inside the render queue
1119 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1121 // Construct message in the render queue memory; note that delete should not be called on the return value
1122 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceOrientation, orientation );
1125 void UpdateManager::KeepRendering( float durationSeconds )
1127 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1130 void UpdateManager::SetRenderingBehavior( DevelStage::Rendering renderingBehavior )
1132 mImpl->renderingBehavior = renderingBehavior;
1135 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, const Layer* rootLayer )
1137 for ( auto&& scene : mImpl->scenes )
1139 if ( scene && scene->root == rootLayer )
1141 scene->sortedLayerList = layers;
1147 void UpdateManager::SetDepthIndices( OwnerPointer< NodeDepths >& nodeDepths )
1149 // note,this vector is already in depth order. It could be used as-is to
1150 // remove sorting in update algorithm. However, it lacks layer boundary markers.
1151 for( auto&& iter : nodeDepths->nodeDepths )
1153 iter.node->SetDepthIndex( iter.sortedDepth );
1156 for ( auto&& scene : mImpl->scenes )
1160 // Go through node hierarchy and rearrange siblings according to depth-index
1161 SortSiblingNodesRecursively( *scene->root );
1166 bool UpdateManager::IsDefaultSurfaceRectChanged()
1168 bool surfaceRectChanged = mImpl->surfaceRectChanged;
1171 mImpl->surfaceRectChanged = false;
1173 return surfaceRectChanged;
1176 void UpdateManager::AddFrameCallback( OwnerPointer< FrameCallback >& frameCallback, const Node* rootNode )
1178 mImpl->GetFrameCallbackProcessor( *this ).AddFrameCallback( frameCallback, rootNode );
1181 void UpdateManager::RemoveFrameCallback( FrameCallbackInterface* frameCallback )
1183 mImpl->GetFrameCallbackProcessor( *this ).RemoveFrameCallback( frameCallback );
1186 void UpdateManager::AddSampler( OwnerPointer< Render::Sampler >& sampler )
1188 // Message has ownership of Sampler while in transit from update to render
1189 typedef MessageValue1< RenderManager, OwnerPointer< Render::Sampler > > DerivedType;
1191 // Reserve some memory inside the render queue
1192 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1194 // Construct message in the render queue memory; note that delete should not be called on the return value
1195 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddSampler, sampler );
1198 void UpdateManager::RemoveSampler( Render::Sampler* sampler )
1200 typedef MessageValue1< RenderManager, Render::Sampler* > DerivedType;
1202 // Reserve some memory inside the render queue
1203 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1205 // Construct message in the render queue memory; note that delete should not be called on the return value
1206 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveSampler, sampler );
1209 void UpdateManager::SetFilterMode( Render::Sampler* sampler, uint32_t minFilterMode, uint32_t magFilterMode )
1211 typedef MessageValue3< RenderManager, Render::Sampler*, uint32_t, uint32_t > DerivedType;
1213 // Reserve some memory inside the render queue
1214 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1216 // Construct message in the render queue memory; note that delete should not be called on the return value
1217 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetFilterMode, sampler, minFilterMode, magFilterMode );
1220 void UpdateManager::SetWrapMode( Render::Sampler* sampler, uint32_t rWrapMode, uint32_t sWrapMode, uint32_t tWrapMode )
1222 typedef MessageValue4< RenderManager, Render::Sampler*, uint32_t, uint32_t, uint32_t > DerivedType;
1224 // Reserve some memory inside the render queue
1225 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1227 // Construct message in the render queue memory; note that delete should not be called on the return value
1228 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetWrapMode, sampler, rWrapMode, sWrapMode, tWrapMode );
1231 void UpdateManager::AddPropertyBuffer( OwnerPointer< Render::PropertyBuffer >& propertyBuffer )
1233 // Message has ownership of format while in transit from update -> render
1234 typedef MessageValue1< RenderManager, OwnerPointer< Render::PropertyBuffer > > DerivedType;
1236 // Reserve some memory inside the render queue
1237 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1239 // Construct message in the render queue memory; note that delete should not be called on the return value
1240 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddPropertyBuffer, propertyBuffer );
1243 void UpdateManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer )
1245 typedef MessageValue1< RenderManager, Render::PropertyBuffer* > DerivedType;
1247 // Reserve some memory inside the render queue
1248 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1250 // Construct message in the render queue memory; note that delete should not be called on the return value
1251 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemovePropertyBuffer, propertyBuffer );
1254 void UpdateManager::SetPropertyBufferFormat( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Render::PropertyBuffer::Format>& format )
1256 // Message has ownership of format while in transit from update -> render
1257 typedef MessageValue2< RenderManager, Render::PropertyBuffer*, OwnerPointer< Render::PropertyBuffer::Format > > DerivedType;
1259 // Reserve some memory inside the render queue
1260 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1262 // Construct message in the render queue memory; note that delete should not be called on the return value
1263 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferFormat, propertyBuffer, format );
1266 void UpdateManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Vector<uint8_t> >& data, uint32_t size )
1268 // Message has ownership of format while in transit from update -> render
1269 typedef MessageValue3< RenderManager, Render::PropertyBuffer*, OwnerPointer< Dali::Vector<uint8_t> >, uint32_t > DerivedType;
1271 // Reserve some memory inside the render queue
1272 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1274 // Construct message in the render queue memory; note that delete should not be called on the return value
1275 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferData, propertyBuffer, data, size );
1278 void UpdateManager::AddGeometry( OwnerPointer< Render::Geometry >& geometry )
1280 // Message has ownership of format while in transit from update -> render
1281 typedef MessageValue1< RenderManager, OwnerPointer< Render::Geometry > > DerivedType;
1283 // Reserve some memory inside the render queue
1284 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1286 // Construct message in the render queue memory; note that delete should not be called on the return value
1287 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddGeometry, geometry );
1290 void UpdateManager::RemoveGeometry( Render::Geometry* geometry )
1292 typedef MessageValue1< RenderManager, Render::Geometry* > DerivedType;
1294 // Reserve some memory inside the render queue
1295 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1297 // Construct message in the render queue memory; note that delete should not be called on the return value
1298 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveGeometry, geometry );
1301 void UpdateManager::SetGeometryType( Render::Geometry* geometry, uint32_t geometryType )
1303 typedef MessageValue2< RenderManager, Render::Geometry*, uint32_t > DerivedType;
1305 // Reserve some memory inside the render queue
1306 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1308 // Construct message in the render queue memory; note that delete should not be called on the return value
1309 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetGeometryType, geometry, geometryType );
1312 void UpdateManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector<uint16_t>& indices )
1314 typedef IndexBufferMessage< RenderManager > DerivedType;
1316 // Reserve some memory inside the render queue
1317 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1319 // Construct message in the render queue memory; note that delete should not be called on the return value
1320 new (slot) DerivedType( &mImpl->renderManager, geometry, indices );
1323 void UpdateManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1325 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1327 // Reserve some memory inside the render queue
1328 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1330 // Construct message in the render queue memory; note that delete should not be called on the return value
1331 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveVertexBuffer, geometry, propertyBuffer );
1334 void UpdateManager::AttachVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1336 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1338 // Reserve some memory inside the render queue
1339 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1341 // Construct message in the render queue memory; note that delete should not be called on the return value
1342 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AttachVertexBuffer, geometry, propertyBuffer );
1345 void UpdateManager::AddTexture( OwnerPointer< Render::Texture >& texture )
1347 // Message has ownership of Texture while in transit from update -> render
1348 typedef MessageValue1< RenderManager, OwnerPointer< Render::Texture > > DerivedType;
1350 // Reserve some memory inside the render queue
1351 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1353 // Construct message in the render queue memory; note that delete should not be called on the return value
1354 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddTexture, texture );
1357 void UpdateManager::RemoveTexture( Render::Texture* texture)
1359 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1361 // Reserve some memory inside the render queue
1362 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1364 // Construct message in the render queue memory; note that delete should not be called on the return value
1365 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveTexture, texture );
1368 void UpdateManager::UploadTexture( Render::Texture* texture, PixelDataPtr pixelData, const Texture::UploadParams& params )
1370 typedef MessageValue3< RenderManager, Render::Texture*, PixelDataPtr, Texture::UploadParams > DerivedType;
1372 // Reserve some memory inside the message queue
1373 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1375 // Construct message in the message queue memory; note that delete should not be called on the return value
1376 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::UploadTexture, texture, pixelData, params );
1379 void UpdateManager::GenerateMipmaps( Render::Texture* texture )
1381 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1383 // Reserve some memory inside the render queue
1384 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1386 // Construct message in the render queue memory; note that delete should not be called on the return value
1387 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::GenerateMipmaps, texture );
1390 void UpdateManager::AddFrameBuffer( OwnerPointer< Render::FrameBuffer >& frameBuffer )
1392 typedef MessageValue1< RenderManager, OwnerPointer< Render::FrameBuffer > > DerivedType;
1394 // Reserve some memory inside the render queue
1395 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1397 // Construct message in the render queue memory; note that delete should not be called on the return value
1398 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddFrameBuffer, frameBuffer );
1401 void UpdateManager::RemoveFrameBuffer( Render::FrameBuffer* frameBuffer)
1403 typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType;
1405 // Reserve some memory inside the render queue
1406 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1408 // Construct message in the render queue memory; note that delete should not be called on the return value
1409 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveFrameBuffer, frameBuffer );
1412 void UpdateManager::AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel, uint32_t layer )
1414 typedef MessageValue4< RenderManager, Render::FrameBuffer*, Render::Texture*, uint32_t, uint32_t > DerivedType;
1416 // Reserve some memory inside the render queue
1417 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1419 // Construct message in the render queue memory; note that delete should not be called on the return value
1420 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AttachColorTextureToFrameBuffer, frameBuffer, texture, mipmapLevel, layer );
1423 } // namespace SceneGraph
1425 } // namespace Internal