2 * Copyright (c) 2018 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/update/manager/update-manager.h>
22 #include <dali/public-api/common/stage.h>
23 #include <dali/devel-api/common/owner-container.h>
24 #include <dali/devel-api/threading/mutex.h>
26 #include <dali/integration-api/core.h>
27 #include <dali/integration-api/render-controller.h>
28 #include <dali/internal/common/shader-data.h>
29 #include <dali/integration-api/debug.h>
31 #include <dali/internal/common/core-impl.h>
32 #include <dali/internal/common/message.h>
34 #include <dali/internal/event/common/notification-manager.h>
35 #include <dali/internal/event/common/property-notification-impl.h>
36 #include <dali/internal/event/common/property-notifier.h>
37 #include <dali/internal/event/effects/shader-factory.h>
38 #include <dali/internal/event/animation/animation-playlist.h>
40 #include <dali/internal/update/animation/scene-graph-animator.h>
41 #include <dali/internal/update/animation/scene-graph-animation.h>
42 #include <dali/internal/update/common/discard-queue.h>
43 #include <dali/internal/update/common/scene-graph-buffers.h>
44 #include <dali/internal/update/controllers/render-message-dispatcher.h>
45 #include <dali/internal/update/controllers/scene-controller-impl.h>
46 #include <dali/internal/update/gestures/scene-graph-pan-gesture.h>
47 #include <dali/internal/update/manager/frame-callback-processor.h>
48 #include <dali/internal/update/manager/render-task-processor.h>
49 #include <dali/internal/update/manager/sorted-layers.h>
50 #include <dali/internal/update/manager/scene-graph-frame-callback.h>
51 #include <dali/internal/update/manager/update-algorithms.h>
52 #include <dali/internal/update/manager/update-manager-debug.h>
53 #include <dali/internal/update/manager/transform-manager.h>
54 #include <dali/internal/update/nodes/node.h>
55 #include <dali/internal/update/nodes/scene-graph-layer.h>
56 #include <dali/internal/update/queue/update-message-queue.h>
57 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
58 #include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
59 #include <dali/internal/update/render-tasks/scene-graph-camera.h>
61 #include <dali/internal/render/common/render-instruction-container.h>
62 #include <dali/internal/render/common/render-manager.h>
63 #include <dali/internal/render/queue/render-queue.h>
64 #include <dali/internal/render/shaders/scene-graph-shader.h>
66 // Un-comment to enable node tree debug logging
67 //#define NODE_TREE_LOGGING 1
69 #if ( defined( DEBUG_ENABLED ) && defined( NODE_TREE_LOGGING ) )
70 #define SNAPSHOT_NODE_LOGGING \
71 const uint32_t FRAME_COUNT_TRIGGER = 16;\
72 if( mImpl->frameCounter >= FRAME_COUNT_TRIGGER )\
74 if ( NULL != mImpl->root )\
76 mImpl->frameCounter = 0;\
77 PrintNodeTree( *mImpl->root, mSceneGraphBuffers.GetUpdateBufferIndex(), "" );\
80 mImpl->frameCounter++;
82 #define SNAPSHOT_NODE_LOGGING
85 #if defined(DEBUG_ENABLED)
86 extern Debug::Filter* gRenderTaskLogFilter;
90 using namespace Dali::Integration;
91 using Dali::Internal::Update::MessageQueue;
105 * Helper to reset animate-able objects to base values
106 * @param container to iterate over
107 * @param updateBufferIndex to use
110 inline void ResetToBaseValues( OwnerContainer<T*>& container, BufferIndex updateBufferIndex )
112 // Reset animatable properties to base values
113 // use reference to avoid extra copies of the iterator
114 for( auto&& iter : container )
116 iter->ResetToBaseValues( updateBufferIndex );
121 * Helper to Erase an object from OwnerContainer using discard queue
122 * @param container to remove from
123 * @param object to remove
124 * @param discardQueue to put the object to
125 * @param updateBufferIndex to use
128 inline void EraseUsingDiscardQueue( OwnerContainer<T*>& container, T* object, DiscardQueue& discardQueue, BufferIndex updateBufferIndex )
130 DALI_ASSERT_DEBUG( object && "NULL object not allowed" );
132 // need to use the reference version of auto as we need the pointer to the pointer for the Release call below
133 for( auto&& iter : container )
135 if ( iter == object )
137 // Transfer ownership to the discard queue, this keeps the object alive, until the render-thread has finished with it
138 discardQueue.Add( updateBufferIndex, container.Release( &iter ) ); // take the address of the reference to a pointer (iter)
139 return; // return as we only ever remove one object. Iterators to container are now invalidated as well so cannot continue
145 * Descends into node's hierarchy and sorts the children of each child according to their depth-index.
146 * @param[in] node The node whose hierarchy to descend
148 void SortSiblingNodesRecursively( Node& node )
150 NodeContainer& container = node.GetChildren();
151 std::sort( container.Begin(), container.End(),
152 []( Node* a, Node* b ) { return a->GetDepthIndex() < b->GetDepthIndex(); } );
154 // Descend tree and sort as well
155 for( auto&& iter : container )
157 SortSiblingNodesRecursively( *iter );
161 } // unnamed namespace
164 * Structure to contain UpdateManager internal data
166 struct UpdateManager::Impl
168 Impl( NotificationManager& notificationManager,
169 CompleteNotificationInterface& animationPlaylist,
170 PropertyNotifier& propertyNotifier,
171 DiscardQueue& discardQueue,
172 RenderController& renderController,
173 RenderManager& renderManager,
174 RenderQueue& renderQueue,
175 SceneGraphBuffers& sceneGraphBuffers,
176 RenderTaskProcessor& renderTaskProcessor )
177 : renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ),
178 notificationManager( notificationManager ),
180 animationPlaylist( animationPlaylist ),
181 propertyNotifier( propertyNotifier ),
183 discardQueue( discardQueue ),
184 renderController( renderController ),
185 sceneController( NULL ),
186 renderManager( renderManager ),
187 renderQueue( renderQueue ),
188 renderInstructions( renderManager.GetRenderInstructionContainer() ),
189 renderTaskProcessor( renderTaskProcessor ),
190 backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
191 taskList( renderMessageDispatcher ),
192 systemLevelTaskList( renderMessageDispatcher ),
194 systemLevelRoot( NULL ),
198 panGestureProcessor( NULL ),
199 messageQueue( renderController, sceneGraphBuffers ),
200 frameCallbackProcessor( NULL ),
201 keepRenderingSeconds( 0.0f ),
202 nodeDirtyFlags( NodePropertyFlags::TRANSFORM ), // set to TransformFlag to ensure full update the first time through Update()
204 renderingBehavior( DevelStage::Rendering::IF_REQUIRED ),
205 animationFinishedDuringUpdate( false ),
206 previousUpdateScene( false ),
207 renderTaskWaiting( false ),
208 renderersAdded( false ),
209 surfaceRectChanged( false )
211 sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue );
213 // create first 'dummy' node
219 // Disconnect render tasks from nodes, before destroying the nodes
220 RenderTaskList::RenderTaskContainer& tasks = taskList.GetTasks();
221 for ( auto&& iter : tasks )
223 iter->SetSourceNode( NULL );
225 // ..repeat for system level RenderTasks
226 RenderTaskList::RenderTaskContainer& systemLevelTasks = systemLevelTaskList.GetTasks();
227 for ( auto&& iter : systemLevelTasks )
229 iter->SetSourceNode( NULL );
232 // UpdateManager owns the Nodes. Although Nodes are pool allocated they contain heap allocated parts
233 // like custom properties, which get released here
234 Vector<Node*>::Iterator iter = nodes.Begin()+1;
235 Vector<Node*>::Iterator endIter = nodes.End();
236 for(;iter!=endIter;++iter)
238 (*iter)->OnDestroy();
242 // If there is root, reset it, otherwise do nothing as rendering was never started
247 Node::Delete( root );
251 if( systemLevelRoot )
253 systemLevelRoot->OnDestroy();
255 Node::Delete( systemLevelRoot );
256 systemLevelRoot = NULL;
259 delete sceneController;
263 * Lazy init for FrameCallbackProcessor.
265 FrameCallbackProcessor& GetFrameCallbackProcessor()
267 if( ! frameCallbackProcessor )
269 frameCallbackProcessor = new FrameCallbackProcessor( transformManager );
271 return *frameCallbackProcessor;
274 SceneGraphBuffers sceneGraphBuffers; ///< Used to keep track of which buffers are being written or read
275 RenderMessageDispatcher renderMessageDispatcher; ///< Used for passing messages to the render-thread
276 NotificationManager& notificationManager; ///< Queues notification messages for the event-thread.
277 TransformManager transformManager; ///< Used to update the transformation matrices of the nodes
278 CompleteNotificationInterface& animationPlaylist; ///< Holds handles to all the animations
279 PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
280 ShaderSaver* shaderSaver; ///< Saves shader binaries.
281 DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
282 RenderController& renderController; ///< render controller
283 SceneControllerImpl* sceneController; ///< scene controller
284 RenderManager& renderManager; ///< This is responsible for rendering the results of each "update"
285 RenderQueue& renderQueue; ///< Used to queue messages for the next render
286 RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions
287 RenderTaskProcessor& renderTaskProcessor; ///< Handles RenderTasks and RenderInstrucitons
289 Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
291 RenderTaskList taskList; ///< The list of scene graph render-tasks
292 RenderTaskList systemLevelTaskList; ///< Separate render-tasks for system-level content
294 Layer* root; ///< The root node (root is a layer)
295 Layer* systemLevelRoot; ///< A separate root-node for system-level content
297 Vector<Node*> nodes; ///< A container of all instantiated nodes
299 SortedLayerPointers sortedLayers; ///< A container of Layer pointers sorted by depth
300 SortedLayerPointers systemLevelSortedLayers; ///< A separate container of system-level Layers
302 OwnerContainer< Camera* > cameras; ///< A container of cameras
303 OwnerContainer< PropertyOwner* > customObjects; ///< A container of owned objects (with custom properties)
305 OwnerContainer< PropertyResetterBase* > propertyResetters; ///< A container of property resetters
306 AnimationContainer animations; ///< A container of owned animations
307 PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
308 OwnerContainer< Renderer* > renderers; ///< A container of owned renderers
309 OwnerContainer< TextureSet* > textureSets; ///< A container of owned texture sets
310 OwnerContainer< Shader* > shaders; ///< A container of owned shaders
311 OwnerPointer< PanGesture > panGestureProcessor; ///< Owned pan gesture processor; it lives for the lifecycle of UpdateManager
313 MessageQueue messageQueue; ///< The messages queued from the event-thread
314 std::vector<Internal::ShaderDataPtr> renderCompiledShaders; ///< Shaders compiled on Render thread are inserted here for update thread to pass on to event thread.
315 std::vector<Internal::ShaderDataPtr> updateCompiledShaders; ///< Shaders to be sent from Update to Event
316 Mutex compiledShaderMutex; ///< lock to ensure no corruption on the renderCompiledShaders
318 OwnerPointer<FrameCallbackProcessor> frameCallbackProcessor; ///< Owned FrameCallbackProcessor, only created if required.
320 float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
321 NodePropertyFlags nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
322 uint32_t frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
324 DevelStage::Rendering renderingBehavior; ///< Set via DevelStage::SetRenderingBehavior
326 bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
327 bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
328 bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
329 bool renderersAdded; ///< Flag to keep track when renderers have been added to avoid unnecessary processing
330 bool surfaceRectChanged; ///< True if the default surface rect is changed
334 Impl( const Impl& ); ///< Undefined
335 Impl& operator=( const Impl& ); ///< Undefined
338 UpdateManager::UpdateManager( NotificationManager& notificationManager,
339 CompleteNotificationInterface& animationFinishedNotifier,
340 PropertyNotifier& propertyNotifier,
341 DiscardQueue& discardQueue,
342 RenderController& controller,
343 RenderManager& renderManager,
344 RenderQueue& renderQueue,
345 RenderTaskProcessor& renderTaskProcessor )
348 mImpl = new Impl( notificationManager,
349 animationFinishedNotifier,
356 renderTaskProcessor );
360 UpdateManager::~UpdateManager()
365 void UpdateManager::InstallRoot( OwnerPointer<Layer>& layer, bool systemLevel )
367 DALI_ASSERT_DEBUG( layer->IsLayer() );
368 DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
372 DALI_ASSERT_DEBUG( mImpl->root == NULL && "Root Node already installed" );
373 mImpl->root = layer.Release();
374 mImpl->root->CreateTransform( &mImpl->transformManager );
375 mImpl->root->SetRoot(true);
379 DALI_ASSERT_DEBUG( mImpl->systemLevelRoot == NULL && "System-level Root Node already installed" );
380 mImpl->systemLevelRoot = layer.Release();
381 mImpl->systemLevelRoot->CreateTransform( &mImpl->transformManager );
382 mImpl->systemLevelRoot->SetRoot(true);
387 void UpdateManager::AddNode( OwnerPointer<Node>& node )
389 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
391 // Nodes must be sorted by pointer
392 Node* rawNode = node.Release();
393 Vector<Node*>::Iterator begin = mImpl->nodes.Begin();
394 for( Vector<Node*>::Iterator iter = mImpl->nodes.End()-1; iter >= begin; --iter )
396 if( rawNode > (*iter) )
398 mImpl->nodes.Insert((iter+1), rawNode );
399 rawNode->CreateTransform( &mImpl->transformManager );
405 void UpdateManager::ConnectNode( Node* parent, Node* node )
407 DALI_ASSERT_ALWAYS( NULL != parent );
408 DALI_ASSERT_ALWAYS( NULL != node );
409 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
411 parent->ConnectChild( node );
413 // Inform the frame-callback-processor, if set, about the node-hierarchy changing
414 if( mImpl->frameCallbackProcessor )
416 mImpl->frameCallbackProcessor->NodeHierarchyChanged();
420 void UpdateManager::DisconnectNode( Node* node )
422 Node* parent = node->GetParent();
423 DALI_ASSERT_ALWAYS( NULL != parent );
424 parent->SetDirtyFlag( NodePropertyFlags::CHILD_DELETED ); // make parent dirty so that render items dont get reused
426 parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node );
428 // Inform the frame-callback-processor, if set, about the node-hierarchy changing
429 if( mImpl->frameCallbackProcessor )
431 mImpl->frameCallbackProcessor->NodeHierarchyChanged();
435 void UpdateManager::DestroyNode( Node* node )
437 DALI_ASSERT_ALWAYS( NULL != node );
438 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
440 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
441 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
442 for(;iter!=endIter;++iter)
446 mImpl->nodes.Erase(iter);
451 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
453 // Notify the Node about impending destruction
457 void UpdateManager::AddCamera( OwnerPointer< Camera >& camera )
459 mImpl->cameras.PushBack( camera.Release() ); // takes ownership
462 void UpdateManager::RemoveCamera( const Camera* camera )
464 // Find the camera and destroy it
465 EraseUsingDiscardQueue( mImpl->cameras, const_cast<Camera*>( camera ), mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
468 void UpdateManager::AddObject( OwnerPointer<PropertyOwner>& object )
470 mImpl->customObjects.PushBack( object.Release() );
473 void UpdateManager::RemoveObject( PropertyOwner* object )
475 mImpl->customObjects.EraseObject( object );
478 void UpdateManager::AddAnimation( OwnerPointer< SceneGraph::Animation >& animation )
480 mImpl->animations.PushBack( animation.Release() );
483 void UpdateManager::StopAnimation( Animation* animation )
485 DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
487 bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
489 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
492 void UpdateManager::RemoveAnimation( Animation* animation )
494 DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
496 animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
498 DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
501 bool UpdateManager::IsAnimationRunning() const
503 // Find any animation that isn't stopped or paused
504 for ( auto&& iter : mImpl->animations )
506 const Animation::State state = iter->GetState();
508 if (state != Animation::Stopped &&
509 state != Animation::Paused)
511 return true; // stop iteration as soon as first one is found
518 void UpdateManager::AddPropertyResetter( OwnerPointer<PropertyResetterBase>& propertyResetter )
520 propertyResetter->Initialize();
521 mImpl->propertyResetters.PushBack( propertyResetter.Release() );
524 void UpdateManager::AddPropertyNotification( OwnerPointer< PropertyNotification >& propertyNotification )
526 mImpl->propertyNotifications.PushBack( propertyNotification.Release() );
529 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
531 mImpl->propertyNotifications.EraseObject( propertyNotification );
534 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
536 DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
537 propertyNotification->SetNotifyMode( notifyMode );
540 void UpdateManager::AddShader( OwnerPointer< Shader >& shader )
542 mImpl->shaders.PushBack( shader.Release() );
545 void UpdateManager::RemoveShader( Shader* shader )
547 // Find the shader and destroy it
548 EraseUsingDiscardQueue( mImpl->shaders, shader, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
551 void UpdateManager::SetShaderProgram( Shader* shader,
552 Internal::ShaderDataPtr shaderData, bool modifiesGeometry )
557 typedef MessageValue3< Shader, Internal::ShaderDataPtr, ProgramCache*, bool> DerivedType;
559 // Reserve some memory inside the render queue
560 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
562 // Construct message in the render queue memory; note that delete should not be called on the return value
563 new (slot) DerivedType( shader, &Shader::SetProgram, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
567 void UpdateManager::SaveBinary( Internal::ShaderDataPtr shaderData )
569 DALI_ASSERT_DEBUG( shaderData && "No NULL shader data pointers please." );
570 DALI_ASSERT_DEBUG( shaderData->GetBufferSize() > 0 && "Shader binary empty so nothing to save." );
572 // lock as update might be sending previously compiled shaders to event thread
573 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
574 mImpl->renderCompiledShaders.push_back( shaderData );
578 void UpdateManager::SetShaderSaver( ShaderSaver& upstream )
580 mImpl->shaderSaver = &upstream;
583 void UpdateManager::AddRenderer( OwnerPointer< Renderer >& renderer )
585 renderer->ConnectToSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
586 mImpl->renderers.PushBack( renderer.Release() );
587 mImpl->renderersAdded = true;
590 void UpdateManager::RemoveRenderer( Renderer* renderer )
592 // Find the renderer and destroy it
593 EraseUsingDiscardQueue( mImpl->renderers, renderer, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
594 // Need to remove the render object as well
595 renderer->DisconnectFromSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
598 void UpdateManager::SetPanGestureProcessor( PanGesture* panGestureProcessor )
600 DALI_ASSERT_DEBUG( NULL != panGestureProcessor );
602 mImpl->panGestureProcessor = panGestureProcessor;
605 void UpdateManager::AddTextureSet( OwnerPointer< TextureSet >& textureSet )
607 mImpl->textureSets.PushBack( textureSet.Release() );
610 void UpdateManager::RemoveTextureSet( TextureSet* textureSet )
612 mImpl->textureSets.EraseObject( textureSet );
615 RenderTaskList* UpdateManager::GetRenderTaskList( bool systemLevel )
619 // copy the list, this is only likely to happen once in application life cycle
620 return &(mImpl->taskList);
624 // copy the list, this is only likely to happen once in application life cycle
625 return &(mImpl->systemLevelTaskList);
629 uint32_t* UpdateManager::ReserveMessageSlot( uint32_t size, bool updateScene )
631 return mImpl->messageQueue.ReserveMessageSlot( size, updateScene );
634 void UpdateManager::EventProcessingStarted()
636 mImpl->messageQueue.EventProcessingStarted();
639 bool UpdateManager::FlushQueue()
641 return mImpl->messageQueue.FlushQueue();
644 void UpdateManager::ResetProperties( BufferIndex bufferIndex )
646 // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
647 mImpl->animationFinishedDuringUpdate = false;
649 // Reset all animating / constrained properties
650 std::vector<PropertyResetterBase*>toDelete;
651 for( auto&& element : mImpl->propertyResetters )
653 element->ResetToBaseValue( bufferIndex );
654 if( element->IsFinished() )
656 toDelete.push_back( element );
660 // If a resetter is no longer required (the animator or constraint has been removed), delete it.
661 for( auto&& elementPtr : toDelete )
663 mImpl->propertyResetters.EraseObject( elementPtr );
666 // Clear node dirty flags
667 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
668 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
669 for( ;iter != endIter; ++iter )
671 (*iter)->ResetDirtyFlags( bufferIndex );
675 bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, uint32_t lastVSyncTimeMilliseconds, uint32_t nextVSyncTimeMilliseconds )
677 bool gestureUpdated( false );
679 if( mImpl->panGestureProcessor )
681 // gesture processor only supports default properties
682 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
683 gestureUpdated |= mImpl->panGestureProcessor->UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
686 return gestureUpdated;
689 void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
691 AnimationContainer &animations = mImpl->animations;
692 AnimationIter iter = animations.Begin();
693 bool animationLooped = false;
695 while ( iter != animations.End() )
697 Animation* animation = *iter;
698 bool finished = false;
700 bool progressMarkerReached = false;
701 animation->Update( bufferIndex, elapsedSeconds, looped, finished, progressMarkerReached );
703 if ( progressMarkerReached )
705 mImpl->notificationManager.QueueMessage( Internal::NotifyProgressReachedMessage( mImpl->animationPlaylist, animation ) );
708 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
709 animationLooped = animationLooped || looped;
711 // Remove animations that had been destroyed but were still waiting for an update
712 if (animation->GetState() == Animation::Destroyed)
714 iter = animations.Erase(iter);
722 // queue the notification on finished or looped (to update loop count)
723 if ( mImpl->animationFinishedDuringUpdate || animationLooped )
725 // The application should be notified by NotificationManager, in another thread
726 mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationPlaylist );
730 void UpdateManager::ConstrainCustomObjects( BufferIndex bufferIndex )
732 //Constrain custom objects (in construction order)
733 for ( auto&& object : mImpl->customObjects )
735 ConstrainPropertyOwner( *object, bufferIndex );
739 void UpdateManager::ConstrainRenderTasks( BufferIndex bufferIndex )
741 // Constrain system-level render-tasks
742 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
743 for ( auto&& task : systemLevelTasks )
745 ConstrainPropertyOwner( *task, bufferIndex );
748 // Constrain render-tasks
749 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
750 for ( auto&& task : tasks )
752 ConstrainPropertyOwner( *task, bufferIndex );
756 void UpdateManager::ConstrainShaders( BufferIndex bufferIndex )
758 // constrain shaders... (in construction order)
759 for ( auto&& shader : mImpl->shaders )
761 ConstrainPropertyOwner( *shader, bufferIndex );
765 void UpdateManager::ProcessPropertyNotifications( BufferIndex bufferIndex )
767 for( auto&& notification : mImpl->propertyNotifications )
769 bool valid = notification->Check( bufferIndex );
772 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
777 void UpdateManager::ForwardCompiledShadersToEventThread()
779 DALI_ASSERT_DEBUG( (mImpl->shaderSaver != 0) && "shaderSaver should be wired-up during startup." );
780 if( mImpl->shaderSaver )
782 // lock and swap the queues
784 // render might be attempting to send us more binaries at the same time
785 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
786 mImpl->renderCompiledShaders.swap( mImpl->updateCompiledShaders );
789 if( mImpl->updateCompiledShaders.size() > 0 )
791 ShaderSaver& factory = *mImpl->shaderSaver;
792 for( auto&& shader : mImpl->updateCompiledShaders )
794 mImpl->notificationManager.QueueMessage( ShaderCompiledMessage( factory, shader ) );
796 // we don't need them in update anymore
797 mImpl->updateCompiledShaders.clear();
802 void UpdateManager::UpdateRenderers( BufferIndex bufferIndex )
804 for( auto&& renderer : mImpl->renderers )
807 ConstrainPropertyOwner( *renderer, bufferIndex );
809 renderer->PrepareRender( bufferIndex );
813 void UpdateManager::UpdateNodes( BufferIndex bufferIndex )
815 mImpl->nodeDirtyFlags = NodePropertyFlags::NOTHING;
822 // Prepare resources, update shaders, for each node
823 // And add the renderers to the sorted layers. Start from root, which is also a layer
824 mImpl->nodeDirtyFlags = UpdateNodeTree( *( mImpl->root ),
826 mImpl->renderQueue );
828 if ( mImpl->systemLevelRoot )
830 mImpl->nodeDirtyFlags |= UpdateNodeTree( *( mImpl->systemLevelRoot ),
832 mImpl->renderQueue );
836 uint32_t UpdateManager::Update( float elapsedSeconds,
837 uint32_t lastVSyncTimeMilliseconds,
838 uint32_t nextVSyncTimeMilliseconds,
839 bool renderToFboEnabled,
840 bool isRenderingToFbo )
842 const BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
844 //Clear nodes/resources which were previously discarded
845 mImpl->discardQueue.Clear( bufferIndex );
847 //Process Touches & Gestures
848 const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
850 bool updateScene = // The scene-graph requires an update if..
851 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
852 IsAnimationRunning() || // ..at least one animation is running OR
853 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
854 gestureUpdated; // ..a gesture property was updated
857 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
858 // values if the scene was updated in the previous frame.
859 if( updateScene || mImpl->previousUpdateScene )
861 //Reset properties from the previous update
862 ResetProperties( bufferIndex );
863 mImpl->transformManager.ResetToBaseValue();
866 // Process the queued scene messages. Note, MessageQueue::FlushQueue may be called
867 // between calling IsSceneUpdateRequired() above and here, so updateScene should
869 updateScene |= mImpl->messageQueue.ProcessMessages( bufferIndex );
871 //Forward compiled shader programs to event thread for saving
872 ForwardCompiledShadersToEventThread();
874 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
875 // renderer lists if the scene was updated in the previous frame.
876 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
877 if( updateScene || mImpl->previousUpdateScene )
880 Animate( bufferIndex, elapsedSeconds );
882 //Constraint custom objects
883 ConstrainCustomObjects( bufferIndex );
885 //Clear the lists of renderers from the previous update
886 for( auto&& layer : mImpl->sortedLayers )
888 layer->ClearRenderables();
891 for( auto&& layer : mImpl->systemLevelSortedLayers )
893 layer->ClearRenderables();
896 //Update node hierarchy, apply constraints and perform sorting / culling.
897 //This will populate each Layer with a list of renderers which are ready.
898 UpdateNodes( bufferIndex );
900 //Apply constraints to RenderTasks, shaders
901 ConstrainRenderTasks( bufferIndex );
902 ConstrainShaders( bufferIndex );
904 //Update renderers and apply constraints
905 UpdateRenderers( bufferIndex );
907 // Call the frame-callback-processor if set
908 if( mImpl->frameCallbackProcessor )
910 mImpl->frameCallbackProcessor->Update( bufferIndex, elapsedSeconds );
913 //Update the transformations of all the nodes
914 mImpl->transformManager.Update();
916 //Process Property Notifications
917 ProcessPropertyNotifications( bufferIndex );
920 for( auto&& cameraIterator : mImpl->cameras )
922 cameraIterator->Update( bufferIndex );
925 //Process the RenderTasks if renderers exist. This creates the instructions for rendering the next frame.
926 //reset the update buffer index and make sure there is enough room in the instruction container
927 if( mImpl->renderersAdded )
929 mImpl->renderInstructions.ResetAndReserve( bufferIndex, mImpl->taskList.GetTaskCount() + mImpl->systemLevelTaskList.GetTaskCount() );
931 if ( NULL != mImpl->root )
933 mImpl->renderTaskProcessor.Process( bufferIndex,
937 mImpl->renderInstructions,
941 // Process the system-level RenderTasks last
942 if ( NULL != mImpl->systemLevelRoot )
944 mImpl->renderTaskProcessor.Process( bufferIndex,
945 mImpl->systemLevelTaskList,
946 *mImpl->systemLevelRoot,
947 mImpl->systemLevelSortedLayers,
948 mImpl->renderInstructions,
956 // check the countdown and notify (note, at the moment this is only done for normal tasks, not for systemlevel tasks)
957 bool doRenderOnceNotify = false;
958 mImpl->renderTaskWaiting = false;
959 for ( auto&& renderTask : mImpl->taskList.GetTasks() )
961 renderTask->UpdateState();
963 if( renderTask->IsWaitingToRender() &&
964 renderTask->ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
966 mImpl->renderTaskWaiting = true; // keep update/render threads alive
969 if( renderTask->HasRendered() )
971 doRenderOnceNotify = true;
975 if( doRenderOnceNotify )
977 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
978 mImpl->notificationManager.QueueCompleteNotification( mImpl->taskList.GetCompleteNotificationInterface() );
981 // Macro is undefined in release build.
982 SNAPSHOT_NODE_LOGGING;
984 // A ResetProperties() may be required in the next frame
985 mImpl->previousUpdateScene = updateScene;
987 // Check whether further updates are required
988 uint32_t keepUpdating = KeepUpdatingCheck( elapsedSeconds );
990 // tell the update manager that we're done so the queue can be given to event thread
991 mImpl->notificationManager.UpdateCompleted();
993 // The update has finished; swap the double-buffering indices
994 mSceneGraphBuffers.Swap();
999 uint32_t UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
1001 // Update the duration set via Stage::KeepRendering()
1002 if ( mImpl->keepRenderingSeconds > 0.0f )
1004 mImpl->keepRenderingSeconds -= elapsedSeconds;
1007 uint32_t keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
1009 // If the rendering behavior is set to continuously render, then continue to render.
1010 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
1011 // Keep updating until no messages are received and no animations are running.
1012 // If an animation has just finished, update at least once more for Discard end-actions.
1013 // No need to check for renderQueue as there is always a render after update and if that
1014 // render needs another update it will tell the adaptor to call update again
1016 if ( ( mImpl->renderingBehavior == DevelStage::Rendering::CONTINUOUSLY ) ||
1017 ( mImpl->keepRenderingSeconds > 0.0f ) )
1019 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
1022 if ( IsAnimationRunning() ||
1023 mImpl->animationFinishedDuringUpdate )
1025 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
1028 if ( mImpl->renderTaskWaiting )
1030 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
1033 return keepUpdatingRequest;
1036 void UpdateManager::SetBackgroundColor( const Vector4& color )
1038 typedef MessageValue1< RenderManager, Vector4 > DerivedType;
1040 // Reserve some memory inside the render queue
1041 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1043 // Construct message in the render queue memory; note that delete should not be called on the return value
1044 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
1047 void UpdateManager::SetDefaultSurfaceRect( const Rect<int32_t>& rect )
1049 mImpl->surfaceRectChanged = true;
1051 typedef MessageValue1< RenderManager, Rect<int32_t> > DerivedType;
1053 // Reserve some memory inside the render queue
1054 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1056 // Construct message in the render queue memory; note that delete should not be called on the return value
1057 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1060 void UpdateManager::KeepRendering( float durationSeconds )
1062 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1065 void UpdateManager::SetRenderingBehavior( DevelStage::Rendering renderingBehavior )
1067 mImpl->renderingBehavior = renderingBehavior;
1070 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, bool systemLevel )
1074 // just copy the vector of pointers
1075 mImpl->sortedLayers = layers;
1079 mImpl->systemLevelSortedLayers = layers;
1083 void UpdateManager::SetDepthIndices( OwnerPointer< NodeDepths >& nodeDepths )
1085 // note,this vector is already in depth order. It could be used as-is to
1086 // remove sorting in update algorithm. However, it lacks layer boundary markers.
1087 for( auto&& iter : nodeDepths->nodeDepths )
1089 iter.node->SetDepthIndex( iter.sortedDepth );
1092 // Go through node hierarchy and rearrange siblings according to depth-index
1093 SortSiblingNodesRecursively( *( mImpl->root ) );
1096 bool UpdateManager::IsDefaultSurfaceRectChanged()
1098 bool surfaceRectChanged = mImpl->surfaceRectChanged;
1101 mImpl->surfaceRectChanged = false;
1103 return surfaceRectChanged;
1106 void UpdateManager::AddFrameCallback( OwnerPointer< FrameCallback >& frameCallback, const Node* rootNode )
1108 mImpl->GetFrameCallbackProcessor().AddFrameCallback( frameCallback, rootNode );
1111 void UpdateManager::RemoveFrameCallback( FrameCallbackInterface* frameCallback )
1113 mImpl->GetFrameCallbackProcessor().RemoveFrameCallback( frameCallback );
1116 void UpdateManager::AddSampler( OwnerPointer< Render::Sampler >& sampler )
1118 // Message has ownership of Sampler while in transit from update to render
1119 typedef MessageValue1< RenderManager, OwnerPointer< Render::Sampler > > DerivedType;
1121 // Reserve some memory inside the render queue
1122 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1124 // Construct message in the render queue memory; note that delete should not be called on the return value
1125 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddSampler, sampler );
1128 void UpdateManager::RemoveSampler( Render::Sampler* sampler )
1130 typedef MessageValue1< RenderManager, Render::Sampler* > DerivedType;
1132 // Reserve some memory inside the render queue
1133 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1135 // Construct message in the render queue memory; note that delete should not be called on the return value
1136 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveSampler, sampler );
1139 void UpdateManager::SetFilterMode( Render::Sampler* sampler, uint32_t minFilterMode, uint32_t magFilterMode )
1141 typedef MessageValue3< RenderManager, Render::Sampler*, uint32_t, uint32_t > DerivedType;
1143 // Reserve some memory inside the render queue
1144 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1146 // Construct message in the render queue memory; note that delete should not be called on the return value
1147 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetFilterMode, sampler, minFilterMode, magFilterMode );
1150 void UpdateManager::SetWrapMode( Render::Sampler* sampler, uint32_t rWrapMode, uint32_t sWrapMode, uint32_t tWrapMode )
1152 typedef MessageValue4< RenderManager, Render::Sampler*, uint32_t, uint32_t, uint32_t > DerivedType;
1154 // Reserve some memory inside the render queue
1155 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1157 // Construct message in the render queue memory; note that delete should not be called on the return value
1158 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetWrapMode, sampler, rWrapMode, sWrapMode, tWrapMode );
1161 void UpdateManager::AddPropertyBuffer( OwnerPointer< Render::PropertyBuffer >& propertyBuffer )
1163 // Message has ownership of format while in transit from update -> render
1164 typedef MessageValue1< RenderManager, OwnerPointer< Render::PropertyBuffer > > DerivedType;
1166 // Reserve some memory inside the render queue
1167 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1169 // Construct message in the render queue memory; note that delete should not be called on the return value
1170 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddPropertyBuffer, propertyBuffer );
1173 void UpdateManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer )
1175 typedef MessageValue1< RenderManager, Render::PropertyBuffer* > DerivedType;
1177 // Reserve some memory inside the render queue
1178 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1180 // Construct message in the render queue memory; note that delete should not be called on the return value
1181 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemovePropertyBuffer, propertyBuffer );
1184 void UpdateManager::SetPropertyBufferFormat( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Render::PropertyBuffer::Format>& format )
1186 // Message has ownership of format while in transit from update -> render
1187 typedef MessageValue2< RenderManager, Render::PropertyBuffer*, OwnerPointer< Render::PropertyBuffer::Format > > DerivedType;
1189 // Reserve some memory inside the render queue
1190 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1192 // Construct message in the render queue memory; note that delete should not be called on the return value
1193 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferFormat, propertyBuffer, format );
1196 void UpdateManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Vector<uint8_t> >& data, uint32_t size )
1198 // Message has ownership of format while in transit from update -> render
1199 typedef MessageValue3< RenderManager, Render::PropertyBuffer*, OwnerPointer< Dali::Vector<uint8_t> >, uint32_t > 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::SetPropertyBufferData, propertyBuffer, data, size );
1208 void UpdateManager::AddGeometry( OwnerPointer< Render::Geometry >& geometry )
1210 // Message has ownership of format while in transit from update -> render
1211 typedef MessageValue1< RenderManager, OwnerPointer< Render::Geometry > > 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::AddGeometry, geometry );
1220 void UpdateManager::RemoveGeometry( Render::Geometry* geometry )
1222 typedef MessageValue1< RenderManager, Render::Geometry* > 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::RemoveGeometry, geometry );
1231 void UpdateManager::SetGeometryType( Render::Geometry* geometry, uint32_t geometryType )
1233 typedef MessageValue2< RenderManager, Render::Geometry*, uint32_t > 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::SetGeometryType, geometry, geometryType );
1242 void UpdateManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector<uint16_t>& indices )
1244 typedef IndexBufferMessage< RenderManager > 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, geometry, indices );
1253 void UpdateManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1255 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1257 // Reserve some memory inside the render queue
1258 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1260 // Construct message in the render queue memory; note that delete should not be called on the return value
1261 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveVertexBuffer, geometry, propertyBuffer );
1264 void UpdateManager::AttachVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1266 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1268 // Reserve some memory inside the render queue
1269 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1271 // Construct message in the render queue memory; note that delete should not be called on the return value
1272 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AttachVertexBuffer, geometry, propertyBuffer );
1275 void UpdateManager::AddTexture( OwnerPointer< Render::Texture >& texture )
1277 // Message has ownership of Texture while in transit from update -> render
1278 typedef MessageValue1< RenderManager, OwnerPointer< Render::Texture > > DerivedType;
1280 // Reserve some memory inside the render queue
1281 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1283 // Construct message in the render queue memory; note that delete should not be called on the return value
1284 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddTexture, texture );
1287 void UpdateManager::RemoveTexture( Render::Texture* texture)
1289 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1291 // Reserve some memory inside the render queue
1292 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1294 // Construct message in the render queue memory; note that delete should not be called on the return value
1295 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveTexture, texture );
1298 void UpdateManager::UploadTexture( Render::Texture* texture, PixelDataPtr pixelData, const Texture::UploadParams& params )
1300 typedef MessageValue3< RenderManager, Render::Texture*, PixelDataPtr, Texture::UploadParams > DerivedType;
1302 // Reserve some memory inside the message queue
1303 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1305 // Construct message in the message queue memory; note that delete should not be called on the return value
1306 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::UploadTexture, texture, pixelData, params );
1309 void UpdateManager::GenerateMipmaps( Render::Texture* texture )
1311 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1313 // Reserve some memory inside the render queue
1314 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1316 // Construct message in the render queue memory; note that delete should not be called on the return value
1317 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::GenerateMipmaps, texture );
1320 void UpdateManager::AddFrameBuffer( Render::FrameBuffer* frameBuffer )
1322 typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType;
1324 // Reserve some memory inside the render queue
1325 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1327 // Construct message in the render queue memory; note that delete should not be called on the return value
1328 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddFrameBuffer, frameBuffer );
1331 void UpdateManager::RemoveFrameBuffer( Render::FrameBuffer* frameBuffer)
1333 typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType;
1335 // Reserve some memory inside the render queue
1336 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1338 // Construct message in the render queue memory; note that delete should not be called on the return value
1339 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveFrameBuffer, frameBuffer );
1342 void UpdateManager::AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel, uint32_t layer )
1344 typedef MessageValue4< RenderManager, Render::FrameBuffer*, Render::Texture*, uint32_t, uint32_t > DerivedType;
1346 // Reserve some memory inside the render queue
1347 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1349 // Construct message in the render queue memory; note that delete should not be called on the return value
1350 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AttachColorTextureToFrameBuffer, frameBuffer, texture, mipmapLevel, layer );
1353 } // namespace SceneGraph
1355 } // namespace Internal