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/update-algorithms.h>
51 #include <dali/internal/update/manager/update-manager-debug.h>
52 #include <dali/internal/update/manager/transform-manager.h>
53 #include <dali/internal/update/nodes/node.h>
54 #include <dali/internal/update/nodes/scene-graph-layer.h>
55 #include <dali/internal/update/queue/update-message-queue.h>
56 #include <dali/internal/update/render-tasks/scene-graph-render-task.h>
57 #include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
58 #include <dali/internal/update/render-tasks/scene-graph-camera.h>
60 #include <dali/internal/render/common/render-instruction-container.h>
61 #include <dali/internal/render/common/render-manager.h>
62 #include <dali/internal/render/queue/render-queue.h>
63 #include <dali/internal/render/shaders/scene-graph-shader.h>
65 // Un-comment to enable node tree debug logging
66 //#define NODE_TREE_LOGGING 1
68 #if ( defined( DEBUG_ENABLED ) && defined( NODE_TREE_LOGGING ) )
69 #define SNAPSHOT_NODE_LOGGING \
70 const int FRAME_COUNT_TRIGGER = 16;\
71 if( mImpl->frameCounter >= FRAME_COUNT_TRIGGER )\
73 if ( NULL != mImpl->root )\
75 mImpl->frameCounter = 0;\
76 PrintNodeTree( *mImpl->root, mSceneGraphBuffers.GetUpdateBufferIndex(), "" );\
79 mImpl->frameCounter++;
81 #define SNAPSHOT_NODE_LOGGING
84 #if defined(DEBUG_ENABLED)
85 extern Debug::Filter* gRenderTaskLogFilter;
89 using namespace Dali::Integration;
90 using Dali::Internal::Update::MessageQueue;
104 * Helper to reset animate-able objects to base values
105 * @param container to iterate over
106 * @param updateBufferIndex to use
109 inline void ResetToBaseValues( OwnerContainer<T*>& container, BufferIndex updateBufferIndex )
111 // Reset animatable properties to base values
112 // use reference to avoid extra copies of the iterator
113 for( auto&& iter : container )
115 iter->ResetToBaseValues( updateBufferIndex );
120 * Helper to Erase an object from OwnerContainer using discard queue
121 * @param container to remove from
122 * @param object to remove
123 * @param discardQueue to put the object to
124 * @param updateBufferIndex to use
127 inline void EraseUsingDiscardQueue( OwnerContainer<T*>& container, T* object, DiscardQueue& discardQueue, BufferIndex updateBufferIndex )
129 DALI_ASSERT_DEBUG( object && "NULL object not allowed" );
131 // need to use the reference version of auto as we need the pointer to the pointer for the Release call below
132 for( auto&& iter : container )
134 if ( iter == object )
136 // Transfer ownership to the discard queue, this keeps the object alive, until the render-thread has finished with it
137 discardQueue.Add( updateBufferIndex, container.Release( &iter ) ); // take the address of the reference to a pointer (iter)
138 return; // return as we only ever remove one object. Iterators to container are now invalidated as well so cannot continue
144 * Descends into node's hierarchy and sorts the children of each child according to their depth-index.
145 * @param[in] node The node whose hierarchy to descend
147 void SortSiblingNodesRecursively( Node& node )
149 NodeContainer& container = node.GetChildren();
150 std::sort( container.Begin(), container.End(),
151 []( Node* a, Node* b ) { return a->GetDepthIndex() < b->GetDepthIndex(); } );
153 // Descend tree and sort as well
154 for( auto&& iter : container )
156 SortSiblingNodesRecursively( *iter );
160 } // unnamed namespace
163 * Structure to contain UpdateManager internal data
165 struct UpdateManager::Impl
167 Impl( NotificationManager& notificationManager,
168 CompleteNotificationInterface& animationPlaylist,
169 PropertyNotifier& propertyNotifier,
170 DiscardQueue& discardQueue,
171 RenderController& renderController,
172 RenderManager& renderManager,
173 RenderQueue& renderQueue,
174 SceneGraphBuffers& sceneGraphBuffers,
175 RenderTaskProcessor& renderTaskProcessor )
176 : renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ),
177 notificationManager( notificationManager ),
179 animationPlaylist( animationPlaylist ),
180 propertyNotifier( propertyNotifier ),
182 discardQueue( discardQueue ),
183 renderController( renderController ),
184 sceneController( NULL ),
185 renderManager( renderManager ),
186 renderQueue( renderQueue ),
187 renderInstructions( renderManager.GetRenderInstructionContainer() ),
188 renderTaskProcessor( renderTaskProcessor ),
189 backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
190 taskList( renderMessageDispatcher ),
191 systemLevelTaskList( renderMessageDispatcher ),
193 systemLevelRoot( NULL ),
197 panGestureProcessor( NULL ),
198 messageQueue( renderController, sceneGraphBuffers ),
199 frameCallbackProcessor( NULL ),
200 keepRenderingSeconds( 0.0f ),
201 nodeDirtyFlags( TransformFlag ), // set to TransformFlag to ensure full update the first time through Update()
203 renderingBehavior( DevelStage::Rendering::IF_REQUIRED ),
204 animationFinishedDuringUpdate( false ),
205 previousUpdateScene( false ),
206 renderTaskWaiting( false ),
207 renderersAdded( false ),
208 surfaceRectChanged( false )
210 sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue );
212 // create first 'dummy' node
218 // Disconnect render tasks from nodes, before destroying the nodes
219 RenderTaskList::RenderTaskContainer& tasks = taskList.GetTasks();
220 for ( auto&& iter : tasks )
222 iter->SetSourceNode( NULL );
224 // ..repeat for system level RenderTasks
225 RenderTaskList::RenderTaskContainer& systemLevelTasks = systemLevelTaskList.GetTasks();
226 for ( auto&& iter : systemLevelTasks )
228 iter->SetSourceNode( NULL );
231 // UpdateManager owns the Nodes. Although Nodes are pool allocated they contain heap allocated parts
232 // like custom properties, which get released here
233 Vector<Node*>::Iterator iter = nodes.Begin()+1;
234 Vector<Node*>::Iterator endIter = nodes.End();
235 for(;iter!=endIter;++iter)
237 (*iter)->OnDestroy();
241 // If there is root, reset it, otherwise do nothing as rendering was never started
246 Node::Delete( root );
250 if( systemLevelRoot )
252 systemLevelRoot->OnDestroy();
254 Node::Delete( systemLevelRoot );
255 systemLevelRoot = NULL;
258 delete sceneController;
262 * Lazy init for FrameCallbackProcessor.
264 FrameCallbackProcessor& GetFrameCallbackProcessor()
266 if( ! frameCallbackProcessor )
268 frameCallbackProcessor = new FrameCallbackProcessor( transformManager, *root );
270 return *frameCallbackProcessor;
273 SceneGraphBuffers sceneGraphBuffers; ///< Used to keep track of which buffers are being written or read
274 RenderMessageDispatcher renderMessageDispatcher; ///< Used for passing messages to the render-thread
275 NotificationManager& notificationManager; ///< Queues notification messages for the event-thread.
276 TransformManager transformManager; ///< Used to update the transformation matrices of the nodes
277 CompleteNotificationInterface& animationPlaylist; ///< Holds handles to all the animations
278 PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
279 ShaderSaver* shaderSaver; ///< Saves shader binaries.
280 DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
281 RenderController& renderController; ///< render controller
282 SceneControllerImpl* sceneController; ///< scene controller
283 RenderManager& renderManager; ///< This is responsible for rendering the results of each "update"
284 RenderQueue& renderQueue; ///< Used to queue messages for the next render
285 RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions
286 RenderTaskProcessor& renderTaskProcessor; ///< Handles RenderTasks and RenderInstrucitons
288 Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
290 RenderTaskList taskList; ///< The list of scene graph render-tasks
291 RenderTaskList systemLevelTaskList; ///< Separate render-tasks for system-level content
293 Layer* root; ///< The root node (root is a layer)
294 Layer* systemLevelRoot; ///< A separate root-node for system-level content
296 Vector<Node*> nodes; ///< A container of all instantiated nodes
298 SortedLayerPointers sortedLayers; ///< A container of Layer pointers sorted by depth
299 SortedLayerPointers systemLevelSortedLayers; ///< A separate container of system-level Layers
301 OwnerContainer< Camera* > cameras; ///< A container of cameras
302 OwnerContainer< PropertyOwner* > customObjects; ///< A container of owned objects (with custom properties)
304 OwnerContainer< PropertyResetterBase* > propertyResetters; ///< A container of property resetters
305 AnimationContainer animations; ///< A container of owned animations
306 PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
307 OwnerContainer< Renderer* > renderers; ///< A container of owned renderers
308 OwnerContainer< TextureSet* > textureSets; ///< A container of owned texture sets
309 OwnerContainer< Shader* > shaders; ///< A container of owned shaders
310 OwnerPointer< PanGesture > panGestureProcessor; ///< Owned pan gesture processor; it lives for the lifecycle of UpdateManager
312 MessageQueue messageQueue; ///< The messages queued from the event-thread
313 std::vector<Internal::ShaderDataPtr> renderCompiledShaders; ///< Shaders compiled on Render thread are inserted here for update thread to pass on to event thread.
314 std::vector<Internal::ShaderDataPtr> updateCompiledShaders; ///< Shaders to be sent from Update to Event
315 Mutex compiledShaderMutex; ///< lock to ensure no corruption on the renderCompiledShaders
317 OwnerPointer<FrameCallbackProcessor> frameCallbackProcessor; ///< Owned FrameCallbackProcessor, only created if required.
319 float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
320 int nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
321 int frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
323 DevelStage::Rendering renderingBehavior; ///< Set via DevelStage::SetRenderingBehavior
325 bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
326 bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
327 bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
328 bool renderersAdded; ///< Flag to keep track when renderers have been added to avoid unnecessary processing
329 bool surfaceRectChanged; ///< True if the default surface rect is changed
333 Impl( const Impl& ); ///< Undefined
334 Impl& operator=( const Impl& ); ///< Undefined
337 UpdateManager::UpdateManager( NotificationManager& notificationManager,
338 CompleteNotificationInterface& animationFinishedNotifier,
339 PropertyNotifier& propertyNotifier,
340 DiscardQueue& discardQueue,
341 RenderController& controller,
342 RenderManager& renderManager,
343 RenderQueue& renderQueue,
344 RenderTaskProcessor& renderTaskProcessor )
347 mImpl = new Impl( notificationManager,
348 animationFinishedNotifier,
355 renderTaskProcessor );
359 UpdateManager::~UpdateManager()
364 void UpdateManager::InstallRoot( OwnerPointer<Layer>& layer, bool systemLevel )
366 DALI_ASSERT_DEBUG( layer->IsLayer() );
367 DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
371 DALI_ASSERT_DEBUG( mImpl->root == NULL && "Root Node already installed" );
372 mImpl->root = layer.Release();
373 mImpl->root->CreateTransform( &mImpl->transformManager );
374 mImpl->root->SetRoot(true);
378 DALI_ASSERT_DEBUG( mImpl->systemLevelRoot == NULL && "System-level Root Node already installed" );
379 mImpl->systemLevelRoot = layer.Release();
380 mImpl->systemLevelRoot->CreateTransform( &mImpl->transformManager );
381 mImpl->systemLevelRoot->SetRoot(true);
386 void UpdateManager::AddNode( OwnerPointer<Node>& node )
388 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
390 // Nodes must be sorted by pointer
391 Node* rawNode = node.Release();
392 Vector<Node*>::Iterator begin = mImpl->nodes.Begin();
393 for( Vector<Node*>::Iterator iter = mImpl->nodes.End()-1; iter >= begin; --iter )
395 if( rawNode > (*iter) )
397 mImpl->nodes.Insert((iter+1), rawNode );
398 rawNode->CreateTransform( &mImpl->transformManager );
404 void UpdateManager::ConnectNode( Node* parent, Node* node )
406 DALI_ASSERT_ALWAYS( NULL != parent );
407 DALI_ASSERT_ALWAYS( NULL != node );
408 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
410 parent->ConnectChild( node );
413 void UpdateManager::DisconnectNode( Node* node )
415 Node* parent = node->GetParent();
416 DALI_ASSERT_ALWAYS( NULL != parent );
417 parent->SetDirtyFlag( ChildDeletedFlag ); // make parent dirty so that render items dont get reused
419 parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node );
422 void UpdateManager::DestroyNode( Node* node )
424 DALI_ASSERT_ALWAYS( NULL != node );
425 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
427 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
428 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
429 for(;iter!=endIter;++iter)
433 mImpl->nodes.Erase(iter);
438 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
440 // Notify the Node about impending destruction
444 void UpdateManager::AddCamera( OwnerPointer< Camera >& camera )
446 mImpl->cameras.PushBack( camera.Release() ); // takes ownership
449 void UpdateManager::RemoveCamera( const Camera* camera )
451 // Find the camera and destroy it
452 EraseUsingDiscardQueue( mImpl->cameras, const_cast<Camera*>( camera ), mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
455 void UpdateManager::AddObject( OwnerPointer<PropertyOwner>& object )
457 mImpl->customObjects.PushBack( object.Release() );
460 void UpdateManager::RemoveObject( PropertyOwner* object )
462 mImpl->customObjects.EraseObject( object );
465 void UpdateManager::AddAnimation( OwnerPointer< SceneGraph::Animation >& animation )
467 mImpl->animations.PushBack( animation.Release() );
470 void UpdateManager::StopAnimation( Animation* animation )
472 DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
474 bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
476 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
479 void UpdateManager::RemoveAnimation( Animation* animation )
481 DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
483 animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
485 DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
488 bool UpdateManager::IsAnimationRunning() const
490 // Find any animation that isn't stopped or paused
491 for ( auto&& iter : mImpl->animations )
493 const Animation::State state = iter->GetState();
495 if (state != Animation::Stopped &&
496 state != Animation::Paused)
498 return true; // stop iteration as soon as first one is found
505 void UpdateManager::AddPropertyResetter( OwnerPointer<PropertyResetterBase>& propertyResetter )
507 propertyResetter->Initialize();
508 mImpl->propertyResetters.PushBack( propertyResetter.Release() );
511 void UpdateManager::AddPropertyNotification( OwnerPointer< PropertyNotification >& propertyNotification )
513 mImpl->propertyNotifications.PushBack( propertyNotification.Release() );
516 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
518 mImpl->propertyNotifications.EraseObject( propertyNotification );
521 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
523 DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
524 propertyNotification->SetNotifyMode( notifyMode );
527 void UpdateManager::AddShader( OwnerPointer< Shader >& shader )
529 mImpl->shaders.PushBack( shader.Release() );
532 void UpdateManager::RemoveShader( Shader* shader )
534 // Find the shader and destroy it
535 EraseUsingDiscardQueue( mImpl->shaders, shader, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
538 void UpdateManager::SetShaderProgram( Shader* shader,
539 Internal::ShaderDataPtr shaderData, bool modifiesGeometry )
544 typedef MessageValue3< Shader, Internal::ShaderDataPtr, ProgramCache*, bool> DerivedType;
546 // Reserve some memory inside the render queue
547 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
549 // Construct message in the render queue memory; note that delete should not be called on the return value
550 new (slot) DerivedType( shader, &Shader::SetProgram, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
554 void UpdateManager::SaveBinary( Internal::ShaderDataPtr shaderData )
556 DALI_ASSERT_DEBUG( shaderData && "No NULL shader data pointers please." );
557 DALI_ASSERT_DEBUG( shaderData->GetBufferSize() > 0 && "Shader binary empty so nothing to save." );
559 // lock as update might be sending previously compiled shaders to event thread
560 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
561 mImpl->renderCompiledShaders.push_back( shaderData );
565 void UpdateManager::SetShaderSaver( ShaderSaver& upstream )
567 mImpl->shaderSaver = &upstream;
570 void UpdateManager::AddRenderer( OwnerPointer< Renderer >& renderer )
572 renderer->ConnectToSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
573 mImpl->renderers.PushBack( renderer.Release() );
574 mImpl->renderersAdded = true;
577 void UpdateManager::RemoveRenderer( Renderer* renderer )
579 // Find the renderer and destroy it
580 EraseUsingDiscardQueue( mImpl->renderers, renderer, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
581 // Need to remove the render object as well
582 renderer->DisconnectFromSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
585 void UpdateManager::SetPanGestureProcessor( PanGesture* panGestureProcessor )
587 DALI_ASSERT_DEBUG( NULL != panGestureProcessor );
589 mImpl->panGestureProcessor = panGestureProcessor;
592 void UpdateManager::AddTextureSet( OwnerPointer< TextureSet >& textureSet )
594 mImpl->textureSets.PushBack( textureSet.Release() );
597 void UpdateManager::RemoveTextureSet( TextureSet* textureSet )
599 mImpl->textureSets.EraseObject( textureSet );
602 RenderTaskList* UpdateManager::GetRenderTaskList( bool systemLevel )
606 // copy the list, this is only likely to happen once in application life cycle
607 return &(mImpl->taskList);
611 // copy the list, this is only likely to happen once in application life cycle
612 return &(mImpl->systemLevelTaskList);
616 unsigned int* UpdateManager::ReserveMessageSlot( std::size_t size, bool updateScene )
618 return mImpl->messageQueue.ReserveMessageSlot( size, updateScene );
621 void UpdateManager::EventProcessingStarted()
623 mImpl->messageQueue.EventProcessingStarted();
626 bool UpdateManager::FlushQueue()
628 return mImpl->messageQueue.FlushQueue();
631 void UpdateManager::ResetProperties( BufferIndex bufferIndex )
633 // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
634 mImpl->animationFinishedDuringUpdate = false;
636 // Reset all animating / constrained properties
637 std::vector<PropertyResetterBase*>toDelete;
638 for( auto&& element : mImpl->propertyResetters )
640 element->ResetToBaseValue( bufferIndex );
641 if( element->IsFinished() )
643 toDelete.push_back( element );
647 // If a resetter is no longer required (the animator or constraint has been removed), delete it.
648 for( auto&& elementPtr : toDelete )
650 mImpl->propertyResetters.EraseObject( elementPtr );
653 // Clear node dirty flags
654 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
655 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
656 for( ;iter != endIter; ++iter )
658 (*iter)->ResetDirtyFlags( bufferIndex );
662 bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds )
664 bool gestureUpdated( false );
666 if( mImpl->panGestureProcessor )
668 // gesture processor only supports default properties
669 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
670 gestureUpdated |= mImpl->panGestureProcessor->UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
673 return gestureUpdated;
676 void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
678 AnimationContainer &animations = mImpl->animations;
679 AnimationIter iter = animations.Begin();
680 bool animationLooped = false;
682 while ( iter != animations.End() )
684 Animation* animation = *iter;
685 bool finished = false;
687 bool progressMarkerReached = false;
688 animation->Update( bufferIndex, elapsedSeconds, looped, finished, progressMarkerReached );
690 if ( progressMarkerReached )
692 mImpl->notificationManager.QueueMessage( Internal::NotifyProgressReachedMessage( mImpl->animationPlaylist, animation ) );
695 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
696 animationLooped = animationLooped || looped;
698 // Remove animations that had been destroyed but were still waiting for an update
699 if (animation->GetState() == Animation::Destroyed)
701 iter = animations.Erase(iter);
709 // queue the notification on finished or looped (to update loop count)
710 if ( mImpl->animationFinishedDuringUpdate || animationLooped )
712 // The application should be notified by NotificationManager, in another thread
713 mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationPlaylist );
717 void UpdateManager::ConstrainCustomObjects( BufferIndex bufferIndex )
719 //Constrain custom objects (in construction order)
720 for ( auto&& object : mImpl->customObjects )
722 ConstrainPropertyOwner( *object, bufferIndex );
726 void UpdateManager::ConstrainRenderTasks( BufferIndex bufferIndex )
728 // Constrain system-level render-tasks
729 const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
730 for ( auto&& task : systemLevelTasks )
732 ConstrainPropertyOwner( *task, bufferIndex );
735 // Constrain render-tasks
736 const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
737 for ( auto&& task : tasks )
739 ConstrainPropertyOwner( *task, bufferIndex );
743 void UpdateManager::ConstrainShaders( BufferIndex bufferIndex )
745 // constrain shaders... (in construction order)
746 for ( auto&& shader : mImpl->shaders )
748 ConstrainPropertyOwner( *shader, bufferIndex );
752 void UpdateManager::ProcessPropertyNotifications( BufferIndex bufferIndex )
754 for( auto&& notification : mImpl->propertyNotifications )
756 bool valid = notification->Check( bufferIndex );
759 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
764 void UpdateManager::ForwardCompiledShadersToEventThread()
766 DALI_ASSERT_DEBUG( (mImpl->shaderSaver != 0) && "shaderSaver should be wired-up during startup." );
767 if( mImpl->shaderSaver )
769 // lock and swap the queues
771 // render might be attempting to send us more binaries at the same time
772 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
773 mImpl->renderCompiledShaders.swap( mImpl->updateCompiledShaders );
776 if( mImpl->updateCompiledShaders.size() > 0 )
778 ShaderSaver& factory = *mImpl->shaderSaver;
779 for( auto&& shader : mImpl->updateCompiledShaders )
781 mImpl->notificationManager.QueueMessage( ShaderCompiledMessage( factory, shader ) );
783 // we don't need them in update anymore
784 mImpl->updateCompiledShaders.clear();
789 void UpdateManager::UpdateRenderers( BufferIndex bufferIndex )
791 const unsigned int rendererCount = mImpl->renderers.Count();
792 for( unsigned int i = 0; i < rendererCount; ++i )
795 ConstrainPropertyOwner( *mImpl->renderers[i], bufferIndex );
797 mImpl->renderers[i]->PrepareRender( bufferIndex );
801 void UpdateManager::UpdateNodes( BufferIndex bufferIndex )
803 mImpl->nodeDirtyFlags = NothingFlag;
810 // Prepare resources, update shaders, for each node
811 // And add the renderers to the sorted layers. Start from root, which is also a layer
812 mImpl->nodeDirtyFlags = UpdateNodeTree( *( mImpl->root ),
814 mImpl->renderQueue );
816 if ( mImpl->systemLevelRoot )
818 mImpl->nodeDirtyFlags |= UpdateNodeTree( *( mImpl->systemLevelRoot ),
820 mImpl->renderQueue );
824 unsigned int UpdateManager::Update( float elapsedSeconds,
825 unsigned int lastVSyncTimeMilliseconds,
826 unsigned int nextVSyncTimeMilliseconds,
827 bool renderToFboEnabled,
828 bool isRenderingToFbo )
830 const BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
832 //Clear nodes/resources which were previously discarded
833 mImpl->discardQueue.Clear( bufferIndex );
835 //Process Touches & Gestures
836 const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
838 bool updateScene = // The scene-graph requires an update if..
839 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
840 IsAnimationRunning() || // ..at least one animation is running OR
841 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
842 gestureUpdated; // ..a gesture property was updated
845 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
846 // values if the scene was updated in the previous frame.
847 if( updateScene || mImpl->previousUpdateScene )
849 //Reset properties from the previous update
850 ResetProperties( bufferIndex );
851 mImpl->transformManager.ResetToBaseValue();
854 // Process the queued scene messages. Note, MessageQueue::FlushQueue may be called
855 // between calling IsSceneUpdateRequired() above and here, so updateScene should
857 updateScene |= mImpl->messageQueue.ProcessMessages( bufferIndex );
859 //Forward compiled shader programs to event thread for saving
860 ForwardCompiledShadersToEventThread();
862 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
863 // renderer lists if the scene was updated in the previous frame.
864 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
865 if( updateScene || mImpl->previousUpdateScene )
868 Animate( bufferIndex, elapsedSeconds );
870 //Constraint custom objects
871 ConstrainCustomObjects( bufferIndex );
873 //Clear the lists of renderers from the previous update
874 for( size_t i(0); i<mImpl->sortedLayers.size(); ++i )
876 mImpl->sortedLayers[i]->ClearRenderables();
879 for( size_t i(0); i<mImpl->systemLevelSortedLayers.size(); ++i )
881 mImpl->systemLevelSortedLayers[i]->ClearRenderables();
884 //Update node hierarchy, apply constraints and perform sorting / culling.
885 //This will populate each Layer with a list of renderers which are ready.
886 UpdateNodes( bufferIndex );
888 //Apply constraints to RenderTasks, shaders
889 ConstrainRenderTasks( bufferIndex );
890 ConstrainShaders( bufferIndex );
892 //Update renderers and apply constraints
893 UpdateRenderers( bufferIndex );
895 //Update the transformations of all the nodes
896 mImpl->transformManager.Update();
898 // Call the frame-callback-processor if set
899 if( mImpl->frameCallbackProcessor )
901 mImpl->frameCallbackProcessor->Update( bufferIndex, elapsedSeconds );
904 //Process Property Notifications
905 ProcessPropertyNotifications( bufferIndex );
908 for( auto&& cameraIterator : mImpl->cameras )
910 cameraIterator->Update( bufferIndex );
913 //Process the RenderTasks if renderers exist. This creates the instructions for rendering the next frame.
914 //reset the update buffer index and make sure there is enough room in the instruction container
915 if( mImpl->renderersAdded )
917 mImpl->renderInstructions.ResetAndReserve( bufferIndex,
918 mImpl->taskList.GetTasks().Count() + mImpl->systemLevelTaskList.GetTasks().Count() );
920 if ( NULL != mImpl->root )
922 mImpl->renderTaskProcessor.Process( bufferIndex,
926 mImpl->renderInstructions,
930 // Process the system-level RenderTasks last
931 if ( NULL != mImpl->systemLevelRoot )
933 mImpl->renderTaskProcessor.Process( bufferIndex,
934 mImpl->systemLevelTaskList,
935 *mImpl->systemLevelRoot,
936 mImpl->systemLevelSortedLayers,
937 mImpl->renderInstructions,
945 // check the countdown and notify (note, at the moment this is only done for normal tasks, not for systemlevel tasks)
946 bool doRenderOnceNotify = false;
947 mImpl->renderTaskWaiting = false;
948 for ( auto&& renderTask : mImpl->taskList.GetTasks() )
950 renderTask->UpdateState();
952 if( renderTask->IsWaitingToRender() &&
953 renderTask->ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
955 mImpl->renderTaskWaiting = true; // keep update/render threads alive
958 if( renderTask->HasRendered() )
960 doRenderOnceNotify = true;
964 if( doRenderOnceNotify )
966 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
967 mImpl->notificationManager.QueueCompleteNotification( mImpl->taskList.GetCompleteNotificationInterface() );
970 // Macro is undefined in release build.
971 SNAPSHOT_NODE_LOGGING;
973 // A ResetProperties() may be required in the next frame
974 mImpl->previousUpdateScene = updateScene;
976 // Check whether further updates are required
977 unsigned int keepUpdating = KeepUpdatingCheck( elapsedSeconds );
979 // tell the update manager that we're done so the queue can be given to event thread
980 mImpl->notificationManager.UpdateCompleted();
982 // The update has finished; swap the double-buffering indices
983 mSceneGraphBuffers.Swap();
988 unsigned int UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
990 // Update the duration set via Stage::KeepRendering()
991 if ( mImpl->keepRenderingSeconds > 0.0f )
993 mImpl->keepRenderingSeconds -= elapsedSeconds;
996 unsigned int keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
998 // If the rendering behavior is set to continuously render, then continue to render.
999 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
1000 // Keep updating until no messages are received and no animations are running.
1001 // If an animation has just finished, update at least once more for Discard end-actions.
1002 // No need to check for renderQueue as there is always a render after update and if that
1003 // render needs another update it will tell the adaptor to call update again
1005 if ( ( mImpl->renderingBehavior == DevelStage::Rendering::CONTINUOUSLY ) ||
1006 ( mImpl->keepRenderingSeconds > 0.0f ) )
1008 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
1011 if ( IsAnimationRunning() ||
1012 mImpl->animationFinishedDuringUpdate )
1014 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
1017 if ( mImpl->renderTaskWaiting )
1019 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
1022 return keepUpdatingRequest;
1025 void UpdateManager::SetBackgroundColor( const Vector4& color )
1027 typedef MessageValue1< RenderManager, Vector4 > DerivedType;
1029 // Reserve some memory inside the render queue
1030 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1032 // Construct message in the render queue memory; note that delete should not be called on the return value
1033 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
1036 void UpdateManager::SetDefaultSurfaceRect( const Rect<int>& rect )
1038 mImpl->surfaceRectChanged = true;
1040 typedef MessageValue1< RenderManager, Rect<int> > DerivedType;
1042 // Reserve some memory inside the render queue
1043 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1045 // Construct message in the render queue memory; note that delete should not be called on the return value
1046 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1049 void UpdateManager::KeepRendering( float durationSeconds )
1051 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1054 void UpdateManager::SetRenderingBehavior( DevelStage::Rendering renderingBehavior )
1056 mImpl->renderingBehavior = renderingBehavior;
1059 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, bool systemLevel )
1063 // just copy the vector of pointers
1064 mImpl->sortedLayers = layers;
1068 mImpl->systemLevelSortedLayers = layers;
1072 void UpdateManager::SetDepthIndices( OwnerPointer< NodeDepths >& nodeDepths )
1074 // note,this vector is already in depth order. It could be used as-is to
1075 // remove sorting in update algorithm. However, it lacks layer boundary markers.
1076 for( auto&& iter : nodeDepths->nodeDepths )
1078 iter.node->SetDepthIndex( iter.sortedDepth );
1081 // Go through node hierarchy and rearrange siblings according to depth-index
1082 SortSiblingNodesRecursively( *( mImpl->root ) );
1085 bool UpdateManager::IsDefaultSurfaceRectChanged()
1087 bool surfaceRectChanged = mImpl->surfaceRectChanged;
1090 mImpl->surfaceRectChanged = false;
1092 return surfaceRectChanged;
1095 void UpdateManager::AddFrameCallback( FrameCallbackInterface* frameCallback, const Node* rootNode )
1097 mImpl->GetFrameCallbackProcessor().AddFrameCallback( frameCallback, rootNode );
1100 void UpdateManager::RemoveFrameCallback( FrameCallbackInterface* frameCallback )
1102 mImpl->GetFrameCallbackProcessor().RemoveFrameCallback( frameCallback );
1105 void UpdateManager::AddSampler( OwnerPointer< Render::Sampler >& sampler )
1107 // Message has ownership of Sampler while in transit from update to render
1108 typedef MessageValue1< RenderManager, OwnerPointer< Render::Sampler > > DerivedType;
1110 // Reserve some memory inside the render queue
1111 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1113 // Construct message in the render queue memory; note that delete should not be called on the return value
1114 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddSampler, sampler );
1117 void UpdateManager::RemoveSampler( Render::Sampler* sampler )
1119 typedef MessageValue1< RenderManager, Render::Sampler* > DerivedType;
1121 // Reserve some memory inside the render queue
1122 unsigned int* 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::RemoveSampler, sampler );
1128 void UpdateManager::SetFilterMode( Render::Sampler* sampler, unsigned int minFilterMode, unsigned int magFilterMode )
1130 typedef MessageValue3< RenderManager, Render::Sampler*, unsigned int, unsigned int > DerivedType;
1132 // Reserve some memory inside the render queue
1133 unsigned int* 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::SetFilterMode, sampler, minFilterMode, magFilterMode );
1139 void UpdateManager::SetWrapMode( Render::Sampler* sampler, unsigned int rWrapMode, unsigned int sWrapMode, unsigned int tWrapMode )
1141 typedef MessageValue4< RenderManager, Render::Sampler*, unsigned int, unsigned int, unsigned int > DerivedType;
1143 // Reserve some memory inside the render queue
1144 unsigned int* 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::SetWrapMode, sampler, rWrapMode, sWrapMode, tWrapMode );
1150 void UpdateManager::AddPropertyBuffer( OwnerPointer< Render::PropertyBuffer >& propertyBuffer )
1152 // Message has ownership of format while in transit from update -> render
1153 typedef MessageValue1< RenderManager, OwnerPointer< Render::PropertyBuffer > > DerivedType;
1155 // Reserve some memory inside the render queue
1156 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1158 // Construct message in the render queue memory; note that delete should not be called on the return value
1159 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddPropertyBuffer, propertyBuffer );
1162 void UpdateManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer )
1164 typedef MessageValue1< RenderManager, Render::PropertyBuffer* > DerivedType;
1166 // Reserve some memory inside the render queue
1167 unsigned int* 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::RemovePropertyBuffer, propertyBuffer );
1173 void UpdateManager::SetPropertyBufferFormat( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Render::PropertyBuffer::Format>& format )
1175 // Message has ownership of format while in transit from update -> render
1176 typedef MessageValue2< RenderManager, Render::PropertyBuffer*, OwnerPointer< Render::PropertyBuffer::Format > > DerivedType;
1178 // Reserve some memory inside the render queue
1179 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1181 // Construct message in the render queue memory; note that delete should not be called on the return value
1182 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferFormat, propertyBuffer, format );
1185 void UpdateManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Vector<char> >& data, size_t size )
1187 // Message has ownership of format while in transit from update -> render
1188 typedef MessageValue3< RenderManager, Render::PropertyBuffer*, OwnerPointer< Dali::Vector<char> >, size_t > DerivedType;
1190 // Reserve some memory inside the render queue
1191 unsigned int* 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::SetPropertyBufferData, propertyBuffer, data, size );
1197 void UpdateManager::AddGeometry( OwnerPointer< Render::Geometry >& geometry )
1199 // Message has ownership of format while in transit from update -> render
1200 typedef MessageValue1< RenderManager, OwnerPointer< Render::Geometry > > DerivedType;
1202 // Reserve some memory inside the render queue
1203 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1205 // Construct message in the render queue memory; note that delete should not be called on the return value
1206 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddGeometry, geometry );
1209 void UpdateManager::RemoveGeometry( Render::Geometry* geometry )
1211 typedef MessageValue1< RenderManager, Render::Geometry* > DerivedType;
1213 // Reserve some memory inside the render queue
1214 unsigned int* 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::RemoveGeometry, geometry );
1220 void UpdateManager::SetGeometryType( Render::Geometry* geometry, unsigned int geometryType )
1222 typedef MessageValue2< RenderManager, Render::Geometry*, unsigned int > DerivedType;
1224 // Reserve some memory inside the render queue
1225 unsigned int* 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::SetGeometryType, geometry, geometryType );
1231 void UpdateManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector<unsigned short>& indices )
1233 typedef IndexBufferMessage< RenderManager > DerivedType;
1235 // Reserve some memory inside the render queue
1236 unsigned int* 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, geometry, indices );
1242 void UpdateManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1244 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1246 // Reserve some memory inside the render queue
1247 unsigned int* 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::RemoveVertexBuffer, geometry, propertyBuffer );
1253 void UpdateManager::AttachVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1255 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1257 // Reserve some memory inside the render queue
1258 unsigned int* 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::AttachVertexBuffer, geometry, propertyBuffer );
1264 void UpdateManager::AddTexture( OwnerPointer< Render::Texture >& texture )
1266 // Message has ownership of Texture while in transit from update -> render
1267 typedef MessageValue1< RenderManager, OwnerPointer< Render::Texture > > DerivedType;
1269 // Reserve some memory inside the render queue
1270 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1272 // Construct message in the render queue memory; note that delete should not be called on the return value
1273 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddTexture, texture );
1276 void UpdateManager::RemoveTexture( Render::Texture* texture)
1278 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1280 // Reserve some memory inside the render queue
1281 unsigned int* 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::RemoveTexture, texture );
1287 void UpdateManager::UploadTexture( Render::Texture* texture, PixelDataPtr pixelData, const Texture::UploadParams& params )
1289 typedef MessageValue3< RenderManager, Render::Texture*, PixelDataPtr, Texture::UploadParams > DerivedType;
1291 // Reserve some memory inside the message queue
1292 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1294 // Construct message in the message queue memory; note that delete should not be called on the return value
1295 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::UploadTexture, texture, pixelData, params );
1298 void UpdateManager::GenerateMipmaps( Render::Texture* texture )
1300 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1302 // Reserve some memory inside the render queue
1303 unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1305 // Construct message in the render queue memory; note that delete should not be called on the return value
1306 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::GenerateMipmaps, texture );
1309 void UpdateManager::AddFrameBuffer( Render::FrameBuffer* frameBuffer )
1311 typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType;
1313 // Reserve some memory inside the render queue
1314 unsigned int* 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::AddFrameBuffer, frameBuffer );
1320 void UpdateManager::RemoveFrameBuffer( Render::FrameBuffer* frameBuffer)
1322 typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType;
1324 // Reserve some memory inside the render queue
1325 unsigned int* 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::RemoveFrameBuffer, frameBuffer );
1331 void UpdateManager::AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, unsigned int mipmapLevel, unsigned int layer )
1333 typedef MessageValue4< RenderManager, Render::FrameBuffer*, Render::Texture*, unsigned int, unsigned int > DerivedType;
1335 // Reserve some memory inside the render queue
1336 unsigned int* 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::AttachColorTextureToFrameBuffer, frameBuffer, texture, mipmapLevel, layer );
1342 } // namespace SceneGraph
1344 } // namespace Internal