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 all root nodes dirty flags
705 for( auto& scene : mImpl->scenes )
707 auto root = scene->root;
708 root->ResetDirtyFlags( bufferIndex );
711 // Clear node dirty flags
712 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
713 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
714 for( ;iter != endIter; ++iter )
716 (*iter)->ResetDirtyFlags( bufferIndex );
720 bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, uint32_t lastVSyncTimeMilliseconds, uint32_t nextVSyncTimeMilliseconds )
722 bool gestureUpdated( false );
724 if( mImpl->panGestureProcessor )
726 // gesture processor only supports default properties
727 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
728 gestureUpdated |= mImpl->panGestureProcessor->UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
731 return gestureUpdated;
734 void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
736 auto&& iter = mImpl->animations.Begin();
737 bool animationLooped = false;
739 while ( iter != mImpl->animations.End() )
741 Animation* animation = *iter;
742 bool finished = false;
744 bool progressMarkerReached = false;
745 animation->Update( bufferIndex, elapsedSeconds, looped, finished, progressMarkerReached );
747 if ( progressMarkerReached )
749 mImpl->notificationManager.QueueMessage( Internal::NotifyProgressReachedMessage( mImpl->animationPlaylist, animation ) );
752 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
753 animationLooped = animationLooped || looped;
755 // Remove animations that had been destroyed but were still waiting for an update
756 if (animation->GetState() == Animation::Destroyed)
758 iter = mImpl->animations.Erase(iter);
766 // queue the notification on finished or looped (to update loop count)
767 if ( mImpl->animationFinishedDuringUpdate || animationLooped )
769 // The application should be notified by NotificationManager, in another thread
770 mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationPlaylist );
774 void UpdateManager::ConstrainCustomObjects( BufferIndex bufferIndex )
776 //Constrain custom objects (in construction order)
777 for ( auto&& object : mImpl->customObjects )
779 ConstrainPropertyOwner( *object, bufferIndex );
783 void UpdateManager::ConstrainRenderTasks( BufferIndex bufferIndex )
785 // Constrain render-tasks
786 for ( auto&& scene : mImpl->scenes )
788 if ( scene && scene->taskList )
790 RenderTaskList::RenderTaskContainer& tasks = scene->taskList->GetTasks();
791 for ( auto&& task : tasks )
793 ConstrainPropertyOwner( *task, bufferIndex );
799 void UpdateManager::ConstrainShaders( BufferIndex bufferIndex )
801 // constrain shaders... (in construction order)
802 for ( auto&& shader : mImpl->shaders )
804 ConstrainPropertyOwner( *shader, bufferIndex );
808 void UpdateManager::ProcessPropertyNotifications( BufferIndex bufferIndex )
810 for( auto&& notification : mImpl->propertyNotifications )
812 bool valid = notification->Check( bufferIndex );
815 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
820 void UpdateManager::ForwardCompiledShadersToEventThread()
822 DALI_ASSERT_DEBUG( (mImpl->shaderSaver != 0) && "shaderSaver should be wired-up during startup." );
823 if( mImpl->shaderSaver )
825 // lock and swap the queues
827 // render might be attempting to send us more binaries at the same time
828 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
829 mImpl->renderCompiledShaders.swap( mImpl->updateCompiledShaders );
832 if( mImpl->updateCompiledShaders.size() > 0 )
834 ShaderSaver& factory = *mImpl->shaderSaver;
835 for( auto&& shader : mImpl->updateCompiledShaders )
837 mImpl->notificationManager.QueueMessage( ShaderCompiledMessage( factory, shader ) );
839 // we don't need them in update anymore
840 mImpl->updateCompiledShaders.clear();
845 void UpdateManager::UpdateRenderers( BufferIndex bufferIndex )
847 for( auto&& renderer : mImpl->renderers )
850 ConstrainPropertyOwner( *renderer, bufferIndex );
852 renderer->PrepareRender( bufferIndex );
856 void UpdateManager::UpdateNodes( BufferIndex bufferIndex )
858 mImpl->nodeDirtyFlags = NodePropertyFlags::NOTHING;
860 for ( auto&& scene : mImpl->scenes )
862 if ( scene && scene->root )
864 // Prepare resources, update shaders, for each node
865 // And add the renderers to the sorted layers. Start from root, which is also a layer
866 mImpl->nodeDirtyFlags |= UpdateNodeTree( *scene->root,
868 mImpl->renderQueue );
873 uint32_t UpdateManager::Update( float elapsedSeconds,
874 uint32_t lastVSyncTimeMilliseconds,
875 uint32_t nextVSyncTimeMilliseconds,
876 bool renderToFboEnabled,
877 bool isRenderingToFbo )
879 const BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
881 //Clear nodes/resources which were previously discarded
882 mImpl->discardQueue.Clear( bufferIndex );
884 //Process Touches & Gestures
885 const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
887 bool updateScene = // The scene-graph requires an update if..
888 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
889 IsAnimationRunning() || // ..at least one animation is running OR
890 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
891 gestureUpdated; // ..a gesture property was updated
893 bool keepRendererRendering = false;
895 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
896 // values if the scene was updated in the previous frame.
897 if( updateScene || mImpl->previousUpdateScene )
899 //Reset properties from the previous update
900 ResetProperties( bufferIndex );
901 mImpl->transformManager.ResetToBaseValue();
904 // Process the queued scene messages. Note, MessageQueue::FlushQueue may be called
905 // between calling IsSceneUpdateRequired() above and here, so updateScene should
907 updateScene |= mImpl->messageQueue.ProcessMessages( bufferIndex );
909 //Forward compiled shader programs to event thread for saving
910 ForwardCompiledShadersToEventThread();
912 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
913 // renderer lists if the scene was updated in the previous frame.
914 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
915 if( updateScene || mImpl->previousUpdateScene )
918 Animate( bufferIndex, elapsedSeconds );
920 //Constraint custom objects
921 ConstrainCustomObjects( bufferIndex );
923 //Clear the lists of renderers from the previous update
924 for( auto&& scene : mImpl->scenes )
928 for( auto&& layer : scene->sortedLayerList )
932 layer->ClearRenderables();
938 // Call the frame-callback-processor if set
939 if( mImpl->frameCallbackProcessor )
941 mImpl->frameCallbackProcessor->Update( bufferIndex, elapsedSeconds );
944 //Update node hierarchy, apply constraints and perform sorting / culling.
945 //This will populate each Layer with a list of renderers which are ready.
946 UpdateNodes( bufferIndex );
948 //Apply constraints to RenderTasks, shaders
949 ConstrainRenderTasks( bufferIndex );
950 ConstrainShaders( bufferIndex );
952 //Update renderers and apply constraints
953 UpdateRenderers( bufferIndex );
955 //Update the transformations of all the nodes
956 mImpl->transformManager.Update();
958 //Process Property Notifications
959 ProcessPropertyNotifications( bufferIndex );
962 for( auto&& cameraIterator : mImpl->cameras )
964 cameraIterator->Update( bufferIndex );
967 //Process the RenderTasks if renderers exist. This creates the instructions for rendering the next frame.
968 //reset the update buffer index and make sure there is enough room in the instruction container
969 if( mImpl->renderersAdded )
971 // Calculate how many render tasks we have in total
972 std::size_t numberOfRenderTasks = 0;
973 for (auto&& scene : mImpl->scenes )
975 if ( scene && scene->taskList )
977 numberOfRenderTasks += scene->taskList->GetTasks().Count();
981 mImpl->renderInstructions.ResetAndReserve( bufferIndex,
982 static_cast<uint32_t>( numberOfRenderTasks ) );
984 for ( auto&& scene : mImpl->scenes )
986 if ( scene && scene->root && scene->taskList )
988 keepRendererRendering |= mImpl->renderTaskProcessor.Process( bufferIndex,
991 scene->sortedLayerList,
992 mImpl->renderInstructions,
998 DALI_LOG_INFO( gLogFilter, Debug::General,
999 "Update: numberOfRenderTasks(%d), Render Instructions(%d)\n",
1000 numberOfRenderTasks, mImpl->renderInstructions.Count( bufferIndex ) );
1004 for ( auto&& scene : mImpl->scenes )
1006 if ( scene && scene->root && scene->taskList )
1008 RenderTaskList::RenderTaskContainer& tasks = scene->taskList->GetTasks();
1010 // check the countdown and notify
1011 bool doRenderOnceNotify = false;
1012 mImpl->renderTaskWaiting = false;
1013 for ( auto&& renderTask : tasks )
1015 renderTask->UpdateState();
1017 if( renderTask->IsWaitingToRender() &&
1018 renderTask->ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
1020 mImpl->renderTaskWaiting = true; // keep update/render threads alive
1023 if( renderTask->HasRendered() )
1025 doRenderOnceNotify = true;
1029 if( doRenderOnceNotify )
1031 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
1032 mImpl->notificationManager.QueueCompleteNotification( scene->taskList->GetCompleteNotificationInterface() );
1037 // Macro is undefined in release build.
1038 SNAPSHOT_NODE_LOGGING;
1040 // A ResetProperties() may be required in the next frame
1041 mImpl->previousUpdateScene = updateScene;
1043 // Check whether further updates are required
1044 uint32_t keepUpdating = KeepUpdatingCheck( elapsedSeconds );
1046 if( keepRendererRendering )
1048 keepUpdating |= KeepUpdating::STAGE_KEEP_RENDERING;
1050 // Set dirty flags for next frame to continue rendering
1051 mImpl->nodeDirtyFlags |= RenderableUpdateFlags;
1054 // tell the update manager that we're done so the queue can be given to event thread
1055 mImpl->notificationManager.UpdateCompleted();
1057 // The update has finished; swap the double-buffering indices
1058 mSceneGraphBuffers.Swap();
1060 return keepUpdating;
1063 uint32_t UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
1065 // Update the duration set via Stage::KeepRendering()
1066 if ( mImpl->keepRenderingSeconds > 0.0f )
1068 mImpl->keepRenderingSeconds -= elapsedSeconds;
1071 uint32_t keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
1073 // If the rendering behavior is set to continuously render, then continue to render.
1074 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
1075 // Keep updating until no messages are received and no animations are running.
1076 // If an animation has just finished, update at least once more for Discard end-actions.
1077 // No need to check for renderQueue as there is always a render after update and if that
1078 // render needs another update it will tell the adaptor to call update again
1080 if ( ( mImpl->renderingBehavior == DevelStage::Rendering::CONTINUOUSLY ) ||
1081 ( mImpl->keepRenderingSeconds > 0.0f ) )
1083 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
1086 if ( IsAnimationRunning() ||
1087 mImpl->animationFinishedDuringUpdate )
1089 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
1092 if ( mImpl->renderTaskWaiting )
1094 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
1097 return keepUpdatingRequest;
1100 void UpdateManager::SetDefaultSurfaceRect( const Rect<int32_t>& rect )
1102 mImpl->surfaceRectChanged = true;
1104 typedef MessageValue1< RenderManager, Rect<int32_t> > DerivedType;
1106 // Reserve some memory inside the render queue
1107 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1109 // Construct message in the render queue memory; note that delete should not be called on the return value
1110 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1113 void UpdateManager::SetDefaultSurfaceOrientation( int orientation )
1115 typedef MessageValue1< RenderManager, int > DerivedType;
1117 // Reserve some memory inside the render queue
1118 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1120 // Construct message in the render queue memory; note that delete should not be called on the return value
1121 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceOrientation, orientation );
1124 void UpdateManager::KeepRendering( float durationSeconds )
1126 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1129 void UpdateManager::SetRenderingBehavior( DevelStage::Rendering renderingBehavior )
1131 mImpl->renderingBehavior = renderingBehavior;
1134 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, const Layer* rootLayer )
1136 for ( auto&& scene : mImpl->scenes )
1138 if ( scene && scene->root == rootLayer )
1140 scene->sortedLayerList = layers;
1146 void UpdateManager::SetDepthIndices( OwnerPointer< NodeDepths >& nodeDepths )
1148 // note,this vector is already in depth order. It could be used as-is to
1149 // remove sorting in update algorithm. However, it lacks layer boundary markers.
1150 for( auto&& iter : nodeDepths->nodeDepths )
1152 iter.node->SetDepthIndex( iter.sortedDepth );
1155 for ( auto&& scene : mImpl->scenes )
1159 // Go through node hierarchy and rearrange siblings according to depth-index
1160 SortSiblingNodesRecursively( *scene->root );
1165 bool UpdateManager::IsDefaultSurfaceRectChanged()
1167 bool surfaceRectChanged = mImpl->surfaceRectChanged;
1170 mImpl->surfaceRectChanged = false;
1172 return surfaceRectChanged;
1175 void UpdateManager::AddFrameCallback( OwnerPointer< FrameCallback >& frameCallback, const Node* rootNode )
1177 mImpl->GetFrameCallbackProcessor( *this ).AddFrameCallback( frameCallback, rootNode );
1180 void UpdateManager::RemoveFrameCallback( FrameCallbackInterface* frameCallback )
1182 mImpl->GetFrameCallbackProcessor( *this ).RemoveFrameCallback( frameCallback );
1185 void UpdateManager::AddSampler( OwnerPointer< Render::Sampler >& sampler )
1187 // Message has ownership of Sampler while in transit from update to render
1188 typedef MessageValue1< RenderManager, OwnerPointer< Render::Sampler > > DerivedType;
1190 // Reserve some memory inside the render queue
1191 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1193 // Construct message in the render queue memory; note that delete should not be called on the return value
1194 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddSampler, sampler );
1197 void UpdateManager::RemoveSampler( Render::Sampler* sampler )
1199 typedef MessageValue1< RenderManager, Render::Sampler* > DerivedType;
1201 // Reserve some memory inside the render queue
1202 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1204 // Construct message in the render queue memory; note that delete should not be called on the return value
1205 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveSampler, sampler );
1208 void UpdateManager::SetFilterMode( Render::Sampler* sampler, uint32_t minFilterMode, uint32_t magFilterMode )
1210 typedef MessageValue3< RenderManager, Render::Sampler*, uint32_t, uint32_t > DerivedType;
1212 // Reserve some memory inside the render queue
1213 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1215 // Construct message in the render queue memory; note that delete should not be called on the return value
1216 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetFilterMode, sampler, minFilterMode, magFilterMode );
1219 void UpdateManager::SetWrapMode( Render::Sampler* sampler, uint32_t rWrapMode, uint32_t sWrapMode, uint32_t tWrapMode )
1221 typedef MessageValue4< RenderManager, Render::Sampler*, uint32_t, uint32_t, uint32_t > DerivedType;
1223 // Reserve some memory inside the render queue
1224 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1226 // Construct message in the render queue memory; note that delete should not be called on the return value
1227 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetWrapMode, sampler, rWrapMode, sWrapMode, tWrapMode );
1230 void UpdateManager::AddPropertyBuffer( OwnerPointer< Render::PropertyBuffer >& propertyBuffer )
1232 // Message has ownership of format while in transit from update -> render
1233 typedef MessageValue1< RenderManager, OwnerPointer< Render::PropertyBuffer > > DerivedType;
1235 // Reserve some memory inside the render queue
1236 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1238 // Construct message in the render queue memory; note that delete should not be called on the return value
1239 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddPropertyBuffer, propertyBuffer );
1242 void UpdateManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer )
1244 typedef MessageValue1< RenderManager, Render::PropertyBuffer* > DerivedType;
1246 // Reserve some memory inside the render queue
1247 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1249 // Construct message in the render queue memory; note that delete should not be called on the return value
1250 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemovePropertyBuffer, propertyBuffer );
1253 void UpdateManager::SetPropertyBufferFormat( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Render::PropertyBuffer::Format>& format )
1255 // Message has ownership of format while in transit from update -> render
1256 typedef MessageValue2< RenderManager, Render::PropertyBuffer*, OwnerPointer< Render::PropertyBuffer::Format > > DerivedType;
1258 // Reserve some memory inside the render queue
1259 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1261 // Construct message in the render queue memory; note that delete should not be called on the return value
1262 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferFormat, propertyBuffer, format );
1265 void UpdateManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Vector<uint8_t> >& data, uint32_t size )
1267 // Message has ownership of format while in transit from update -> render
1268 typedef MessageValue3< RenderManager, Render::PropertyBuffer*, OwnerPointer< Dali::Vector<uint8_t> >, uint32_t > DerivedType;
1270 // Reserve some memory inside the render queue
1271 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1273 // Construct message in the render queue memory; note that delete should not be called on the return value
1274 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferData, propertyBuffer, data, size );
1277 void UpdateManager::AddGeometry( OwnerPointer< Render::Geometry >& geometry )
1279 // Message has ownership of format while in transit from update -> render
1280 typedef MessageValue1< RenderManager, OwnerPointer< Render::Geometry > > DerivedType;
1282 // Reserve some memory inside the render queue
1283 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1285 // Construct message in the render queue memory; note that delete should not be called on the return value
1286 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddGeometry, geometry );
1289 void UpdateManager::RemoveGeometry( Render::Geometry* geometry )
1291 typedef MessageValue1< RenderManager, Render::Geometry* > DerivedType;
1293 // Reserve some memory inside the render queue
1294 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1296 // Construct message in the render queue memory; note that delete should not be called on the return value
1297 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveGeometry, geometry );
1300 void UpdateManager::SetGeometryType( Render::Geometry* geometry, uint32_t geometryType )
1302 typedef MessageValue2< RenderManager, Render::Geometry*, uint32_t > DerivedType;
1304 // Reserve some memory inside the render queue
1305 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1307 // Construct message in the render queue memory; note that delete should not be called on the return value
1308 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetGeometryType, geometry, geometryType );
1311 void UpdateManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector<uint16_t>& indices )
1313 typedef IndexBufferMessage< RenderManager > DerivedType;
1315 // Reserve some memory inside the render queue
1316 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1318 // Construct message in the render queue memory; note that delete should not be called on the return value
1319 new (slot) DerivedType( &mImpl->renderManager, geometry, indices );
1322 void UpdateManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1324 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1326 // Reserve some memory inside the render queue
1327 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1329 // Construct message in the render queue memory; note that delete should not be called on the return value
1330 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveVertexBuffer, geometry, propertyBuffer );
1333 void UpdateManager::AttachVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1335 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1337 // Reserve some memory inside the render queue
1338 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1340 // Construct message in the render queue memory; note that delete should not be called on the return value
1341 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AttachVertexBuffer, geometry, propertyBuffer );
1344 void UpdateManager::AddTexture( OwnerPointer< Render::Texture >& texture )
1346 // Message has ownership of Texture while in transit from update -> render
1347 typedef MessageValue1< RenderManager, OwnerPointer< Render::Texture > > DerivedType;
1349 // Reserve some memory inside the render queue
1350 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1352 // Construct message in the render queue memory; note that delete should not be called on the return value
1353 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddTexture, texture );
1356 void UpdateManager::RemoveTexture( Render::Texture* texture)
1358 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1360 // Reserve some memory inside the render queue
1361 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1363 // Construct message in the render queue memory; note that delete should not be called on the return value
1364 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveTexture, texture );
1367 void UpdateManager::UploadTexture( Render::Texture* texture, PixelDataPtr pixelData, const Texture::UploadParams& params )
1369 typedef MessageValue3< RenderManager, Render::Texture*, PixelDataPtr, Texture::UploadParams > DerivedType;
1371 // Reserve some memory inside the message queue
1372 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1374 // Construct message in the message queue memory; note that delete should not be called on the return value
1375 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::UploadTexture, texture, pixelData, params );
1378 void UpdateManager::GenerateMipmaps( Render::Texture* texture )
1380 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1382 // Reserve some memory inside the render queue
1383 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1385 // Construct message in the render queue memory; note that delete should not be called on the return value
1386 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::GenerateMipmaps, texture );
1389 void UpdateManager::AddFrameBuffer( OwnerPointer< Render::FrameBuffer >& frameBuffer )
1391 typedef MessageValue1< RenderManager, OwnerPointer< Render::FrameBuffer > > DerivedType;
1393 // Reserve some memory inside the render queue
1394 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1396 // Construct message in the render queue memory; note that delete should not be called on the return value
1397 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddFrameBuffer, frameBuffer );
1400 void UpdateManager::RemoveFrameBuffer( Render::FrameBuffer* frameBuffer)
1402 typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType;
1404 // Reserve some memory inside the render queue
1405 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1407 // Construct message in the render queue memory; note that delete should not be called on the return value
1408 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveFrameBuffer, frameBuffer );
1411 void UpdateManager::AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel, uint32_t layer )
1413 typedef MessageValue4< RenderManager, Render::FrameBuffer*, Render::Texture*, uint32_t, uint32_t > DerivedType;
1415 // Reserve some memory inside the render queue
1416 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1418 // Construct message in the render queue memory; note that delete should not be called on the return value
1419 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AttachColorTextureToFrameBuffer, frameBuffer, texture, mipmapLevel, layer );
1422 } // namespace SceneGraph
1424 } // namespace Internal