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 for( auto root : mImpl->roots )
78 mImpl->frameCounter = 0;\
79 PrintNodeTree( *root, mSceneGraphBuffers.GetUpdateBufferIndex(), "" );\
83 mImpl->frameCounter++;
85 #define SNAPSHOT_NODE_LOGGING
88 #if defined(DEBUG_ENABLED)
89 extern Debug::Filter* gRenderTaskLogFilter;
93 using namespace Dali::Integration;
94 using Dali::Internal::Update::MessageQueue;
108 * Helper to reset animate-able objects to base values
109 * @param container to iterate over
110 * @param updateBufferIndex to use
113 inline void ResetToBaseValues( OwnerContainer<T*>& container, BufferIndex updateBufferIndex )
115 // Reset animatable properties to base values
116 // use reference to avoid extra copies of the iterator
117 for( auto&& iter : container )
119 iter->ResetToBaseValues( updateBufferIndex );
124 * Helper to Erase an object from OwnerContainer using discard queue
125 * @param container to remove from
126 * @param object to remove
127 * @param discardQueue to put the object to
128 * @param updateBufferIndex to use
131 inline void EraseUsingDiscardQueue( OwnerContainer<T*>& container, T* object, DiscardQueue& discardQueue, BufferIndex updateBufferIndex )
133 DALI_ASSERT_DEBUG( object && "NULL object not allowed" );
135 // need to use the reference version of auto as we need the pointer to the pointer for the Release call below
136 for( auto&& iter : container )
138 if ( iter == object )
140 // Transfer ownership to the discard queue, this keeps the object alive, until the render-thread has finished with it
141 discardQueue.Add( updateBufferIndex, container.Release( &iter ) ); // take the address of the reference to a pointer (iter)
142 return; // return as we only ever remove one object. Iterators to container are now invalidated as well so cannot continue
148 * Descends into node's hierarchy and sorts the children of each child according to their depth-index.
149 * @param[in] node The node whose hierarchy to descend
151 void SortSiblingNodesRecursively( Node& node )
153 NodeContainer& container = node.GetChildren();
154 std::sort( container.Begin(), container.End(),
155 []( Node* a, Node* b ) { return a->GetDepthIndex() < b->GetDepthIndex(); } );
157 // Descend tree and sort as well
158 for( auto&& iter : container )
160 SortSiblingNodesRecursively( *iter );
164 } // unnamed namespace
167 * Structure to contain UpdateManager internal data
169 struct UpdateManager::Impl
171 Impl( NotificationManager& notificationManager,
172 CompleteNotificationInterface& animationPlaylist,
173 PropertyNotifier& propertyNotifier,
174 DiscardQueue& discardQueue,
175 RenderController& renderController,
176 RenderManager& renderManager,
177 RenderQueue& renderQueue,
178 SceneGraphBuffers& sceneGraphBuffers,
179 RenderTaskProcessor& renderTaskProcessor )
180 : renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ),
181 notificationManager( notificationManager ),
183 animationPlaylist( animationPlaylist ),
184 propertyNotifier( propertyNotifier ),
186 discardQueue( discardQueue ),
187 renderController( renderController ),
188 sceneController( NULL ),
189 renderManager( renderManager ),
190 renderQueue( renderQueue ),
191 renderInstructions( renderManager.GetRenderInstructionContainer() ),
192 renderTaskProcessor( renderTaskProcessor ),
193 backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
197 panGestureProcessor( NULL ),
198 messageQueue( renderController, sceneGraphBuffers ),
199 frameCallbackProcessor( NULL ),
200 keepRenderingSeconds( 0.0f ),
201 nodeDirtyFlags( NodePropertyFlags::TRANSFORM ), // 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 for( auto taskList : taskLists )
221 RenderTaskList::RenderTaskContainer& tasks = taskList->GetTasks();
222 for ( auto&& task : tasks )
224 task->SetSourceNode( NULL );
228 // UpdateManager owns the Nodes. Although Nodes are pool allocated they contain heap allocated parts
229 // like custom properties, which get released here
230 Vector<Node*>::Iterator iter = nodes.Begin()+1;
231 Vector<Node*>::Iterator endIter = nodes.End();
232 for(;iter!=endIter;++iter)
234 (*iter)->OnDestroy();
238 for( auto root : roots )
243 delete sceneController;
247 * Lazy init for FrameCallbackProcessor.
248 * @param[in] updateManager A reference to the update-manager
250 FrameCallbackProcessor& GetFrameCallbackProcessor( UpdateManager& updateManager )
252 if( ! frameCallbackProcessor )
254 frameCallbackProcessor = new FrameCallbackProcessor( updateManager, transformManager );
256 return *frameCallbackProcessor;
259 SceneGraphBuffers sceneGraphBuffers; ///< Used to keep track of which buffers are being written or read
260 RenderMessageDispatcher renderMessageDispatcher; ///< Used for passing messages to the render-thread
261 NotificationManager& notificationManager; ///< Queues notification messages for the event-thread.
262 TransformManager transformManager; ///< Used to update the transformation matrices of the nodes
263 CompleteNotificationInterface& animationPlaylist; ///< Holds handles to all the animations
264 PropertyNotifier& propertyNotifier; ///< Provides notification to applications when properties are modified.
265 ShaderSaver* shaderSaver; ///< Saves shader binaries.
266 DiscardQueue& discardQueue; ///< Nodes are added here when disconnected from the scene-graph.
267 RenderController& renderController; ///< render controller
268 SceneControllerImpl* sceneController; ///< scene controller
269 RenderManager& renderManager; ///< This is responsible for rendering the results of each "update"
270 RenderQueue& renderQueue; ///< Used to queue messages for the next render
271 RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions
272 RenderTaskProcessor& renderTaskProcessor; ///< Handles RenderTasks and RenderInstrucitons
274 Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame.
276 OwnerContainer<RenderTaskList*> taskLists; ///< A container of scene graph render task lists
278 OwnerContainer<Layer*> roots; ///< A container of root nodes (root is a layer). The layers are not stored in the node memory pool.
280 Vector<Node*> nodes; ///< A container of all instantiated nodes
282 std::vector<SortedLayerPointers> sortedLayerLists; ///< A container of lists of Layer pointers sorted by depth (one list of sorted layers per root)
284 OwnerContainer< Camera* > cameras; ///< A container of cameras
285 OwnerContainer< PropertyOwner* > customObjects; ///< A container of owned objects (with custom properties)
287 OwnerContainer< PropertyResetterBase* > propertyResetters; ///< A container of property resetters
288 AnimationContainer animations; ///< A container of owned animations
289 PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications.
290 OwnerContainer< Renderer* > renderers; ///< A container of owned renderers
291 OwnerContainer< TextureSet* > textureSets; ///< A container of owned texture sets
292 OwnerContainer< Shader* > shaders; ///< A container of owned shaders
293 OwnerPointer< PanGesture > panGestureProcessor; ///< Owned pan gesture processor; it lives for the lifecycle of UpdateManager
295 MessageQueue messageQueue; ///< The messages queued from the event-thread
296 std::vector<Internal::ShaderDataPtr> renderCompiledShaders; ///< Shaders compiled on Render thread are inserted here for update thread to pass on to event thread.
297 std::vector<Internal::ShaderDataPtr> updateCompiledShaders; ///< Shaders to be sent from Update to Event
298 Mutex compiledShaderMutex; ///< lock to ensure no corruption on the renderCompiledShaders
300 OwnerPointer<FrameCallbackProcessor> frameCallbackProcessor; ///< Owned FrameCallbackProcessor, only created if required.
302 float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering
303 NodePropertyFlags nodeDirtyFlags; ///< cumulative node dirty flags from previous frame
304 uint32_t frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
306 DevelStage::Rendering renderingBehavior; ///< Set via DevelStage::SetRenderingBehavior
308 bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
309 bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
310 bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered
311 bool renderersAdded; ///< Flag to keep track when renderers have been added to avoid unnecessary processing
312 bool surfaceRectChanged; ///< True if the default surface rect is changed
316 Impl( const Impl& ); ///< Undefined
317 Impl& operator=( const Impl& ); ///< Undefined
320 UpdateManager::UpdateManager( NotificationManager& notificationManager,
321 CompleteNotificationInterface& animationFinishedNotifier,
322 PropertyNotifier& propertyNotifier,
323 DiscardQueue& discardQueue,
324 RenderController& controller,
325 RenderManager& renderManager,
326 RenderQueue& renderQueue,
327 RenderTaskProcessor& renderTaskProcessor )
330 mImpl = new Impl( notificationManager,
331 animationFinishedNotifier,
338 renderTaskProcessor );
342 UpdateManager::~UpdateManager()
347 void UpdateManager::InstallRoot( OwnerPointer<Layer>& layer )
349 DALI_ASSERT_DEBUG( layer->IsLayer() );
350 DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
352 Layer* rootLayer = layer.Release();
354 DALI_ASSERT_DEBUG( std::find( mImpl->roots.begin(), mImpl->roots.end(), rootLayer ) == mImpl->roots.end() && "Root Node already installed" );
356 rootLayer->CreateTransform( &mImpl->transformManager );
357 rootLayer->SetRoot(true);
358 mImpl->roots.PushBack( rootLayer );
361 void UpdateManager::AddNode( OwnerPointer<Node>& node )
363 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
365 // Nodes must be sorted by pointer
366 Node* rawNode = node.Release();
367 Vector<Node*>::Iterator begin = mImpl->nodes.Begin();
368 for( Vector<Node*>::Iterator iter = mImpl->nodes.End()-1; iter >= begin; --iter )
370 if( rawNode > (*iter) )
372 mImpl->nodes.Insert((iter+1), rawNode );
373 rawNode->CreateTransform( &mImpl->transformManager );
379 void UpdateManager::ConnectNode( Node* parent, Node* node )
381 DALI_ASSERT_ALWAYS( NULL != parent );
382 DALI_ASSERT_ALWAYS( NULL != node );
383 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
385 parent->ConnectChild( node );
387 // Inform the frame-callback-processor, if set, about the node-hierarchy changing
388 if( mImpl->frameCallbackProcessor )
390 mImpl->frameCallbackProcessor->NodeHierarchyChanged();
394 void UpdateManager::DisconnectNode( Node* node )
396 Node* parent = node->GetParent();
397 DALI_ASSERT_ALWAYS( NULL != parent );
398 parent->SetDirtyFlag( NodePropertyFlags::CHILD_DELETED ); // make parent dirty so that render items dont get reused
400 parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node );
402 // Inform the frame-callback-processor, if set, about the node-hierarchy changing
403 if( mImpl->frameCallbackProcessor )
405 mImpl->frameCallbackProcessor->NodeHierarchyChanged();
409 void UpdateManager::DestroyNode( Node* node )
411 DALI_ASSERT_ALWAYS( NULL != node );
412 DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
414 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
415 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
416 for(;iter!=endIter;++iter)
420 mImpl->nodes.Erase(iter);
425 mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
427 // Notify the Node about impending destruction
431 void UpdateManager::AddCamera( OwnerPointer< Camera >& camera )
433 mImpl->cameras.PushBack( camera.Release() ); // takes ownership
436 void UpdateManager::RemoveCamera( const Camera* camera )
438 // Find the camera and destroy it
439 EraseUsingDiscardQueue( mImpl->cameras, const_cast<Camera*>( camera ), mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
442 void UpdateManager::AddObject( OwnerPointer<PropertyOwner>& object )
444 mImpl->customObjects.PushBack( object.Release() );
447 void UpdateManager::RemoveObject( PropertyOwner* object )
449 mImpl->customObjects.EraseObject( object );
452 void UpdateManager::AddRenderTaskList( OwnerPointer<RenderTaskList>& taskList )
454 RenderTaskList* taskListPointer = taskList.Release();
455 taskListPointer->SetRenderMessageDispatcher( &mImpl->renderMessageDispatcher );
456 mImpl->taskLists.PushBack( taskListPointer );
459 void UpdateManager::RemoveRenderTaskList( RenderTaskList* taskList )
461 mImpl->taskLists.EraseObject( taskList );
464 void UpdateManager::AddAnimation( OwnerPointer< SceneGraph::Animation >& animation )
466 mImpl->animations.PushBack( animation.Release() );
469 void UpdateManager::StopAnimation( Animation* animation )
471 DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
473 bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
475 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
478 void UpdateManager::RemoveAnimation( Animation* animation )
480 DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
482 animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
484 DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
487 bool UpdateManager::IsAnimationRunning() const
489 // Find any animation that isn't stopped or paused
490 for ( auto&& iter : mImpl->animations )
492 const Animation::State state = iter->GetState();
494 if (state != Animation::Stopped &&
495 state != Animation::Paused)
497 return true; // stop iteration as soon as first one is found
504 void UpdateManager::AddPropertyResetter( OwnerPointer<PropertyResetterBase>& propertyResetter )
506 propertyResetter->Initialize();
507 mImpl->propertyResetters.PushBack( propertyResetter.Release() );
510 void UpdateManager::AddPropertyNotification( OwnerPointer< PropertyNotification >& propertyNotification )
512 mImpl->propertyNotifications.PushBack( propertyNotification.Release() );
515 void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
517 mImpl->propertyNotifications.EraseObject( propertyNotification );
520 void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
522 DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
523 propertyNotification->SetNotifyMode( notifyMode );
526 void UpdateManager::AddShader( OwnerPointer< Shader >& shader )
528 mImpl->shaders.PushBack( shader.Release() );
531 void UpdateManager::RemoveShader( Shader* shader )
533 // Find the shader and destroy it
534 EraseUsingDiscardQueue( mImpl->shaders, shader, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
537 void UpdateManager::SetShaderProgram( Shader* shader,
538 Internal::ShaderDataPtr shaderData, bool modifiesGeometry )
543 typedef MessageValue3< Shader, Internal::ShaderDataPtr, ProgramCache*, bool> DerivedType;
545 // Reserve some memory inside the render queue
546 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
548 // Construct message in the render queue memory; note that delete should not be called on the return value
549 new (slot) DerivedType( shader, &Shader::SetProgram, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
553 void UpdateManager::SaveBinary( Internal::ShaderDataPtr shaderData )
555 DALI_ASSERT_DEBUG( shaderData && "No NULL shader data pointers please." );
556 DALI_ASSERT_DEBUG( shaderData->GetBufferSize() > 0 && "Shader binary empty so nothing to save." );
558 // lock as update might be sending previously compiled shaders to event thread
559 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
560 mImpl->renderCompiledShaders.push_back( shaderData );
564 void UpdateManager::SetShaderSaver( ShaderSaver& upstream )
566 mImpl->shaderSaver = &upstream;
569 void UpdateManager::AddRenderer( OwnerPointer< Renderer >& renderer )
571 renderer->ConnectToSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
572 mImpl->renderers.PushBack( renderer.Release() );
573 mImpl->renderersAdded = true;
576 void UpdateManager::RemoveRenderer( Renderer* renderer )
578 // Find the renderer and destroy it
579 EraseUsingDiscardQueue( mImpl->renderers, renderer, mImpl->discardQueue, mSceneGraphBuffers.GetUpdateBufferIndex() );
580 // Need to remove the render object as well
581 renderer->DisconnectFromSceneGraph( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
584 void UpdateManager::SetPanGestureProcessor( PanGesture* panGestureProcessor )
586 DALI_ASSERT_DEBUG( NULL != panGestureProcessor );
588 mImpl->panGestureProcessor = panGestureProcessor;
591 void UpdateManager::AddTextureSet( OwnerPointer< TextureSet >& textureSet )
593 mImpl->textureSets.PushBack( textureSet.Release() );
596 void UpdateManager::RemoveTextureSet( TextureSet* textureSet )
598 mImpl->textureSets.EraseObject( textureSet );
601 uint32_t* UpdateManager::ReserveMessageSlot( uint32_t size, bool updateScene )
603 return mImpl->messageQueue.ReserveMessageSlot( size, updateScene );
606 void UpdateManager::EventProcessingStarted()
608 mImpl->messageQueue.EventProcessingStarted();
611 bool UpdateManager::FlushQueue()
613 return mImpl->messageQueue.FlushQueue();
616 void UpdateManager::ResetProperties( BufferIndex bufferIndex )
618 // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
619 mImpl->animationFinishedDuringUpdate = false;
621 // Reset all animating / constrained properties
622 std::vector<PropertyResetterBase*>toDelete;
623 for( auto&& element : mImpl->propertyResetters )
625 element->ResetToBaseValue( bufferIndex );
626 if( element->IsFinished() )
628 toDelete.push_back( element );
632 // If a resetter is no longer required (the animator or constraint has been removed), delete it.
633 for( auto&& elementPtr : toDelete )
635 mImpl->propertyResetters.EraseObject( elementPtr );
638 // Clear node dirty flags
639 Vector<Node*>::Iterator iter = mImpl->nodes.Begin()+1;
640 Vector<Node*>::Iterator endIter = mImpl->nodes.End();
641 for( ;iter != endIter; ++iter )
643 (*iter)->ResetDirtyFlags( bufferIndex );
647 bool UpdateManager::ProcessGestures( BufferIndex bufferIndex, uint32_t lastVSyncTimeMilliseconds, uint32_t nextVSyncTimeMilliseconds )
649 bool gestureUpdated( false );
651 if( mImpl->panGestureProcessor )
653 // gesture processor only supports default properties
654 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
655 gestureUpdated |= mImpl->panGestureProcessor->UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
658 return gestureUpdated;
661 void UpdateManager::Animate( BufferIndex bufferIndex, float elapsedSeconds )
663 AnimationContainer &animations = mImpl->animations;
664 AnimationIter iter = animations.Begin();
665 bool animationLooped = false;
667 while ( iter != animations.End() )
669 Animation* animation = *iter;
670 bool finished = false;
672 bool progressMarkerReached = false;
673 animation->Update( bufferIndex, elapsedSeconds, looped, finished, progressMarkerReached );
675 if ( progressMarkerReached )
677 mImpl->notificationManager.QueueMessage( Internal::NotifyProgressReachedMessage( mImpl->animationPlaylist, animation ) );
680 mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
681 animationLooped = animationLooped || looped;
683 // Remove animations that had been destroyed but were still waiting for an update
684 if (animation->GetState() == Animation::Destroyed)
686 iter = animations.Erase(iter);
694 // queue the notification on finished or looped (to update loop count)
695 if ( mImpl->animationFinishedDuringUpdate || animationLooped )
697 // The application should be notified by NotificationManager, in another thread
698 mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationPlaylist );
702 void UpdateManager::ConstrainCustomObjects( BufferIndex bufferIndex )
704 //Constrain custom objects (in construction order)
705 for ( auto&& object : mImpl->customObjects )
707 ConstrainPropertyOwner( *object, bufferIndex );
711 void UpdateManager::ConstrainRenderTasks( BufferIndex bufferIndex )
713 // Constrain render-tasks
714 for( auto taskList : mImpl->taskLists )
716 RenderTaskList::RenderTaskContainer& tasks = taskList->GetTasks();
717 for ( auto&& task : tasks )
719 ConstrainPropertyOwner( *task, bufferIndex );
724 void UpdateManager::ConstrainShaders( BufferIndex bufferIndex )
726 // constrain shaders... (in construction order)
727 for ( auto&& shader : mImpl->shaders )
729 ConstrainPropertyOwner( *shader, bufferIndex );
733 void UpdateManager::ProcessPropertyNotifications( BufferIndex bufferIndex )
735 for( auto&& notification : mImpl->propertyNotifications )
737 bool valid = notification->Check( bufferIndex );
740 mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
745 void UpdateManager::ForwardCompiledShadersToEventThread()
747 DALI_ASSERT_DEBUG( (mImpl->shaderSaver != 0) && "shaderSaver should be wired-up during startup." );
748 if( mImpl->shaderSaver )
750 // lock and swap the queues
752 // render might be attempting to send us more binaries at the same time
753 Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
754 mImpl->renderCompiledShaders.swap( mImpl->updateCompiledShaders );
757 if( mImpl->updateCompiledShaders.size() > 0 )
759 ShaderSaver& factory = *mImpl->shaderSaver;
760 for( auto&& shader : mImpl->updateCompiledShaders )
762 mImpl->notificationManager.QueueMessage( ShaderCompiledMessage( factory, shader ) );
764 // we don't need them in update anymore
765 mImpl->updateCompiledShaders.clear();
770 void UpdateManager::UpdateRenderers( BufferIndex bufferIndex )
772 for( auto&& renderer : mImpl->renderers )
775 ConstrainPropertyOwner( *renderer, bufferIndex );
777 renderer->PrepareRender( bufferIndex );
781 void UpdateManager::UpdateNodes( BufferIndex bufferIndex )
783 mImpl->nodeDirtyFlags = NodePropertyFlags::NOTHING;
785 for( auto&& rootLayer : mImpl->roots )
787 // Prepare resources, update shaders, for each node
788 // And add the renderers to the sorted layers. Start from root, which is also a layer
789 mImpl->nodeDirtyFlags |= UpdateNodeTree( *rootLayer,
791 mImpl->renderQueue );
795 uint32_t UpdateManager::Update( float elapsedSeconds,
796 uint32_t lastVSyncTimeMilliseconds,
797 uint32_t nextVSyncTimeMilliseconds,
798 bool renderToFboEnabled,
799 bool isRenderingToFbo )
801 const BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
803 //Clear nodes/resources which were previously discarded
804 mImpl->discardQueue.Clear( bufferIndex );
806 //Process Touches & Gestures
807 const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
809 bool updateScene = // The scene-graph requires an update if..
810 (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR
811 IsAnimationRunning() || // ..at least one animation is running OR
812 mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR
813 gestureUpdated; // ..a gesture property was updated
816 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
817 // values if the scene was updated in the previous frame.
818 if( updateScene || mImpl->previousUpdateScene )
820 //Reset properties from the previous update
821 ResetProperties( bufferIndex );
822 mImpl->transformManager.ResetToBaseValue();
825 // Process the queued scene messages. Note, MessageQueue::FlushQueue may be called
826 // between calling IsSceneUpdateRequired() above and here, so updateScene should
828 updateScene |= mImpl->messageQueue.ProcessMessages( bufferIndex );
830 //Forward compiled shader programs to event thread for saving
831 ForwardCompiledShadersToEventThread();
833 // Although the scene-graph may not require an update, we still need to synchronize double-buffered
834 // renderer lists if the scene was updated in the previous frame.
835 // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
836 if( updateScene || mImpl->previousUpdateScene )
839 Animate( bufferIndex, elapsedSeconds );
841 //Constraint custom objects
842 ConstrainCustomObjects( bufferIndex );
844 //Clear the lists of renderers from the previous update
845 for( auto sortedLayers : mImpl->sortedLayerLists )
847 for( auto&& layer : sortedLayers )
849 layer->ClearRenderables();
853 // Call the frame-callback-processor if set
854 if( mImpl->frameCallbackProcessor )
856 mImpl->frameCallbackProcessor->Update( bufferIndex, elapsedSeconds );
859 //Update node hierarchy, apply constraints and perform sorting / culling.
860 //This will populate each Layer with a list of renderers which are ready.
861 UpdateNodes( bufferIndex );
863 //Apply constraints to RenderTasks, shaders
864 ConstrainRenderTasks( bufferIndex );
865 ConstrainShaders( bufferIndex );
867 //Update renderers and apply constraints
868 UpdateRenderers( bufferIndex );
870 //Update the transformations of all the nodes
871 mImpl->transformManager.Update();
873 //Process Property Notifications
874 ProcessPropertyNotifications( bufferIndex );
877 for( auto&& cameraIterator : mImpl->cameras )
879 cameraIterator->Update( bufferIndex );
882 //Process the RenderTasks if renderers exist. This creates the instructions for rendering the next frame.
883 //reset the update buffer index and make sure there is enough room in the instruction container
884 if( mImpl->renderersAdded )
886 // Calculate how many render tasks we have in total
887 VectorBase::SizeType numberOfRenderTasks = 0;
889 const VectorBase::SizeType taskListCount = mImpl->taskLists.Count();
890 for ( VectorBase::SizeType index = 0u; index < taskListCount; index++ )
892 numberOfRenderTasks += mImpl->taskLists[index]->GetTasks().Count();
895 mImpl->renderInstructions.ResetAndReserve( bufferIndex,
896 static_cast<uint32_t>( numberOfRenderTasks ) );
898 for ( VectorBase::SizeType index = 0u; index < taskListCount; index++ )
900 if ( NULL != mImpl->roots[index] )
902 mImpl->renderTaskProcessor.Process( bufferIndex,
903 *mImpl->taskLists[index],
904 *mImpl->roots[index],
905 mImpl->sortedLayerLists[index],
906 mImpl->renderInstructions,
914 for( auto taskList : mImpl->taskLists )
916 RenderTaskList::RenderTaskContainer& tasks = taskList->GetTasks();
918 // check the countdown and notify
919 bool doRenderOnceNotify = false;
920 mImpl->renderTaskWaiting = false;
921 for ( auto&& renderTask : tasks )
923 renderTask->UpdateState();
925 if( renderTask->IsWaitingToRender() &&
926 renderTask->ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
928 mImpl->renderTaskWaiting = true; // keep update/render threads alive
931 if( renderTask->HasRendered() )
933 doRenderOnceNotify = true;
937 if( doRenderOnceNotify )
939 DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
940 mImpl->notificationManager.QueueCompleteNotification( taskList->GetCompleteNotificationInterface() );
944 // Macro is undefined in release build.
945 SNAPSHOT_NODE_LOGGING;
947 // A ResetProperties() may be required in the next frame
948 mImpl->previousUpdateScene = updateScene;
950 // Check whether further updates are required
951 uint32_t keepUpdating = KeepUpdatingCheck( elapsedSeconds );
953 // tell the update manager that we're done so the queue can be given to event thread
954 mImpl->notificationManager.UpdateCompleted();
956 // The update has finished; swap the double-buffering indices
957 mSceneGraphBuffers.Swap();
962 uint32_t UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
964 // Update the duration set via Stage::KeepRendering()
965 if ( mImpl->keepRenderingSeconds > 0.0f )
967 mImpl->keepRenderingSeconds -= elapsedSeconds;
970 uint32_t keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
972 // If the rendering behavior is set to continuously render, then continue to render.
973 // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
974 // Keep updating until no messages are received and no animations are running.
975 // If an animation has just finished, update at least once more for Discard end-actions.
976 // No need to check for renderQueue as there is always a render after update and if that
977 // render needs another update it will tell the adaptor to call update again
979 if ( ( mImpl->renderingBehavior == DevelStage::Rendering::CONTINUOUSLY ) ||
980 ( mImpl->keepRenderingSeconds > 0.0f ) )
982 keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
985 if ( IsAnimationRunning() ||
986 mImpl->animationFinishedDuringUpdate )
988 keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
991 if ( mImpl->renderTaskWaiting )
993 keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
996 return keepUpdatingRequest;
999 void UpdateManager::SetBackgroundColor( const Vector4& color )
1001 typedef MessageValue1< RenderManager, Vector4 > DerivedType;
1003 // Reserve some memory inside the render queue
1004 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1006 // Construct message in the render queue memory; note that delete should not be called on the return value
1007 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
1010 void UpdateManager::SetDefaultSurfaceRect( const Rect<int32_t>& rect )
1012 mImpl->surfaceRectChanged = true;
1014 typedef MessageValue1< RenderManager, Rect<int32_t> > DerivedType;
1016 // Reserve some memory inside the render queue
1017 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1019 // Construct message in the render queue memory; note that delete should not be called on the return value
1020 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultSurfaceRect, rect );
1023 void UpdateManager::KeepRendering( float durationSeconds )
1025 mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
1028 void UpdateManager::SetRenderingBehavior( DevelStage::Rendering renderingBehavior )
1030 mImpl->renderingBehavior = renderingBehavior;
1033 void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, const Layer* rootLayer )
1035 const VectorBase::SizeType rootCount = mImpl->roots.Count();
1037 // Make sure we reserve the correct size for the container so that
1038 // we can save the sorted layers in the same order as the root layer
1039 mImpl->sortedLayerLists.resize( rootCount );
1041 for ( VectorBase::SizeType rootIndex = 0u; rootIndex < rootCount; rootIndex++ )
1043 Layer* root = mImpl->roots[rootIndex];
1044 if ( root == rootLayer )
1046 mImpl->sortedLayerLists[rootIndex] = layers;
1052 void UpdateManager::SetDepthIndices( OwnerPointer< NodeDepths >& nodeDepths )
1054 // note,this vector is already in depth order. It could be used as-is to
1055 // remove sorting in update algorithm. However, it lacks layer boundary markers.
1056 for( auto&& iter : nodeDepths->nodeDepths )
1058 iter.node->SetDepthIndex( iter.sortedDepth );
1061 for( auto root : mImpl->roots )
1063 // Go through node hierarchy and rearrange siblings according to depth-index
1064 SortSiblingNodesRecursively( *root );
1068 bool UpdateManager::IsDefaultSurfaceRectChanged()
1070 bool surfaceRectChanged = mImpl->surfaceRectChanged;
1073 mImpl->surfaceRectChanged = false;
1075 return surfaceRectChanged;
1078 void UpdateManager::AddFrameCallback( OwnerPointer< FrameCallback >& frameCallback, const Node* rootNode )
1080 mImpl->GetFrameCallbackProcessor( *this ).AddFrameCallback( frameCallback, rootNode );
1083 void UpdateManager::RemoveFrameCallback( FrameCallbackInterface* frameCallback )
1085 mImpl->GetFrameCallbackProcessor( *this ).RemoveFrameCallback( frameCallback );
1088 void UpdateManager::AddSampler( OwnerPointer< Render::Sampler >& sampler )
1090 // Message has ownership of Sampler while in transit from update to render
1091 typedef MessageValue1< RenderManager, OwnerPointer< Render::Sampler > > DerivedType;
1093 // Reserve some memory inside the render queue
1094 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1096 // Construct message in the render queue memory; note that delete should not be called on the return value
1097 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddSampler, sampler );
1100 void UpdateManager::RemoveSampler( Render::Sampler* sampler )
1102 typedef MessageValue1< RenderManager, Render::Sampler* > DerivedType;
1104 // Reserve some memory inside the render queue
1105 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1107 // Construct message in the render queue memory; note that delete should not be called on the return value
1108 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveSampler, sampler );
1111 void UpdateManager::SetFilterMode( Render::Sampler* sampler, uint32_t minFilterMode, uint32_t magFilterMode )
1113 typedef MessageValue3< RenderManager, Render::Sampler*, uint32_t, uint32_t > DerivedType;
1115 // Reserve some memory inside the render queue
1116 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1118 // Construct message in the render queue memory; note that delete should not be called on the return value
1119 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetFilterMode, sampler, minFilterMode, magFilterMode );
1122 void UpdateManager::SetWrapMode( Render::Sampler* sampler, uint32_t rWrapMode, uint32_t sWrapMode, uint32_t tWrapMode )
1124 typedef MessageValue4< RenderManager, Render::Sampler*, uint32_t, uint32_t, uint32_t > DerivedType;
1126 // Reserve some memory inside the render queue
1127 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1129 // Construct message in the render queue memory; note that delete should not be called on the return value
1130 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetWrapMode, sampler, rWrapMode, sWrapMode, tWrapMode );
1133 void UpdateManager::AddPropertyBuffer( OwnerPointer< Render::PropertyBuffer >& propertyBuffer )
1135 // Message has ownership of format while in transit from update -> render
1136 typedef MessageValue1< RenderManager, OwnerPointer< Render::PropertyBuffer > > DerivedType;
1138 // Reserve some memory inside the render queue
1139 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1141 // Construct message in the render queue memory; note that delete should not be called on the return value
1142 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddPropertyBuffer, propertyBuffer );
1145 void UpdateManager::RemovePropertyBuffer( Render::PropertyBuffer* propertyBuffer )
1147 typedef MessageValue1< RenderManager, Render::PropertyBuffer* > DerivedType;
1149 // Reserve some memory inside the render queue
1150 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1152 // Construct message in the render queue memory; note that delete should not be called on the return value
1153 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemovePropertyBuffer, propertyBuffer );
1156 void UpdateManager::SetPropertyBufferFormat( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Render::PropertyBuffer::Format>& format )
1158 // Message has ownership of format while in transit from update -> render
1159 typedef MessageValue2< RenderManager, Render::PropertyBuffer*, OwnerPointer< Render::PropertyBuffer::Format > > DerivedType;
1161 // Reserve some memory inside the render queue
1162 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1164 // Construct message in the render queue memory; note that delete should not be called on the return value
1165 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferFormat, propertyBuffer, format );
1168 void UpdateManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffer, OwnerPointer< Vector<uint8_t> >& data, uint32_t size )
1170 // Message has ownership of format while in transit from update -> render
1171 typedef MessageValue3< RenderManager, Render::PropertyBuffer*, OwnerPointer< Dali::Vector<uint8_t> >, uint32_t > DerivedType;
1173 // Reserve some memory inside the render queue
1174 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1176 // Construct message in the render queue memory; note that delete should not be called on the return value
1177 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferData, propertyBuffer, data, size );
1180 void UpdateManager::AddGeometry( OwnerPointer< Render::Geometry >& geometry )
1182 // Message has ownership of format while in transit from update -> render
1183 typedef MessageValue1< RenderManager, OwnerPointer< Render::Geometry > > DerivedType;
1185 // Reserve some memory inside the render queue
1186 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1188 // Construct message in the render queue memory; note that delete should not be called on the return value
1189 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddGeometry, geometry );
1192 void UpdateManager::RemoveGeometry( Render::Geometry* geometry )
1194 typedef MessageValue1< RenderManager, Render::Geometry* > DerivedType;
1196 // Reserve some memory inside the render queue
1197 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1199 // Construct message in the render queue memory; note that delete should not be called on the return value
1200 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveGeometry, geometry );
1203 void UpdateManager::SetGeometryType( Render::Geometry* geometry, uint32_t geometryType )
1205 typedef MessageValue2< RenderManager, Render::Geometry*, uint32_t > DerivedType;
1207 // Reserve some memory inside the render queue
1208 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1210 // Construct message in the render queue memory; note that delete should not be called on the return value
1211 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetGeometryType, geometry, geometryType );
1214 void UpdateManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector<uint16_t>& indices )
1216 typedef IndexBufferMessage< RenderManager > DerivedType;
1218 // Reserve some memory inside the render queue
1219 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1221 // Construct message in the render queue memory; note that delete should not be called on the return value
1222 new (slot) DerivedType( &mImpl->renderManager, geometry, indices );
1225 void UpdateManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1227 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1229 // Reserve some memory inside the render queue
1230 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1232 // Construct message in the render queue memory; note that delete should not be called on the return value
1233 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveVertexBuffer, geometry, propertyBuffer );
1236 void UpdateManager::AttachVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer )
1238 typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType;
1240 // Reserve some memory inside the render queue
1241 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1243 // Construct message in the render queue memory; note that delete should not be called on the return value
1244 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AttachVertexBuffer, geometry, propertyBuffer );
1247 void UpdateManager::AddTexture( OwnerPointer< Render::Texture >& texture )
1249 // Message has ownership of Texture while in transit from update -> render
1250 typedef MessageValue1< RenderManager, OwnerPointer< Render::Texture > > DerivedType;
1252 // Reserve some memory inside the render queue
1253 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1255 // Construct message in the render queue memory; note that delete should not be called on the return value
1256 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddTexture, texture );
1259 void UpdateManager::RemoveTexture( Render::Texture* texture)
1261 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1263 // Reserve some memory inside the render queue
1264 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1266 // Construct message in the render queue memory; note that delete should not be called on the return value
1267 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveTexture, texture );
1270 void UpdateManager::UploadTexture( Render::Texture* texture, PixelDataPtr pixelData, const Texture::UploadParams& params )
1272 typedef MessageValue3< RenderManager, Render::Texture*, PixelDataPtr, Texture::UploadParams > DerivedType;
1274 // Reserve some memory inside the message queue
1275 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1277 // Construct message in the message queue memory; note that delete should not be called on the return value
1278 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::UploadTexture, texture, pixelData, params );
1281 void UpdateManager::GenerateMipmaps( Render::Texture* texture )
1283 typedef MessageValue1< RenderManager, Render::Texture* > DerivedType;
1285 // Reserve some memory inside the render queue
1286 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1288 // Construct message in the render queue memory; note that delete should not be called on the return value
1289 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::GenerateMipmaps, texture );
1292 void UpdateManager::AddFrameBuffer( Render::FrameBuffer* frameBuffer )
1294 typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType;
1296 // Reserve some memory inside the render queue
1297 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1299 // Construct message in the render queue memory; note that delete should not be called on the return value
1300 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddFrameBuffer, frameBuffer );
1303 void UpdateManager::RemoveFrameBuffer( Render::FrameBuffer* frameBuffer)
1305 typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType;
1307 // Reserve some memory inside the render queue
1308 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1310 // Construct message in the render queue memory; note that delete should not be called on the return value
1311 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveFrameBuffer, frameBuffer );
1314 void UpdateManager::AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel, uint32_t layer )
1316 typedef MessageValue4< RenderManager, Render::FrameBuffer*, Render::Texture*, uint32_t, uint32_t > DerivedType;
1318 // Reserve some memory inside the render queue
1319 uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
1321 // Construct message in the render queue memory; note that delete should not be called on the return value
1322 new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AttachColorTextureToFrameBuffer, frameBuffer, texture, mipmapLevel, layer );
1325 } // namespace SceneGraph
1327 } // namespace Internal